/* ; Project: Open Vehicle Monitor System ; Date: 14th March 2017 ; ; Changes: ; 1.0 Initial release ; ; (C) 2011 Michael Stegen / Stegen Electronics ; (C) 2011-2017 Mark Webb-Johnson ; (C) 2011 Sonny Chen @ EPRO/DX ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal ; in the Software without restriction, including without limitation the rights ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ; copies of the Software, and to permit persons to whom the Software is ; furnished to do so, subject to the following conditions: ; ; The above copyright notice and this permission notice shall be included in ; all copies or substantial portions of the Software. ; ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ; THE SOFTWARE. */ #include "ovms_log.h" static const char *TAG = "script"; #include #include #include #include #include #include #include #include "ovms_malloc.h" #include "ovms_module.h" #include "ovms_script.h" #include "ovms_config.h" #include "ovms_command.h" #include "ovms_events.h" #include "console_async.h" #include "buffered_shell.h" #include "ovms_netmanager.h" #include "ovms_boot.h" #include "ovms_peripherals.h" #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE #include "ovms_duktape.h" static void script_reload(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv) { writer->puts("Reloading javascript engine"); MyDuktape.DuktapeReload(); } static void script_eval(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv) { MyDuktape.DuktapeEvalNoResult(argv[0], writer); } static void script_compact(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv) { writer->puts("Compacting javascript memory"); MyDuktape.DuktapeCompact(); } static void script_meminfo(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv) { MyDuktape.DuktapeEvalNoResult("JSON.print(meminfo())", writer); } #endif // #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE OvmsScripts MyScripts __attribute__ ((init_priority (1600))); static void script_ovms(int verbosity, OvmsWriter* writer, const char* spath, FILE* sf, bool secure=false) { char *ext = rindex(spath, '.'); if ((ext != NULL)&&(strcmp(ext,".js")==0)) { // Javascript script #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE fseek(sf,0,SEEK_END); long slen = ftell(sf); fseek(sf,0,SEEK_SET); char *script = new char[slen+1]; memset(script,0,slen+1); fread(script,1,slen,sf); MyDuktape.NotifyDuktapeModuleLoad(spath); MyDuktape.DuktapeEvalNoResult(script, writer, spath); MyDuktape.NotifyDuktapeModuleUnload(spath); delete [] script; #else // #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE if (writer) { writer->puts("Error: No javascript engine available"); } else { ESP_LOGE(TAG, "Error: No javascript engine available"); } #endif // #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE fclose(sf); } else { // Default: OVMS command script BufferedShell* bs = new BufferedShell(false, verbosity); if (secure) bs->SetSecure(true); char* cmdline = new char[_COMMAND_LINE_LEN]; while(fgets(cmdline, _COMMAND_LINE_LEN, sf) != NULL ) { bs->ProcessChars(cmdline, strlen(cmdline)); if (strlen(cmdline) > 0 && cmdline[strlen(cmdline)-1] != '\n') bs->ProcessChar('\n'); } fclose(sf); if (writer) { bs->Output(writer); } else { extram::string output; bs->Dump(output); ESP_LOGI(TAG, "%s", output.c_str()); } delete bs; delete [] cmdline; } } static void script_run(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv) { FILE *sf = NULL; std::string path; if (argv[0][0] == '/') { // A direct path specification path = std::string(argv[0]); sf = fopen(argv[0], "r"); } else { #ifdef CONFIG_OVMS_DEV_SDCARDSCRIPTS path = std::string("/sd/scripts/"); path.append(argv[0]); sf = fopen(path.c_str(), "r"); #endif // #ifdef CONFIG_OVMS_DEV_SDCARDSCRIPTS if (sf == NULL) { path = std::string("/store/scripts/"); path.append(argv[0]); sf = fopen(path.c_str(), "r"); } } if (sf == NULL) { writer->puts("Error: Script not found"); return; } script_ovms(verbosity, writer, path.c_str(), sf, writer->IsSecure()); } void OvmsScripts::AllScripts(std::string path) { DIR *dir; struct dirent *dp; FILE *sf; std::set files; // read dir, sort scripts by name: if ((dir = opendir (path.c_str())) != NULL) { while ((dp = readdir (dir)) != NULL) { std::string fpath = path; fpath.append("/"); fpath.append(dp->d_name); files.insert(fpath); } closedir(dir); } // execute scripts: for (auto it = files.begin(); it != files.end(); it++) { std::string fpath = *it; sf = fopen(fpath.c_str(), "r"); if (sf) { ESP_LOGI(TAG, "Running script %s", fpath.c_str()); script_ovms(COMMAND_RESULT_MINIMAL, NULL, fpath.c_str(), sf, true); // script_ovms() closes sf } } } void OvmsScripts::EventScript(std::string event, void* data) { std::string path; #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE MyDuktape.EventScript(event, data); #endif // #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE #ifdef CONFIG_OVMS_DEV_SDCARDSCRIPTS // run event scripts on external storage: path=std::string("/sd/events/"); path.append(event); AllScripts(path); #endif // #ifdef CONFIG_OVMS_DEV_SDCARDSCRIPTS // run event scripts on internal storage: path=std::string("/store/events/"); path.append(event); AllScripts(path); } OvmsScripts::OvmsScripts() { ESP_LOGI(TAG, "Initialising SCRIPTS (1600)"); #ifdef CONFIG_OVMS_SC_JAVASCRIPT_NONE ESP_LOGI(TAG, "No javascript engines enabled (command scripting only)"); #endif //#ifdef CONFIG_OVMS_SC_JAVASCRIPT_NONE OvmsCommand* cmd_script = MyCommandApp.RegisterCommand("script","SCRIPT framework"); cmd_script->RegisterCommand("run","Run a script",script_run,"",1,1); #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE cmd_script->RegisterCommand("reload","Reload javascript framework",script_reload); cmd_script->RegisterCommand("eval","Eval some javascript code",script_eval,"",1,1); cmd_script->RegisterCommand("compact","Compact javascript heap",script_compact); cmd_script->RegisterCommand("meminfo","Show heap memory status",script_meminfo); #endif // #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE MyCommandApp.RegisterCommand(".","Run a script",script_run,"",1,1); } OvmsScripts::~OvmsScripts() { }