diff --git a/components/webguiapp b/components/webguiapp index 1e3eb96..fcffb19 160000 --- a/components/webguiapp +++ b/components/webguiapp @@ -1 +1 @@ -Subproject commit 1e3eb967ab70d350fd9dba82832c69c9d85a7b5a +Subproject commit fcffb19740889a4df6ceb731bd18e9398c6e1067 diff --git a/main/include/AppConfiguration.h b/main/include/AppConfiguration.h index c245633..e5929b1 100644 --- a/main/include/AppConfiguration.h +++ b/main/include/AppConfiguration.h @@ -26,8 +26,8 @@ #include #include +#include "../../components/webguiapp/include/CronTimers.h" #include "esp_netif.h" -#include "CronTimers.h" /// Application-dependent structure used to contain address information diff --git a/main/include/CronTimers.h b/main/include/CronTimers.h deleted file mode 100644 index 4566bfe..0000000 --- a/main/include/CronTimers.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright 2023 Bogdan Pilyugin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * File name: CronTimers.h - * Project: webguiapp_ref_implement - * Created on: 2023-04-15 - * Author: bogdan - * Description: - */ - -#ifndef MAIN_INCLUDE_CRONTIMERS_H_ -#define MAIN_INCLUDE_CRONTIMERS_H_ -#include "esp_err.h" -#include "cron.h" -#include "jobs.h" -#include "ccronexpr.h" - -#define CRON_TIMERS_NUMBER (16) -#define TIMER_NAME_LENGTH (16) -#define TIMER_CRONSTRING_LENGTH (32) -#define CRON_EXPRESS_MAX_LENGTH (128) - -#define CRON_OBJECTS_NUMBER (16) -#define CRON_OBJECT_NAME_LENGTH (16) - -typedef struct -{ - int idx; - char objname[CRON_OBJECT_NAME_LENGTH]; -} cron_obj_t; - -/** - * Cron scheduler configuration structure - */ -typedef struct -{ - int num; /*!< Index of sheduler */ - bool del; /*!< Flag of non valid record, free for future overwrite */ - bool enab; /*!< Enable scheduler */ - bool prev; /*!< Enable to execute nearest in the past sheduled action */ - char name[TIMER_NAME_LENGTH]; /*!< Human readable name of scheduler */ - int obj; /*!< Index of object scheduler affected on */ - int act; /*!< Index of action with the object*/ - char cron[TIMER_CRONSTRING_LENGTH]; /*!< Cron expression */ - -} cron_timer_t; - -esp_err_t InitCronSheduler(); -esp_err_t ReloadCronSheduler(); -char* GetCronError(); -void DebugTimer(); - -char* GetCronObjectNameDef(int idx); -char* GetCronObjectName(int idx); -char* GetCronActionName(int idx); -char* GetCronActAvail(int idx); - -/** - * \brief Handle all actions under all objects - * \param obj Index of the object - * \param act Index of the action - */ -void custom_cron_execute(int obj, int act); - -#endif /* MAIN_INCLUDE_CRONTIMERS_H_ */ diff --git a/main/main.c b/main/main.c index d1a5181..57e9067 100644 --- a/main/main.c +++ b/main/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,13 +6,13 @@ #include "cron.h" #include "jobs.h" #include "AppConfiguration.h" -#include "CronTimers.h" int HTTPPrintCustom(httpd_req_t *req, char *buf, char *var, int arg); HTTP_IO_RESULT AfterPostHandlerCustom(httpd_req_t *req, const char *filename, char *PostData); void UserMQTTEventHndlr(int idx, void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data); void TimeObtainHandler(struct timeval *tm); void SaveUserConf(); +int ExecAppCommand(char *cmd); const char my_context_data[] = "MyContextDataPassedIntoMQTTHandler"; @@ -22,9 +23,11 @@ void app_main(void) regUserEventHandler(&UserMQTTEventHndlr, (void*) my_context_data); regTimeSyncCallback(&TimeObtainHandler); regCustomSaveConf(&SaveUserConf); + regCustomExecCommand(&ExecAppCommand); RegAppVariables(); + WebGuiAppInit(); if (GetUserAppNeedReset()) { diff --git a/main/src/CommandProcApp.c b/main/src/CommandProcApp.c new file mode 100644 index 0000000..13f04af --- /dev/null +++ b/main/src/CommandProcApp.c @@ -0,0 +1,124 @@ +/* Copyright 2023 Bogdan Pilyugin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * File name: CommandProcApp.c + * Project: WebguiappTemplate + * Created on: 2023-10-09 + * Author: bogdan + * Description: + */ + +#include "webguiapp.h" + +#define TAG "COMMAND_PROC_APP" + +#define OBJECTS_NUMBER_APP (1) +#define EXEC_ACTIONS_MAX_NUMBER_APP (2) + +static int ExecCommandParseApp(char *cmd); + +static void APPLICATION_TEST1_handle(char *obj, char *com, char *arg) +{ + ESP_LOGI(TAG, "INPUTS handler command %s with argument %s", com, arg); +} + +static void APPLICATION_TEST2_handle(char *obj, char *com, char *arg) +{ + ESP_LOGI(TAG, "SYSTEM handler command %s with argument %s", com, arg); +} + +typedef struct +{ + int index; + char object_name[EXEC_OBJECT_NAME_MAX_LENGTH]; + char allowed_actions[EXEC_ACTIONS_MAX_NUMBER_APP][EXEC_ACTION_NAME_MAX_LENGTH]; + void (*command_handlers[EXEC_ACTIONS_MAX_NUMBER_APP])(char *obj, char *com, char *arg); +} app_obj_struct_t; + +const app_obj_struct_t app_com_obj_arr[] = { + { + .index = 0, + .object_name = "APPLICATION", + .allowed_actions = { "TEST1", "TEST2" }, + .command_handlers = { &APPLICATION_TEST1_handle, &APPLICATION_TEST2_handle } + } +}; + +void GetAppObjectsInfo(char *data) +{ + struct jWriteControl jwc; + jwOpen(&jwc, data, VAR_MAX_VALUE_LENGTH, JW_ARRAY, JW_COMPACT); + for (int idx = 0; idx < OBJECTS_NUMBER_APP; idx++) + { + jwArr_object(&jwc); + jwObj_string(&jwc, "object", app_com_obj_arr[idx].object_name); + jwObj_array(&jwc, "actions"); + for (int i = 0; i < EXEC_ACTIONS_MAX_NUMBER_APP; i++) + { + if ((app_com_obj_arr[idx].allowed_actions[i])[0] != NULL) + jwArr_string(&jwc, app_com_obj_arr[idx].allowed_actions[i]); + } + jwEnd(&jwc); + jwEnd(&jwc); + } + jwClose(&jwc); +} + +int ExecAppCommand(char *cmd) +{ + return ExecCommandParseApp(cmd); +} + +static int ExecCommandParseApp(char *cmd) +{ + char *obj = NULL, *com = NULL, *arg = NULL; + int err = 0; + int commlen = strlen(cmd); + if (commlen > EXEC_COMMAND_MAX_LENGTH) + return 1; + char comm[EXEC_COMMAND_MAX_LENGTH + 1]; + const char del1 = ','; + const char del2 = 0x00; + strcpy(comm, cmd); + obj = strtok(comm, &del1); + com = strtok(NULL, &del1); + arg = strtok(NULL, &del2); + if (!obj) + return 2; + if (!com) + return 2; + err = 4; + for (int idx = 0; idx < OBJECTS_NUMBER_APP; idx++) + { + if (!strcmp(obj, app_com_obj_arr[idx].object_name)) + { + err = 5; + for (int i = 0; i < EXEC_ACTIONS_MAX_NUMBER_APP; i++) + { + if (!strcmp(com, app_com_obj_arr[idx].allowed_actions[i])) + { + if (app_com_obj_arr[idx].command_handlers[i] != NULL) + { + app_com_obj_arr[idx].command_handlers[i](obj, com, arg); + err = 0; + } + else + err = 6; + } + } + } + } + return err; +} + diff --git a/main/src/CronTimers.c b/main/src/CronTimers.c deleted file mode 100644 index 992606a..0000000 --- a/main/src/CronTimers.c +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright 2023 Bogdan Pilyugin - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * File name: CronTimers.c - * Project: webguiapp_ref_implement - * Created on: 2023-04-15 - * Author: bogdan - * Description: - */ - -#include "CronTimers.h" -#include "AppConfiguration.h" -#include "esp_log.h" -#include "webguiapp.h" - -#define TAG "CRON_TIMER" - - -const char *cron_actions[] = { "ON", "REBOOT", "TOGGLE", "OFF","VERYLONG_OPERATION" }; -const char *cron_objects[] = { - "RELAY1", - "RELAY2", - "RELAY3", - "RELAY4", - "RELAY5", - "RELAY6", - "RELAY7", - "RELAY8", - "SYSTEM" }; -const char *cron_act_avail[] = { - "[0,2,3]", - "[0,2,3]", - "[0,2,3]", - "[0,2,3]", - "[0,2,3]", - "[0,2,3]", - "[0,2,3]", - "[0,2,3]", - "[1,4]" }; - -char* GetCronObjectNameDef(int idx) -{ - if(idx < 0 || idx >= sizeof(cron_objects)/sizeof(char*)) - return ""; - return (char*)cron_objects[idx]; -} - -char* GetCronObjectName(int idx) -{ - if(idx < 0 || idx >= sizeof(cron_objects)/sizeof(char*)) - return ""; - return GetAppConf()->CronObjects[idx].objname; -} - -char* GetCronActionName(int idx) -{ - if(idx < 0 || idx >= sizeof(cron_actions)/sizeof(char*)) - return ""; - return (char*)cron_actions[idx]; -} - -char* GetCronActAvail(int idx) -{ - if(idx < 0 || idx >= sizeof(cron_act_avail)/sizeof(char*)) - return "[]"; - return (char*)cron_act_avail[idx]; -} - - -static cron_job *JobsList[CRON_TIMERS_NUMBER]; -static char cron_express_error[CRON_EXPRESS_MAX_LENGTH]; - -char* GetCronError() -{ - return cron_express_error; -} - -/** - * \brief Handle all actions under all objects - * \param obj Index of the object - * \param act Index of the action - */ -void custom_cron_execute(int obj, int act) -{ - - - -} - -void custom_cron_job_callback(cron_job *job) -{ - int act = ((cron_timer_t*) job->data)->act; - int obj = ((cron_timer_t*) job->data)->obj; - char *name = ((cron_timer_t*) job->data)->name; - //here call all timers jobs depends on object and action - time_t now; - time(&now); - ESP_LOGI(TAG, "Execute scheduler '%s' action %d under object %d at time %d", name, act, obj, (unsigned int )now); - LogFile("cron.log", "Executed sheduler with action %u under object %u", act, obj); - custom_cron_execute(obj, act); - return; -} - -esp_err_t InitCronSheduler() -{ - esp_err_t res = ESP_OK; - return res; -} - -const char* check_expr(const char *expr) -{ - const char *err = NULL; - cron_expr test; - memset(&test, 0, sizeof(test)); - cron_parse_expr(expr, &test, &err); - return err; -} - - -static void ExecuteLastAction() -{ - int obj; - for (obj = 0; obj < sizeof(cron_objects); obj++) - { - int shdl; - time_t now; - time(&now); - time_t delta = now; - int act = -1; - - 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) - { - cron_expr cron_exp = { 0 }; - cron_parse_expr(GetAppConf()->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; - } - } - } - - if(act != -1) - { - ESP_LOGW(TAG, "Execute last action %d with object %d", act, obj); - LogFile("cron.log", "Execute last action %d under object %d", act, obj); - custom_cron_execute(obj, act); - } - } -} - -void TimeObtainHandler(struct timeval *tm) -{ - ESP_LOGW(TAG, "Current time received with value %d", (unsigned int )tm->tv_sec); - ReloadCronSheduler(); - ExecuteLastAction(); - LogFile("cron.log", "Cron service started"); -} - -void DebugTimer() -{ - ExecuteLastAction(); -} - -esp_err_t ReloadCronSheduler() -{ - //remove all jobs - ESP_LOGI(TAG, "Cron stop call result %d", cron_stop()); - cron_job_clear_all(); - //check if we have jobs to run - bool isExpressError = false; - for (int i = 0; i < CRON_TIMERS_NUMBER; i++) - { - const char *err = check_expr(GetAppConf()->Timers[i].cron); - if (err) - { - snprintf(cron_express_error, CRON_EXPRESS_MAX_LENGTH - 1, "In timer %d expression error:%s", i + 1, err); - ESP_LOGE(TAG, "%s", cron_express_error); - isExpressError = true; - continue; - } - else if (!GetAppConf()->Timers[i].del && GetAppConf()->Timers[i].enab) - { - JobsList[i] = cron_job_create(GetAppConf()->Timers[i].cron, custom_cron_job_callback, - (void*) &GetAppConf()->Timers[i]); - } - } - if (!isExpressError) - cron_express_error[0] = 0x00; //clear last cron expression parse - int jobs_num = cron_job_node_count(); - ESP_LOGI(TAG, "In config presents %d jobs", jobs_num); - - if (jobs_num > 0) - ESP_LOGI(TAG, "Cron start call result %d", cron_start()); - return ESP_OK; -} - diff --git a/main/src/HTTPPostCustom.c b/main/src/HTTPPostCustom.c index 034e71c..d16f8ef 100644 --- a/main/src/HTTPPostCustom.c +++ b/main/src/HTTPPostCustom.c @@ -20,9 +20,9 @@ * \details * \copyright Apache License, Version 2.0 */ +#include #include "webguiapp.h" #include "AppConfiguration.h" -#include "CronTimers.h" const char pg_40[] = "index40.html"; const char pg_42[] = "index42.html"; diff --git a/main/src/HTTPPrintCustom.c b/main/src/HTTPPrintCustom.c index 6fa7092..b2576b1 100644 --- a/main/src/HTTPPrintCustom.c +++ b/main/src/HTTPPrintCustom.c @@ -20,9 +20,9 @@ * \details * \copyright Apache License, Version 2.0 */ +#include #include "webguiapp.h" #include "AppConfiguration.h" -#include "CronTimers.h" static void HTTPPrint_crontmr(char *VarData, void *arg) { diff --git a/main/src/RestApiHandlersApp.c b/main/src/RestApiHandlersApp.c index 6ecf1e4..2049800 100644 --- a/main/src/RestApiHandlersApp.c +++ b/main/src/RestApiHandlersApp.c @@ -21,9 +21,9 @@ * \copyright Apache License, Version 2.0 */ +#include #include "webguiapp.h" #include "AppConfiguration.h" -#include "CronTimers.h" extern APP_CONFIG AppConfig;