From 4ec2b111eb583580e3c7bc0b2b54acbffbfc4090 Mon Sep 17 00:00:00 2001 From: bogd Date: Tue, 10 Oct 2023 12:24:11 +0200 Subject: [PATCH] implemented cron and command expressions --- CMakeLists.txt | 1 + include/CronTimers.h | 4 +++ include/SysConfiguration.h | 5 +++ src/CommandProcSys.c | 4 +-- src/CronTimers.c | 37 ++++++++++++++------ src/RestApiHandler.c | 71 +++++++++++++++++++++++++++++++++++++- src/SNTP.c | 4 +++ src/SysConfiguration.c | 19 ++++++++++ 8 files changed, 131 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba3fb22..3366f93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ idf_component_register( "src/ETHTransport.c" "src/SNTP.c" "src/MQTT.c" + "src/CronTimers.c" src/OTA.c src/RestApiHandler.c src/SysComm.c diff --git a/include/CronTimers.h b/include/CronTimers.h index b2c0575..83034b7 100644 --- a/include/CronTimers.h +++ b/include/CronTimers.h @@ -30,6 +30,7 @@ #define TIMER_NAME_LENGTH (16) #define TIMER_CRONSTRING_LENGTH (32) #define CRON_EXPRESS_MAX_LENGTH (128) +#define TIMER_EXECSTRING_LENGTH (64) #define CRON_OBJECTS_NUMBER (16) #define CRON_OBJECT_NAME_LENGTH (16) @@ -53,6 +54,7 @@ typedef struct int obj; /*!< Index of object scheduler affected on */ int act; /*!< Index of action with the object*/ char cron[TIMER_CRONSTRING_LENGTH]; /*!< Cron expression */ + char exec[TIMER_EXECSTRING_LENGTH]; /*!< Cron command string */ } cron_timer_t; @@ -66,6 +68,8 @@ char* GetCronObjectName(int idx); char* GetCronActionName(int idx); char* GetCronActAvail(int idx); +void TimeObtainHandler(struct timeval *tm); + /** * \brief Handle all actions under all objects * \param obj Index of the object diff --git a/include/SysConfiguration.h b/include/SysConfiguration.h index 55dcee3..0343d91 100644 --- a/include/SysConfiguration.h +++ b/include/SysConfiguration.h @@ -28,6 +28,7 @@ #include #include "esp_netif.h" #include "sdkconfig.h" +#include "CronTimers.h" typedef enum { @@ -209,6 +210,10 @@ typedef struct } modbusSettings; + cron_timer_t Timers[16]; + cron_obj_t CronObjects[16]; + + } SYS_CONFIG; esp_err_t ReadNVSSysConfig(SYS_CONFIG *SysConf); diff --git a/src/CommandProcSys.c b/src/CommandProcSys.c index 875685a..814b7a9 100644 --- a/src/CommandProcSys.c +++ b/src/CommandProcSys.c @@ -48,11 +48,11 @@ void regCustomExecCommand(int (*custom_exec)(char *cmd)) static void SYSTEM_TEST_handle(char *obj, char *com, char *arg) { - ESP_LOGI(TAG, "INPUTS handler command %s with argument %s", com, arg); + ESP_LOGI(TAG, "Object:%s, Command:%s, Argument %s",obj, com, arg); } static void SYSTEM_REBOOT_handle(char *obj, char *com, char *arg) { - ESP_LOGI(TAG, "SYSTEM handler command %s with argument %s", com, arg); + ESP_LOGI(TAG, "Object:%s, Command:%s, Argument %s",obj, com, arg); } typedef struct diff --git a/src/CronTimers.c b/src/CronTimers.c index 7e80978..8da869e 100644 --- a/src/CronTimers.c +++ b/src/CronTimers.c @@ -19,6 +19,18 @@ * Description: */ +//{ +// "data":{ +// "msgid":123456789, +// "time":"2023-06-03T12:25:24+00:00", +// "msgtype":1,"payloadtype":1, "payload":{"applytype":1, +// "variables":{ +// "cronrecs":[{ "num": 1, "del": 0, "enab": 1, "prev": 0, "name": "Timer Name", "obj": 0, "act": 0, +// "cron": "*/3 * * * * *", +// "exec": "OUTPUTS,TEST,ARGUMENTS" +// }] +// }}},"signature":"6a11b872e8f766673eb82e127b6918a0dc96a42c5c9d184604f9787f3d27bcef"} + #include #include "esp_log.h" #include "webguiapp.h" @@ -59,7 +71,7 @@ char* GetCronObjectName(int idx) { if(idx < 0 || idx >= sizeof(cron_objects)/sizeof(char*)) return ""; - return GetAppConf()->CronObjects[idx].objname; + return GetSysConf()->CronObjects[idx].objname; } char* GetCronActionName(int idx) @@ -99,6 +111,8 @@ void custom_cron_execute(int obj, int act) void custom_cron_job_callback(cron_job *job) { + ExecCommand(((cron_timer_t*) job->data)->exec); + /* int act = ((cron_timer_t*) job->data)->act; int obj = ((cron_timer_t*) job->data)->obj; char *name = ((cron_timer_t*) job->data)->name; @@ -109,6 +123,7 @@ void custom_cron_job_callback(cron_job *job) LogFile("cron.log", "Executed sheduler with action %u under object %u", act, obj); custom_cron_execute(obj, act); return; + */ } esp_err_t InitCronSheduler() @@ -140,18 +155,18 @@ static void ExecuteLastAction() for (shdl = 0; shdl < CRON_TIMERS_NUMBER; shdl++) { - if (GetAppConf()->Timers[shdl].enab && - !GetAppConf()->Timers[shdl].del && - GetAppConf()->Timers[shdl].prev && - GetAppConf()->Timers[shdl].obj == obj) + if (GetSysConf()->Timers[shdl].enab && + !GetSysConf()->Timers[shdl].del && + GetSysConf()->Timers[shdl].prev && + GetSysConf()->Timers[shdl].obj == obj) { cron_expr cron_exp = { 0 }; - cron_parse_expr(GetAppConf()->Timers[shdl].cron, &cron_exp, NULL); + cron_parse_expr(GetSysConf()->Timers[shdl].cron, &cron_exp, NULL); time_t prev = cron_prev(&cron_exp, now); if ((now - prev) < delta) { delta = (now - prev); - act = GetAppConf()->Timers[shdl].act; + act = GetSysConf()->Timers[shdl].act; } } } @@ -187,7 +202,7 @@ esp_err_t ReloadCronSheduler() bool isExpressError = false; for (int i = 0; i < CRON_TIMERS_NUMBER; i++) { - const char *err = check_expr(GetAppConf()->Timers[i].cron); + const char *err = check_expr(GetSysConf()->Timers[i].cron); if (err) { snprintf(cron_express_error, CRON_EXPRESS_MAX_LENGTH - 1, "In timer %d expression error:%s", i + 1, err); @@ -195,10 +210,10 @@ esp_err_t ReloadCronSheduler() isExpressError = true; continue; } - else if (!GetAppConf()->Timers[i].del && GetAppConf()->Timers[i].enab) + else if (!GetSysConf()->Timers[i].del && GetSysConf()->Timers[i].enab) { - JobsList[i] = cron_job_create(GetAppConf()->Timers[i].cron, custom_cron_job_callback, - (void*) &GetAppConf()->Timers[i]); + JobsList[i] = cron_job_create(GetSysConf()->Timers[i].cron, custom_cron_job_callback, + (void*) &GetSysConf()->Timers[i]); } } if (!isExpressError) diff --git a/src/RestApiHandler.c b/src/RestApiHandler.c index a0d4524..ade193f 100644 --- a/src/RestApiHandler.c +++ b/src/RestApiHandler.c @@ -277,8 +277,73 @@ static void funct_ota_newver(char *argres, int rw) snprintf(argres, MAX_DYNVAR_LENGTH, "\"%s\"", GetAvailVersion()); } +//CRON implementation BEGIN +static void funct_cronrecs(char *argres, int rw) +{ + if (rw) + { + struct jReadElement result; + cron_timer_t T = { 0 }; + jRead(argres, "", &result); + if (result.dataType == JREAD_ARRAY) + { + int i; + for (i = 0; i < result.elements; i++) + { + T.num = jRead_int(argres, "[*{'num'", &i); + T.del = jRead_int(argres, "[*{'del'", &i); + T.enab = jRead_int(argres, "[*{'enab'", &i); + T.prev = jRead_int(argres, "[*{'prev'", &i); + jRead_string(argres, "[*{'name'", T.name, sizeof(T.name), &i); + T.obj = jRead_int(argres, "[*{'obj'", &i); + T.act = jRead_int(argres, "[*{'act'", &i); + jRead_string(argres, "[*{'cron'", T.cron, sizeof(T.cron), &i); + jRead_string(argres, "[*{'exec'", T.exec, sizeof(T.exec), &i); + memcpy(&GetSysConf()->Timers[T.num - 1], &T, sizeof(cron_timer_t)); + } + ReloadCronSheduler(); + } + } + else + { + struct jWriteControl jwc; + jwOpen(&jwc, argres, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT); + for (int idx = 0; idx < CRON_TIMERS_NUMBER; idx++) + { + cron_timer_t T; + memcpy(&T, &GetSysConf()->Timers[idx], sizeof(cron_timer_t)); + jwArr_object(&jwc); + jwObj_int(&jwc, "num", (unsigned int) T.num); + jwObj_int(&jwc, "del", (T.del) ? 1 : 0); + jwObj_int(&jwc, "enab", (T.enab) ? 1 : 0); + jwObj_int(&jwc, "prev", (T.prev) ? 1 : 0); + jwObj_string(&jwc, "name", T.name); + jwObj_int(&jwc, "obj", (unsigned int) T.obj); + jwObj_int(&jwc, "act", (unsigned int) T.act); + jwObj_string(&jwc, "cron", T.cron); + jwObj_string(&jwc, "exec", T.exec); + jwEnd(&jwc); + } + jwClose(&jwc); + } +} + +//CRON implementation END +static void funct_objsinfo(char *argres, int rw) +{ + GetSysObjectsInfo(argres); +} + + +static void funct_exec(char *argres, int rw) +{ + if (rw) + ExecCommand(argres); + else + snprintf(argres, MAX_DYNVAR_LENGTH, "\"EXECUTED\""); +} const int hw_rev = CONFIG_BOARD_HARDWARE_REVISION; const bool VAR_TRUE = true; @@ -287,7 +352,8 @@ const bool VAR_FALSE = false; const rest_var_t SystemVariables[] = { - { 0, "time", &funct_time, VAR_FUNCT, R, 0, 0 }, + { 0, "exec", &funct_exec, VAR_FUNCT, RW, 0, 0 }, + { 0, "time", &funct_time, VAR_FUNCT, R, 0, 0 }, { 0, "uptime", &funct_uptime, VAR_FUNCT, R, 0, 0 }, { 0, "free_ram", &funct_fram, VAR_FUNCT, R, 0, 0 }, { 0, "free_ram_min", &funct_fram_min, VAR_FUNCT, R, 0, 0 }, @@ -435,6 +501,9 @@ const rest_var_t SystemVariables[] = #else { 0, "mbtcp_visible", (bool*) (&VAR_FALSE), VAR_BOOL, R, 0, 1 }, #endif + { 0, "cronrecs", &funct_cronrecs, VAR_FUNCT, RW, 0, 0 }, + { 0, "objsinfo", &funct_objsinfo, VAR_FUNCT, R, 0, 0 }, + }; diff --git a/src/SNTP.c b/src/SNTP.c index 6428902..8518eac 100644 --- a/src/SNTP.c +++ b/src/SNTP.c @@ -23,10 +23,13 @@ #include "esp_timer.h" #include "NetTransport.h" #include "UserCallbacks.h" +#include "CronTimers.h" + #define YEAR_BASE (1900) //tm structure base year static uint32_t UpTime = 0; + //Pointer to extend user on time got callback static void (*time_sync_notif)(struct timeval *tv) = NULL; @@ -62,6 +65,7 @@ static void time_sync_notification_cb(struct timeval *tv) { if (time_sync_notif) time_sync_notif(tv); + TimeObtainHandler(tv); } static void initialize_sntp(void) diff --git a/src/SysConfiguration.c b/src/SysConfiguration.c index 6461a2f..a4ce141 100644 --- a/src/SysConfiguration.c +++ b/src/SysConfiguration.c @@ -158,6 +158,7 @@ esp_err_t WebGuiAppInit(void) #if CONFIG_WEBGUIAPP_GPRS_ENABLE || CONFIG_WEBGUIAPP_ETHERNET_ENABLE || CONFIG_WEBGUIAPP_WIFI_ENABLE ESP_ERROR_CHECK(start_file_server()); StartTimeGet(); + //regTimeSyncCallback(&TimeObtainHandler); //mDNSServiceStart(); #if CONFIG_WEBGUIAPP_MQTT_ENABLE @@ -395,6 +396,24 @@ esp_netif_str_to_ip4(CONFIG_WEBGUIAPP_DNS3_ADDRESS_DEFAULT, (esp_ip4_addr_t*) &C #endif Conf->modbusSettings.ModbusTCPPort = CONFIG_WEBGUIAPP_MBTCP_SERVER_PORT; #endif + for (int i = 0; i < 16; i++ ) + { + Conf->Timers[i].num = i+1; + Conf->Timers[i].del = true; + Conf->Timers[i].enab = false; + Conf->Timers[i].prev = false; + Conf->Timers[i].obj = 0; + Conf->Timers[i].act = 0; + strcpy(Conf->Timers[i].name, "Timer Name"); + strcpy(Conf->Timers[i].cron, "* * * * * *"); + strcpy(Conf->Timers[i].exec, "OBJECT,ACTION,ARGUMENTS"); + + } + for (int i = 0; i < 16; i++ ) + { + strcpy(Conf->CronObjects[i].objname, GetCronObjectNameDef(i)); + Conf->CronObjects[i].idx = i; + } }