diff --git a/components/script/CMakeLists.txt b/components/script/CMakeLists.txt index 79eb010..238b8bb 100644 --- a/components/script/CMakeLists.txt +++ b/components/script/CMakeLists.txt @@ -41,7 +41,6 @@ set(srcs "src/l_aux_lib.c" "src/l_board_config_lib.c" "src/l_serial_lib.c" - "src/l_modbus_lib.c" ) idf_component_register(SRC_DIRS "src" "lib/lua" "lib/yaml/src" diff --git a/components/script/src/l_component.c b/components/script/src/l_component.c index 479b808..1b71697 100644 --- a/components/script/src/l_component.c +++ b/components/script/src/l_component.c @@ -115,47 +115,44 @@ static void l_process_params(lua_State* L, component_param_list_t* param_list) lua_remove(L, -2); } -static void component_process_params(lua_State* L, component_entry_t* component_entry) +static void component_process_params(lua_State* L, component_entry_t* component) { - luaL_unref(L, LUA_REGISTRYINDEX, component_entry->params_ref); + luaL_unref(L, LUA_REGISTRYINDEX, component->params_ref); - component_param_list_t* param_list = component_params_read(component_entry->id); + component_param_list_t* param_list = component_params_read(component->id); - lua_rawgeti(L, LUA_REGISTRYINDEX, component_entry->params_def_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, component->params_def_ref); l_process_params(L, param_list); - component_entry->params_ref = luaL_ref(L, LUA_REGISTRYINDEX); + component->params_ref = luaL_ref(L, LUA_REGISTRYINDEX); if (param_list) component_params_free(param_list); } -static void component_restart_coroutine(lua_State* L, component_entry_t* component_entry) +static void component_restart_coroutine(lua_State* L, component_entry_t* component) { // end previous coroutine - lua_rawgeti(L, LUA_REGISTRYINDEX, component_entry->coroutine_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, component->coroutine_ref); if (lua_isthread(L, -1)) { lua_State* co = lua_tothread(L, -1); if (lua_status(co) == LUA_YIELD) { - int nresults = 0; - lua_pushboolean(co, false); - int status = lua_resume(co, L, 1, &nresults); - lua_pop(co, nresults); - - if (status == LUA_YIELD) { - ESP_LOGI(TAG, "Coroutine not stop itself"); - lua_closethread(L, co); - } + lua_closethread(L, co); + } else { + lua_pop(L, 1); } + } else { + lua_pop(L, 1); } - lua_pop(L, 1); - luaL_unref(L, LUA_REGISTRYINDEX, component_entry->coroutine_ref); - component_entry->coroutine_ref = LUA_NOREF; - component_entry->resume_after = 0; + luaL_unref(L, LUA_REGISTRYINDEX, component->coroutine_ref); + component->coroutine_ref = LUA_NOREF; + component->resume_after = 0; + + lua_gc(L, LUA_GCCOLLECT, 0); // start new coroutine - lua_rawgeti(L, LUA_REGISTRYINDEX, component_entry->start_ref); - lua_rawgeti(L, LUA_REGISTRYINDEX, component_entry->params_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, component->start_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, component->params_ref); if (lua_pcall(L, 1, 1, 0) != LUA_OK) { const char* err = lua_tostring(L, -1); lua_writestring(err, strlen(err)); @@ -163,7 +160,7 @@ static void component_restart_coroutine(lua_State* L, component_entry_t* compone lua_pop(L, 1); } else { if (lua_isthread(L, -1)) { - component_entry->coroutine_ref = luaL_ref(L, LUA_REGISTRYINDEX); + component->coroutine_ref = luaL_ref(L, LUA_REGISTRYINDEX); } else { lua_pop(L, 1); } @@ -202,28 +199,28 @@ static int l_add_component(lua_State* L) lua_pop(L, 1); component_list_t* component_list = get_component_list(L); - component_entry_t* component_entry; - SLIST_FOREACH (component_entry, component_list, entries) { - if (strcmp(id, component_entry->id) == 0) { + component_entry_t* component; + SLIST_FOREACH (component, component_list, entries) { + if (strcmp(id, component->id) == 0) { luaL_argerror(L, 1, "component with duplicate id"); } } - component_entry = (component_entry_t*)malloc(sizeof(component_entry_t)); - component_entry->id = strdup(id); - component_entry->name = strdup(name); - component_entry->description = description ? strdup(description) : NULL; + component = (component_entry_t*)malloc(sizeof(component_entry_t)); + component->id = strdup(id); + component->name = strdup(name); + component->description = description ? strdup(description) : NULL; lua_getfield(L, 1, "params"); - component_entry->params_def_ref = luaL_ref(L, LUA_REGISTRYINDEX); + component->params_def_ref = luaL_ref(L, LUA_REGISTRYINDEX); lua_getfield(L, 1, "start"); - component_entry->start_ref = luaL_ref(L, LUA_REGISTRYINDEX); - component_entry->params_ref = LUA_NOREF; - component_entry->coroutine_ref = LUA_NOREF; + component->start_ref = luaL_ref(L, LUA_REGISTRYINDEX); + component->params_ref = LUA_NOREF; + component->coroutine_ref = LUA_NOREF; - component_process_params(L, component_entry); - component_restart_coroutine(L, component_entry); + component_process_params(L, component); + component_restart_coroutine(L, component); - SLIST_INSERT_HEAD(component_list, component_entry, entries); + SLIST_INSERT_HEAD(component_list, component, entries); return 0; } @@ -262,20 +259,19 @@ void l_component_register(lua_State* L) components_ref = luaL_ref(L, LUA_REGISTRYINDEX); } -void l_component_resume(lua_State* L, bool finalize) +void l_component_resume(lua_State* L) { component_list_t* component_list = get_component_list(L); component_entry_t* component; SLIST_FOREACH (component, component_list, entries) { - if (finalize || component->resume_after == 0 || component->resume_after < xTaskGetTickCount()) { + if (component->resume_after == 0 || component->resume_after < xTaskGetTickCount()) { lua_rawgeti(L, LUA_REGISTRYINDEX, component->coroutine_ref); if (lua_isthread(L, -1)) { lua_State* co = lua_tothread(L, -1); int status = lua_status(co); if (status == LUA_YIELD || status == LUA_OK) { int nresults = 0; - lua_pushboolean(co, !finalize); - status = lua_resume(co, L, 1, &nresults); + status = lua_resume(co, L, 0, &nresults); if (status == LUA_YIELD || status == LUA_OK) { if (nresults > 0 && lua_isinteger(co, -nresults)) { component->resume_after = xTaskGetTickCount() + pdMS_TO_TICKS(lua_tointeger(co, -nresults)); diff --git a/components/script/src/l_component.h b/components/script/src/l_component.h index 2a23ba1..66adc7d 100644 --- a/components/script/src/l_component.h +++ b/components/script/src/l_component.h @@ -8,7 +8,7 @@ void l_component_register(lua_State* L); -void l_component_resume(lua_State* L, bool finalize); +void l_component_resume(lua_State* L); script_component_list_t* l_component_get_components(lua_State* L); diff --git a/components/script/src/l_modbus_lib.c b/components/script/src/l_modbus_lib.c deleted file mode 100644 index b94f997..0000000 --- a/components/script/src/l_modbus_lib.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "l_modbus_lib.h" - -#include - -#include "lauxlib.h" -#include "lua.h" - -#define BUF_SIZE 256 - -// @todo - -// static const char* TAG = "l_modbus"; - -// static int l_get_available(lua_State* L) -// { - -// return 0; -// } - -// static int l_read(lua_State* L) -// { - -// return 0; -// } - -// static int l_write(lua_State* L) -// { - -// return 0; -// } - -static const luaL_Reg lib[] = { - // { "getavailable", l_get_available }, - { NULL, NULL }, -}; - -int luaopen_modbus(lua_State* L) -{ - luaL_newlib(L, lib); - - return 1; -} diff --git a/components/script/src/l_modbus_lib.h b/components/script/src/l_modbus_lib.h deleted file mode 100644 index dcaac4a..0000000 --- a/components/script/src/l_modbus_lib.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef L_MODBUS_LIB_H_ -#define L_MODBUS_LIB_H_ - -#include "lua.h" - -int luaopen_modbus(lua_State* L); - -#endif /* L_MODBUS_LIB_H_ */ diff --git a/components/script/src/l_serial_lib.c b/components/script/src/l_serial_lib.c index 67c0617..451b071 100644 --- a/components/script/src/l_serial_lib.c +++ b/components/script/src/l_serial_lib.c @@ -8,24 +8,33 @@ #define BUF_SIZE 256 -// static const char* TAG = "l_serial"; +static const char* TAG = "l_serial"; -static int l_get_available(lua_State* L) +static bool is_opened; + +static int l_open(lua_State* L) { - lua_pushboolean(L, serial_script_is_available()); + ESP_LOGW(TAG, "l_open"); + + if (!serial_script_is_available() || is_opened) { + lua_pushnil(L); + } else { + is_opened = true; + lua_newtable(L); + luaL_setmetatable(L, "serial.port"); + } + return 1; } -static int l_read(lua_State* L) +static int l_port_read(lua_State* L) { + ESP_LOGW(TAG, "l_port_read"); + char buf[BUF_SIZE]; size_t len = BUF_SIZE; - uint32_t timeout = 0; - if (!lua_isnoneornil(L, 1)) { - timeout = luaL_checkinteger(L, 1); - } - if (serial_script_read(buf, &len, timeout) != ESP_OK) { + if (serial_script_read(buf, &len) != ESP_OK) { luaL_error(L, "serial error"); } @@ -38,38 +47,82 @@ static int l_read(lua_State* L) return 1; } -static int l_write(lua_State* L) +static int l_port_write(lua_State* L) { + ESP_LOGW(TAG, "l_port_write"); + size_t len; const char* buf; char buf_num; - if (lua_isnumber(L, 1)) { - buf_num = lua_tonumber(L, 1); + if (lua_isnumber(L, 2)) { + buf_num = lua_tonumber(L, 2); len = 1; buf = &buf_num; - } else if (lua_isstring(L, 1)) { - buf = lua_tolstring(L, 1, &len); + } else if (lua_isstring(L, 2)) { + buf = lua_tolstring(L, 2, &len); } else { - luaL_error(L, "argument must be number or string"); + luaL_argerror(L, 2, "argument must be number or string"); return 0; } - serial_script_write(buf, len); + if (serial_script_write(buf, len) != ESP_OK) { + luaL_error(L, "serial error"); + } + + return 0; +} + +static int l_port_flush(lua_State* L) +{ + ESP_LOGW(TAG, "l_port_flush"); + + if (serial_script_flush() != ESP_OK) { + luaL_error(L, "serial error"); + } + + return 0; +} + +static int l_port_gc(lua_State* L) +{ + ESP_LOGW(TAG, "l_port_gc"); + + is_opened = false; return 0; } static const luaL_Reg lib[] = { - { "getavailable", l_get_available }, - { "read", l_read }, - { "write", l_write }, + { "open", l_open }, + { NULL, NULL }, +}; + +static const luaL_Reg port_fields[] = { + { "write", l_port_write }, + { "read", l_port_read }, + { "flush", l_port_flush }, + { NULL, NULL }, +}; + +static const luaL_Reg port_metadata[] = { + { "__index", NULL }, + { "__gc", l_port_gc }, { NULL, NULL }, }; int luaopen_serial(lua_State* L) { + is_opened = false; + luaL_newlib(L, lib); + luaL_newmetatable(L, "serial.port"); + luaL_setfuncs(L, port_metadata, 0); + luaL_newlibtable(L, port_fields); + luaL_setfuncs(L, port_fields, 0); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + return 1; } diff --git a/components/script/src/script.c b/components/script/src/script.c index 4d52ea8..9ede294 100644 --- a/components/script/src/script.c +++ b/components/script/src/script.c @@ -14,7 +14,6 @@ #include "l_component.h" #include "l_evse_lib.h" #include "l_json_lib.h" -#include "l_modbus_lib.h" #include "l_mqtt_lib.h" #include "l_serial_lib.h" #include "lauxlib.h" @@ -25,9 +24,7 @@ #include "script_utils.h" #include "script_watchdog.h" -#define START_TIMEOUT 10000 #define SHUTDOWN_TIMEOUT 1000 -#define HEARTBEAT_THRESHOLD 5 #define OUTPUT_BUFFER_SIZE 4096 #define NVS_NAMESPACE "script" @@ -83,9 +80,6 @@ static void script_task_func(void* param) luaL_requiref(L, "serial", luaopen_serial, 0); lua_pop(L, 1); - luaL_requiref(L, "modbus", luaopen_modbus, 0); - lua_pop(L, 1); - lua_gc(L, LUA_GCSETPAUSE, 110); lua_gc(L, LUA_GCSETSTEPMUL, 200); @@ -108,7 +102,7 @@ static void script_task_func(void* param) } xSemaphoreTake(script_mutex, portMAX_DELAY); script_watchdog_reset(); - l_component_resume(L, false); + l_component_resume(L); xSemaphoreGive(script_mutex); int top = lua_gettop(L); @@ -119,8 +113,6 @@ static void script_task_func(void* param) vTaskDelay(pdMS_TO_TICKS(50)); } - l_component_resume(L, true); - lua_close(L); L = NULL; diff --git a/components/serial/include/serial_script.h b/components/serial/include/serial_script.h index 3c76c17..37dcd2e 100644 --- a/components/serial/include/serial_script.h +++ b/components/serial/include/serial_script.h @@ -25,6 +25,8 @@ bool serial_script_is_available(void); esp_err_t serial_script_write(const char *buf, size_t len); -esp_err_t serial_script_read(char *buf, size_t *len, uint32_t timeout); +esp_err_t serial_script_read(char *buf, size_t *len); + +esp_err_t serial_script_flush(void); #endif /* SERIAL_SCRIPT_H_ */ diff --git a/components/serial/src/serial_script.c b/components/serial/src/serial_script.c index 2996eee..efc3b06 100644 --- a/components/serial/src/serial_script.c +++ b/components/serial/src/serial_script.c @@ -1,10 +1,10 @@ #include "serial_script.h" -#include #include #define BUF_SIZE 256 #define EVENT_QUEUE_SIZE 20 +#define VFS_PATH "/dev/serial" static const char* TAG = "serial_script"; @@ -35,7 +35,7 @@ void serial_script_start(uart_port_t uart_num, uint32_t baud_rate, uart_word_len ESP_LOGE(TAG, "uart_driver_install() returned 0x%x", err); return; } - uart_vfs_dev_use_driver(uart_num); + port = uart_num; if (rs485) { @@ -81,14 +81,26 @@ esp_err_t serial_script_write(const char* buf, size_t len) return ESP_OK; } -esp_err_t serial_script_read(char* buf, size_t* len, uint32_t timeout) +esp_err_t serial_script_flush(void) +{ + if (port == -1) { + ESP_LOGW(TAG, "No script serial available"); + return ESP_ERR_NOT_FOUND; + } + + uart_flush(port); + + return ESP_OK; +} + +esp_err_t serial_script_read(char* buf, size_t* len) { if (port == -1) { ESP_LOGW(TAG, "No script serial available"); return ESP_ERR_NOT_FOUND; } - *len = uart_read_bytes(port, buf, *len, pdMS_TO_TICKS(timeout)); + *len = uart_read_bytes(port, buf, *len, 0); return ESP_OK; } \ No newline at end of file diff --git a/test_app/main/component1.lua b/test_app/main/component1.lua index 944a7c5..90145c0 100644 --- a/test_app/main/component1.lua +++ b/test_app/main/component1.lua @@ -23,13 +23,12 @@ addcomponent({ paramnumber1 = tostring(params.number1) paramboolean1 = tostring(params.boolean1) return coroutine.create(function() - stage = "begin" local counter = 1 - while coroutine.yield(1000) do + while true do stage = "loop" .. counter counter = counter + 1 + coroutine.yield(1000) end - stage = "end" end) end }) diff --git a/test_app/main/main.c b/test_app/main/main.c index c9f3e22..6bcb169 100644 --- a/test_app/main/main.c +++ b/test_app/main/main.c @@ -15,7 +15,7 @@ static void run_all_tests(void) { - // RUN_TEST_GROUP(evse); + RUN_TEST_GROUP(evse); RUN_TEST_GROUP(script); } diff --git a/test_app/main/test_script.c b/test_app/main/test_script.c index 8024861..b4c575d 100644 --- a/test_app/main/test_script.c +++ b/test_app/main/test_script.c @@ -265,29 +265,29 @@ TEST(script, component) script_component_params_free(component_params); // test yield/resume - l_component_resume(L, false); - TEST_ASSERT_EQUAL_STRING("begin", get_global_var("stage")); + l_component_resume(L); + TEST_ASSERT_EQUAL_STRING("loop1", get_global_var("stage")); - vTaskStepTick(pdMS_TO_TICKS(1100)); - l_component_resume(L, false); + l_component_resume(L); TEST_ASSERT_EQUAL_STRING("loop1", get_global_var("stage")); vTaskStepTick(pdMS_TO_TICKS(1100)); - l_component_resume(L, false); + l_component_resume(L); TEST_ASSERT_EQUAL_STRING("loop2", get_global_var("stage")); + vTaskStepTick(pdMS_TO_TICKS(1100)); + l_component_resume(L); + TEST_ASSERT_EQUAL_STRING("loop3", get_global_var("stage")); + l_component_restart(L, "component1"); TEST_ASSERT_EQUAL_STRING("start", get_global_var("stage")); - l_component_resume(L, false); - TEST_ASSERT_EQUAL_STRING("begin", get_global_var("stage")); - - vTaskStepTick(pdMS_TO_TICKS(1100)); - l_component_resume(L, false); + l_component_resume(L); TEST_ASSERT_EQUAL_STRING("loop1", get_global_var("stage")); - l_component_resume(L, true); - TEST_ASSERT_EQUAL_STRING("end", get_global_var("stage")); + vTaskStepTick(pdMS_TO_TICKS(1100)); + l_component_resume(L); + TEST_ASSERT_EQUAL_STRING("loop2", get_global_var("stage")); TEST_ASSERT_EQUAL(0, lua_gettop(L)); // after all Lua stack should be empty } @@ -452,10 +452,10 @@ TEST(script, json) TEST_GROUP_RUNNER(script) { - // RUN_TEST_CASE(script, watchdog); + RUN_TEST_CASE(script, watchdog); RUN_TEST_CASE(script, component); - // RUN_TEST_CASE(script, component_params); - // RUN_TEST_CASE(script, evse); - // RUN_TEST_CASE(script, board_config) - // RUN_TEST_CASE(script, json); + RUN_TEST_CASE(script, component_params); + RUN_TEST_CASE(script, evse); + RUN_TEST_CASE(script, board_config) + RUN_TEST_CASE(script, json); } \ No newline at end of file