implemented cron and command expressions

This commit is contained in:
Bogdan Pilyugin 2023-10-10 12:24:11 +02:00
parent fcffb19740
commit 4ec2b111eb
8 changed files with 131 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -28,6 +28,7 @@
#include <stdbool.h>
#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);

View File

@ -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

View File

@ -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 <CronTimers.h>
#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)

View File

@ -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 },
};

View File

@ -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)

View File

@ -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;
}
}