From fce91c4fb048c625b109ca537d37a671212ab71f Mon Sep 17 00:00:00 2001 From: Piyush Shah Date: Fri, 21 May 2021 18:35:10 +0530 Subject: [PATCH] esp_rmaker_core: Add a system service for reboot/reset --- CHANGES.md | 29 +++++++ components/esp_rainmaker/CMakeLists.txt | 1 + .../esp_rainmaker/include/esp_rmaker_core.h | 64 +++++++++++++++ .../include/esp_rmaker_standard_params.h | 44 +++++++++- .../include/esp_rmaker_standard_services.h | 14 ++++ .../include/esp_rmaker_standard_types.h | 4 + .../src/core/esp_rmaker_system_service.c | 81 +++++++++++++++++++ .../src/core/esp_rmaker_time_service.c | 2 + .../esp_rmaker_standard_params.c | 21 +++++ .../esp_rmaker_standard_services.c | 5 ++ components/rmaker_common | 2 +- examples/common/app_reset/app_reset.c | 4 +- 12 files changed, 267 insertions(+), 4 deletions(-) create mode 100644 components/esp_rainmaker/src/core/esp_rmaker_system_service.c diff --git a/CHANGES.md b/CHANGES.md index 5b1c238..3a541eb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,34 @@ # Changes +## 28-May-2021 (esp_rmaker_core: Add a system service for reboot/reset) + +The reboot/reset API prototypes have changed from + +``` +esp_err_t esp_rmaker_reboot(uint8_t seconds); +esp_err_t esp_rmaker_wifi_reset(uint8_t seconds); +esp_err_t esp_rmaker_factory_reset(uint8_t seconds); +``` +To + +``` +esp_err_t esp_rmaker_reboot(int8_t seconds); +esp_err_t esp_rmaker_wifi_reset(int8_t reset_seconds, int8_t reboot_seconds); +esp_err_t esp_rmaker_factory_reset(int8_t reset_seconds, int8_t reboot_seconds); +``` + +- The behavior of `esp_rmaker_reboot()` has changed such that passing a value of 0 would trigger +an immediate reboot without starting any timer. +- The `esp_rmaker_wifi_reset()` and `esp_rmaker_factory_reset()` APIs have been modified such that +they now accept 2 time values. The `reset_seconds` specify the time after which the reset should trigger +and the `reboot_seconds` specify the time after which the reboot should trigger, after the reset +was done. +- `reboot_seconds` is similar to the earlier `seconds` argument, but it allows for 0 and negative values. +0 indicates that the reboot should happen immediately after reset and negative value indicates that the +reboot should be skipped. + +Please refer the [API documentation](https://docs.espressif.com/projects/esp-rainmaker/en/latest/c-api-reference/rainmaker_common.html#utilities) for additional details. + ## 1-Feb-2021 (esp_rmaker: Moved out some generic modules from esp_rainmaker component) Some generic code has been moved out of the esp_rainmaker repo and included as submodules at diff --git a/components/esp_rainmaker/CMakeLists.txt b/components/esp_rainmaker/CMakeLists.txt index bcb2e05..44ea954 100644 --- a/components/esp_rainmaker/CMakeLists.txt +++ b/components/esp_rainmaker/CMakeLists.txt @@ -6,6 +6,7 @@ set(core_srcs "src/core/esp_rmaker_core.c" "src/core/esp_rmaker_node_config.c" "src/core/esp_rmaker_client_data.c" "src/core/esp_rmaker_time_service.c" + "src/core/esp_rmaker_system_service.c" "src/core/esp_rmaker_user_mapping.pb-c.c" "src/core/esp_rmaker_user_mapping.c" "src/core/esp_rmaker_schedule.c") diff --git a/components/esp_rainmaker/include/esp_rmaker_core.h b/components/esp_rainmaker/include/esp_rmaker_core.h index 4701d68..fa6a922 100644 --- a/components/esp_rainmaker/include/esp_rmaker_core.h +++ b/components/esp_rainmaker/include/esp_rmaker_core.h @@ -110,6 +110,18 @@ typedef enum { PROP_FLAG_PERSIST = (1 << 3) } esp_param_property_flags_t; +/** System Service Reboot Flag */ +#define SYSTEM_SERV_FLAG_REBOOT (1 << 0) + +/** System Service Factory Reset Flag */ +#define SYSTEM_SERV_FLAG_FACTORY_RESET (1 << 1) + +/** System Service Wi-Fi Reset Flag */ +#define SYSTEM_SERV_FLAG_WIFI_RESET (1 << 2) + +/** System Service All Flags */ +#define SYSTEM_SERV_FLAGS_ALL (SYSTEM_SERV_FLAG_REBOOT | SYSTEM_SERV_FLAG_FACTORY_RESET | SYSTEM_SERV_FLAG_WIFI_RESET) + /** Generic ESP RainMaker handle */ typedef size_t esp_rmaker_handle_t; @@ -152,6 +164,32 @@ typedef struct { esp_rmaker_req_src_t src; } esp_rmaker_read_ctx_t; +/** System service configuration */ +typedef struct { + /** Logical OR of system service flags (SYSTEM_SERV_FLAG_REBOOT, + * SYSTEM_SERV_FLAG_FACTORY_RESET, SYSTEM_SERV_FLAG_WIFI_RESET) as required + * or SYSTEM_SERV_FLAGS_ALL. + */ + uint16_t flags; + /** Time in seconds after which the device should reboot. + * Value of zero would trigger an immediate reboot if a write is received for + * the Reboot parameter. + * Recommended value: 2 + */ + int8_t reboot_seconds; + /** Time in seconds after which the device should reset (Wi-Fi or factory). + * Value of zero would trigger an immediate action if a write is received for + * the Wi-Fi reset or Factory reset parameter. + * Recommended value: 2 + */ + int8_t reset_seconds; + /** Time in seconds after which the device should reboot after it has been reset. + * Value of zero would mean that there won't be any reboot after the reset. + * Recommended value: 2 + */ + int8_t reset_reboot_seconds; +} esp_rmaker_system_serv_config_t; + /** Callback for parameter value write requests. * * The callback should call the esp_rmaker_param_update_and_report() API if the new value is to be set @@ -705,6 +743,32 @@ char *esp_rmaker_param_get_type(const esp_rmaker_param_t *param); */ esp_err_t esp_rmaker_report_node_details(void); +/** Enable Timezone Service + * + * This enables the ESP RainMaker standard timezone service which can be used to set + * timezone, either in POSIX or location string format. Please refer the specifications + * for additional details. + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_timezone_service_enable(void); + +/** Enable System Service + * + * This enables the ESP RainMaker standard system service which can be + * used for operations like reboot, factory reset and Wi-Fi reset. + * + * Please refer the specifications for additional details. + * + * @param[in] config Configuration for the system service. + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_system_service_enable(esp_rmaker_system_serv_config_t *config); + + #ifdef __cplusplus } #endif diff --git a/components/esp_rainmaker/include/esp_rmaker_standard_params.h b/components/esp_rainmaker/include/esp_rmaker_standard_params.h index 5a5ad85..e029330 100644 --- a/components/esp_rainmaker/include/esp_rmaker_standard_params.h +++ b/components/esp_rainmaker/include/esp_rmaker_standard_params.h @@ -45,6 +45,9 @@ extern "C" #define ESP_RMAKER_DEF_TIMEZONE_NAME "TZ" #define ESP_RMAKER_DEF_TIMEZONE_POSIX_NAME "TZ-POSIX" #define ESP_RMAKER_DEF_SCHEDULE_NAME "Schedules" +#define ESP_RMAKER_DEF_REBOOT_NAME "Reboot" +#define ESP_RMAKER_DEF_FACTORY_RESET_NAME "Factory-Reset" +#define ESP_RMAKER_DEF_WIFI_RESET_NAME "Wi-Fi-Reset" /** * Create standard name param @@ -247,7 +250,7 @@ esp_rmaker_param_t *esp_rmaker_timezone_param_create(const char *param_name, con esp_rmaker_param_t *esp_rmaker_timezone_posix_param_create(const char *param_name, const char *val); /** - * Create standard schedules param + * Create standard Schedules param * * This will create the standard schedules parameter. Default value * is set internally. @@ -260,6 +263,45 @@ esp_rmaker_param_t *esp_rmaker_timezone_posix_param_create(const char *param_nam */ esp_rmaker_param_t *esp_rmaker_schedules_param_create(const char *param_name, int max_schedules); +/** + * Create standard Reboot param + * + * This will create the standard reboot parameter. + * Set value to true (via write param) for the action to trigger. + * + * @param[in] param_name Name of the parameter + * + * @return Parameter handle on success. + * @return NULL in case of failures. + */ +esp_rmaker_param_t *esp_rmaker_reboot_param_create(const char *param_name); + +/** + * Create standard Factory Reset param + * + * This will create the standard factory reset parameter. + * Set value to true (via write param) for the action to trigger. + * + * @param[in] param_name Name of the parameter + * + * @return Parameter handle on success. + * @return NULL in case of failures. + */ +esp_rmaker_param_t *esp_rmaker_factory_reset_param_create(const char *param_name); + +/** + * Create standard Wi-Fi Reset param + * + * This will create the standard Wi-Fi Reset parameter. + * Set value to true (via write param) for the action to trigger. + * + * @param[in] param_name Name of the parameter + * + * @return Parameter handle on success. + * @return NULL in case of failures. + */ +esp_rmaker_param_t *esp_rmaker_wifi_reset_param_create(const char *param_name); + #ifdef __cplusplus } #endif diff --git a/components/esp_rainmaker/include/esp_rmaker_standard_services.h b/components/esp_rainmaker/include/esp_rmaker_standard_services.h index 348505c..57358c1 100644 --- a/components/esp_rainmaker/include/esp_rmaker_standard_services.h +++ b/components/esp_rainmaker/include/esp_rmaker_standard_services.h @@ -71,6 +71,20 @@ esp_rmaker_device_t *esp_rmaker_time_service_create(const char *serv_name, const */ esp_rmaker_device_t *esp_rmaker_create_schedule_service(const char *serv_name, esp_rmaker_device_write_cb_t write_cb, esp_rmaker_device_read_cb_t read_cb, int max_schedules, void *priv_data); +/** Create a standard System service + * + * This creates an empty System service. Appropriate parameters should be added by the caller. + * + * @param[in] serv_name The unique service name + * @param[in] priv_data (Optional) Private data associated with the service. This should stay + * allocated throughout the lifetime of the service. + * + * @return service_handle on success. + * @return NULL in case of any error. + */ + +esp_rmaker_device_t *esp_rmaker_create_system_service(const char *serv_name, void *priv_data); + #ifdef __cplusplus } #endif diff --git a/components/esp_rainmaker/include/esp_rmaker_standard_types.h b/components/esp_rainmaker/include/esp_rmaker_standard_types.h index 803862d..90cc502 100644 --- a/components/esp_rainmaker/include/esp_rmaker_standard_types.h +++ b/components/esp_rainmaker/include/esp_rmaker_standard_types.h @@ -44,6 +44,9 @@ extern "C" #define ESP_RMAKER_PARAM_TIMEZONE "esp.param.tz" #define ESP_RMAKER_PARAM_TIMEZONE_POSIX "esp.param.tz_posix" #define ESP_RMAKER_PARAM_SCHEDULES "esp.param.schedules" +#define ESP_RMAKER_PARAM_REBOOT "esp.param.reboot" +#define ESP_RMAKER_PARAM_FACTORY_RESET "esp.param.factory-reset" +#define ESP_RMAKER_PARAM_WIFI_RESET "esp.param.wifi-reset" /********** STANDARD DEVICE TYPES **********/ @@ -58,6 +61,7 @@ extern "C" #define ESP_RMAKER_SERVICE_OTA "esp.service.ota" #define ESP_RMAKER_SERVICE_TIME "esp.service.time" #define ESP_RMAKER_SERVICE_SCHEDULE "esp.service.schedule" +#define ESP_RMAKER_SERVICE_SYSTEM "esp.service.system" #ifdef __cplusplus } diff --git a/components/esp_rainmaker/src/core/esp_rmaker_system_service.c b/components/esp_rainmaker/src/core/esp_rmaker_system_service.c new file mode 100644 index 0000000..2395e71 --- /dev/null +++ b/components/esp_rainmaker/src/core/esp_rmaker_system_service.c @@ -0,0 +1,81 @@ +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// 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. +#include +#include +#include +#include +#include +#include +#include + +static const char *TAG = "esp_rmaker_system_service"; + +#define ESP_RMAKER_SYSTEM_SERV_NAME "System" + +static esp_err_t esp_rmaker_system_serv_write_cb(const esp_rmaker_device_t *device, + const esp_rmaker_param_t *param, const esp_rmaker_param_val_t val, + void *priv_data, esp_rmaker_write_ctx_t *ctx) +{ + esp_err_t err = ESP_FAIL; + esp_rmaker_system_serv_config_t *config = (esp_rmaker_system_serv_config_t *)priv_data; + if (strcmp(esp_rmaker_param_get_type(param), ESP_RMAKER_PARAM_REBOOT) == 0) { + err = esp_rmaker_reboot(config->reboot_seconds); + } else if (strcmp(esp_rmaker_param_get_type(param), ESP_RMAKER_PARAM_FACTORY_RESET) == 0) { + err = esp_rmaker_factory_reset(config->reset_seconds, config->reset_reboot_seconds); + } else if (strcmp(esp_rmaker_param_get_type(param), ESP_RMAKER_PARAM_WIFI_RESET) == 0) { + err = esp_rmaker_wifi_reset(config->reset_seconds, config->reset_reboot_seconds); + } + if (err == ESP_OK) { + esp_rmaker_param_update_and_report(param, val); + } + return err; +} + +esp_err_t esp_rmaker_system_service_enable(esp_rmaker_system_serv_config_t *config) +{ + if ((config->flags & SYSTEM_SERV_FLAGS_ALL) == 0) { + ESP_LOGE(TAG, "Atleast one flag should be set for system service."); + return ESP_ERR_INVALID_ARG; + } + esp_rmaker_system_serv_config_t *priv_config = calloc(1, sizeof(esp_rmaker_system_serv_config_t)); + if (!priv_config) { + ESP_LOGE(TAG, "Failed to allocate data for system service config."); + return ESP_ERR_NO_MEM; + } + *priv_config = *config; + esp_rmaker_device_t *service = esp_rmaker_create_system_service(ESP_RMAKER_SYSTEM_SERV_NAME, (void *)priv_config); + if (service) { + esp_rmaker_device_add_cb(service, esp_rmaker_system_serv_write_cb, NULL); + if (priv_config->flags & SYSTEM_SERV_FLAG_REBOOT) { + esp_rmaker_device_add_param(service, esp_rmaker_reboot_param_create(ESP_RMAKER_DEF_REBOOT_NAME)); + } + if (priv_config->flags & SYSTEM_SERV_FLAG_FACTORY_RESET) { + esp_rmaker_device_add_param(service, esp_rmaker_factory_reset_param_create(ESP_RMAKER_DEF_FACTORY_RESET_NAME)); + } + if (priv_config->flags & SYSTEM_SERV_FLAG_WIFI_RESET) { + esp_rmaker_device_add_param(service, esp_rmaker_wifi_reset_param_create(ESP_RMAKER_DEF_WIFI_RESET_NAME)); + } + esp_err_t err = esp_rmaker_node_add_device(esp_rmaker_get_node(), service); + if (err == ESP_OK) { + ESP_LOGI(TAG, "System service enabled."); + } else { + esp_rmaker_device_delete(service); + } + return err; + } else { + free(priv_config); + ESP_LOGE(TAG, "Failed to create System service."); + } + return ESP_ERR_NO_MEM; +} diff --git a/components/esp_rainmaker/src/core/esp_rmaker_time_service.c b/components/esp_rainmaker/src/core/esp_rmaker_time_service.c index b95e042..a897b4e 100644 --- a/components/esp_rainmaker/src/core/esp_rmaker_time_service.c +++ b/components/esp_rainmaker/src/core/esp_rmaker_time_service.c @@ -63,6 +63,8 @@ static esp_err_t esp_rmaker_time_add_service(const char *tz, const char *tz_posi esp_err_t err = esp_rmaker_node_add_device(esp_rmaker_get_node(), service); if (err == ESP_OK) { ESP_LOGI(TAG, "Time service enabled"); + } else { + esp_rmaker_device_delete(service); } return err; } diff --git a/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_params.c b/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_params.c index 530dae1..c8af62b 100644 --- a/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_params.c +++ b/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_params.c @@ -160,3 +160,24 @@ esp_rmaker_param_t *esp_rmaker_schedules_param_create(const char *param_name, in esp_rmaker_param_add_array_max_count(param, max_schedules); return param; } + +esp_rmaker_param_t *esp_rmaker_reboot_param_create(const char *param_name) +{ + esp_rmaker_param_t *param = esp_rmaker_param_create(param_name, ESP_RMAKER_PARAM_REBOOT, + esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); + return param; +} + +esp_rmaker_param_t *esp_rmaker_factory_reset_param_create(const char *param_name) +{ + esp_rmaker_param_t *param = esp_rmaker_param_create(param_name, ESP_RMAKER_PARAM_FACTORY_RESET, + esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); + return param; +} + +esp_rmaker_param_t *esp_rmaker_wifi_reset_param_create(const char *param_name) +{ + esp_rmaker_param_t *param = esp_rmaker_param_create(param_name, ESP_RMAKER_PARAM_WIFI_RESET, + esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); + return param; +} diff --git a/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_services.c b/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_services.c index 3c43267..980322e 100644 --- a/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_services.c +++ b/components/esp_rainmaker/src/standard_types/esp_rmaker_standard_services.c @@ -50,3 +50,8 @@ esp_rmaker_device_t *esp_rmaker_create_schedule_service(const char *serv_name, e } return service; } + +esp_rmaker_device_t *esp_rmaker_create_system_service(const char *serv_name, void *priv_data) +{ + return esp_rmaker_service_create(serv_name, ESP_RMAKER_SERVICE_SYSTEM, priv_data); +} diff --git a/components/rmaker_common b/components/rmaker_common index 0fe32f4..446e34f 160000 --- a/components/rmaker_common +++ b/components/rmaker_common @@ -1 +1 @@ -Subproject commit 0fe32f4d309d39575c5621c5ef0b590d64188ffb +Subproject commit 446e34f80b7967ed145823e7c386de5be9ad4413 diff --git a/examples/common/app_reset/app_reset.c b/examples/common/app_reset/app_reset.c index b330711..d8d1e89 100644 --- a/examples/common/app_reset/app_reset.c +++ b/examples/common/app_reset/app_reset.c @@ -21,7 +21,7 @@ static const char *TAG = "app_reset"; static void wifi_reset_trigger(void *arg) { - esp_rmaker_wifi_reset(REBOOT_DELAY); + esp_rmaker_wifi_reset(0, REBOOT_DELAY); } static void wifi_reset_indicate(void *arg) @@ -31,7 +31,7 @@ static void wifi_reset_indicate(void *arg) static void factory_reset_trigger(void *arg) { - esp_rmaker_factory_reset(REBOOT_DELAY); + esp_rmaker_factory_reset(0, REBOOT_DELAY); } static void factory_reset_indicate(void *arg)