From e62ff6dc375d1e75682ce9d79248134d18600680 Mon Sep 17 00:00:00 2001 From: Piyush Shah <8659527+shahpiyushv@users.noreply.github.com> Date: Thu, 22 Apr 2021 15:29:27 +0530 Subject: [PATCH] RainMaker library: Minor changes (#5092) - Use Serial.print instead of log_i for QR code helper information, so that it is always printed by default. - Expose the RainMaker factory reset and wifi reset APIs. - Simplify example to have only a Switch device. Create another example for custom device. - Enable push button based Factory reset and Wi-Fi reset. - Added support for the TimeZone service. - Moved API doc to RainMaker library's top level README. - Other minor doc changes. --- libraries/RainMaker/README.md | 444 ++++++++++++++++++ libraries/RainMaker/examples/README.md | 438 +---------------- .../.skip.esp32c3 | 0 .../.skip.esp32s2 | 0 .../RainMaker/examples/RMakerCustom/README.md | 27 ++ .../examples/RMakerCustom/RMakerCustom.ino | 126 +++++ .../RainMaker/examples/RMakerDevice/README.md | 34 -- .../examples/RMakerSwitch/.skip.esp32c3 | 0 .../examples/RMakerSwitch/.skip.esp32s2 | 0 .../RainMaker/examples/RMakerSwitch/README.md | 27 ++ .../RMakerSwitch.ino} | 76 ++- libraries/RainMaker/src/RMaker.cpp | 11 +- libraries/RainMaker/src/RMaker.h | 4 +- libraries/RainMaker/src/RMakerQR.h | 6 +- libraries/RainMaker/src/RMakerUtils.h | 16 + 15 files changed, 700 insertions(+), 509 deletions(-) rename libraries/RainMaker/examples/{RMakerDevice => RMakerCustom}/.skip.esp32c3 (100%) rename libraries/RainMaker/examples/{RMakerDevice => RMakerCustom}/.skip.esp32s2 (100%) create mode 100644 libraries/RainMaker/examples/RMakerCustom/README.md create mode 100644 libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino delete mode 100644 libraries/RainMaker/examples/RMakerDevice/README.md create mode 100644 libraries/RainMaker/examples/RMakerSwitch/.skip.esp32c3 create mode 100644 libraries/RainMaker/examples/RMakerSwitch/.skip.esp32s2 create mode 100644 libraries/RainMaker/examples/RMakerSwitch/README.md rename libraries/RainMaker/examples/{RMakerDevice/RMakerDevice.ino => RMakerSwitch/RMakerSwitch.ino} (52%) create mode 100644 libraries/RainMaker/src/RMakerUtils.h diff --git a/libraries/RainMaker/README.md b/libraries/RainMaker/README.md index f67650af..03f5e4c5 100644 --- a/libraries/RainMaker/README.md +++ b/libraries/RainMaker/README.md @@ -37,3 +37,447 @@ This ESP RainMaker library is built using esp-rainmaker component. Additional information about ESP RainMaker can be found [here](https://rainmaker.espressif.com/) NOTE : ESP RainMaker library is currently supported for ESP32 board only. + +## ESP RainMaker Agent API + +### RMaker.initNode() +This initializes the ESP RainMaker agent, wifi and creates the node. +``` +Node initNode(const char *name, const char *type); +``` +* **Parameters** +1. `name`: Name of the node +2. `type`: Type of the node + +* **Return** +1. Object of Node. + +* You can also set the configuration of the node using the following API + 1. RMaker.setTimeSync(bool val) +> NOTE: If you want to set the configuration for the node then these configuration API must be called before `RMaker.initNode()`. + +### RMaker.start() +It starts the ESP RainMaker agent. +``` +esp_err_t start() +``` +* **Return** +1. ESP_OK : On success +2. Error in case of failure + +> NOTE : +> 1. ESP RainMaker agent should be initialized before this call. +> 2. Once ESP RainMaker agent starts, compulsorily call WiFi.beginProvision() API. + +### RMaker.stop() +It stops the ESP RainMaker agent which was started using `RMaker.start()`. +``` +esp_err_t stop() +``` +* **Return** +1. ESP_OK : On success +2. Error in case of failure + +### RMaker.deinitNode() +It deinitializes the ESP RainMaker agent and the node created using `RMaker.initNode()`. +``` +esp_err_t deinitNode(Node node) +``` +* **Parameter** +1. `node` : Node object created using `RMaker.initNode()` +* **Return** +1. ESP_OK : On success +2. Error in case of failure + +### RMaker.enableOTA() +It enables OTA as per the ESP RainMaker Specification. For more details refer ESP RainMaker documentation. check [here](https://rainmaker.espressif.com/docs/ota.html) +``` +esp_err_t enableOTA(ota_type_t type); +``` +* **Parameter** +1. `type` : The OTA workflow type. + - OTA_USING_PARAMS + - OTA_USING_TOPICS +* **Return** +1. ESP_OK : On success +2. Error in case of failure + +### RMaker.enableSchedule() +This API enables the scheduling service for the node. For more information, check [here](https://rainmaker.espressif.com/docs/scheduling.html). +``` +esp_err_t enableSchedule(); +``` +* **Return** +1. ESP_OK : On success +2. Error in case of failure + +### RMaker.setTimeZone() +This API set's the timezone as a user friendly location string. Check [here](https://rainmaker.espressif.com/docs/time-service.html) for a list of valid values. +``` +esp_err_t setTimeZone(const char *tz); +``` +* **Parameter** +1. `tz' : Valid values as specified in documentation. + +* **Return** +1. ESP_OK : On success +2. Error in case of failure +> NOTE : default value is "Asia/Shanghai". +> This API comes into picture only when working with scheduling. + +## ESP RainMaker NODE APIs +`Node` class expose API's for node. +> NOTE : my_node is the object of Node class. + +### my_node.getNodeID() +It returns the unique node_id assigned to the node. This node_id is usually the MAC address of the board. +``` +char * getNodeID() +``` +* **Return** +1. `char * ` : Pointer to a NULL terminated node_id string. + +### my_node.getNodeInfo() +It returns pointer to the node_info_t as configured during node initialisation. +``` +node_info_t * getNodeInfo(); +``` +* **Return** +1. `node_info_t` : Pointer to the structure node_info_t on success. +2. `NULL` : On failure. + +* **ESP RainMaker node info** +It has following data member +1. char * name +2. char * type +3. char * fw_version +4. char * model + +### my_node.addNodeAttr() +It adds a new attribute as the metadata to the node. +``` +esp_err_t addNodeAttr(const char *attr_name, const char *val); +``` +* **Parameters** +1. `attr_name` : Name of the attribute +2. `val` : Value of the attribute + +* **Return** +1. `ESP_OK` : On success +2. Error in case of failure + +> NOTE : Only string values are allowed. + +### my_node.addDevice() +It adds a device to the node. +``` +esp_err_t addDevice(Device device); +``` +* **Parameter** +1. `device` : Device object + +* **Return** +1. `ESP_OK` : On success +2. Error in case of failure + +> NOTE : +> - This is the mandatory API to register device to node. +> - Single Node can have multiple devices. +> - Device name should be unique for each device. + +### my_node.removeDevice() +It removes a device from the node. +``` +esp_err_t removeDevice(Device device); +``` +* **Parameter** +1. `device` : Device object + +* **Return** +1. `ESP_OK` : On success +2. Error in case of failure + +## ESP RainMaker DEVICE API's +`Device` class expose API's for virtual devices on the node. +Parameterized constructor is defined which creates the virtual device on the node. Using Device class object you can create your own device. +> NOTE : my_device is the object of Device class +``` +Device my_device(const char *dev_name, const char *dev_type, void *priv_data); +``` +* **Parameters** +1. `dev_name` : Unique device name +2. `dev_type` : Optional device type. It can be kept NULL. + * Standard Device Types + * ESP_RMAKER_DEVICE_SWITCH + * ESP_RMAKER_DEVICE_LIGHTBULB + * ESP_RMAKER_DEVICE_FAN + * ESP_RMAKER_DEVICE_TEMP_SENSOR +3. `priv_data` : Private data associated with the device. This will be passed to the callbacks. + +> NOTE : This created device should be added to the node using `my_node.addDevice(my_device)`. + +- Sample example +``` +Device my_device("Switch"); +Device my_device("Switch1", NULL, NULL); +``` +> Here, dev_name is compulsory, rest are optional. +> Node can have multiple device, each device should have unique device name. + +### Standard Device +- Classes are defined for the standard devices. +- Creating object of these class creates the standard device with default parameters to it. +- Class for standard devices + * Switch + * LightBulb + * TemperatureSensor + * Fan +``` +Switch my_switch(const char *dev_name, void *priv_data, bool power); +``` +* **Parameters** +1. `dev_name` : Unique device name by default it is "switch" for switch device. +2. `priv_data` : Private data associated with the device. This will be passed to the callbacks. +3. `power` : It is the value that can be set for primary parameter. + +- Sample example for standard device. +``` +Switch switch1; +Switch switch2("switch2", NULL, true); +``` +`"switch2"` : Name for standard device. + +`NULL` : Private data for the device, which will be used in callback. + +`true` : Default value for the primary param, in case of switch it is power. + +> NOTE : No parameter are compulsory for standard devices. However if you are creating two objects of same standard class then in that case you will have to set the device name, if not then both device will have same name which is set by default, hence device will not get create. Device name should be unique for each device. + +### my_device.getDeviceName() +It returns the name of the Device. +``` +const char * getDeviceName(); +``` +* **Return** +1. `char *`: Returns Device name. + +> NOTE : Each device on the node should have unique device name. + +### my_device.addDeviceAttr() +It adds attribute to the device. Device attributes are reported only once after a boot-up as part of the node configuration. Eg. Serial Number +``` +esp_err_t addDeviceAttr(const char *attr_name, const char *val); +``` +* **Parameters** +1. `attr_name` : Name of the attribute +2. `val` : Value of the attribute + +* **Return** +1. `ESP_OK` : On success +2. Error in case of failure + +### my_device.deleteDevice() +It deletes the device created using parameterized constructor. This device should be first removed from the node using `my_node.removeDevice(my_device)`. +``` +esp_err_t deleteDevice(); +``` +* **Return** +1. `ESP_OK` : On success +2. Error in case of failure + +### my_device.addXParam() +It adds standard parameter to the device. +> NOTE : X is the default name by which parameter is referred, you can specify your own name to each parameter. + +> Default + +> Eg. `my_device.addPowerParam(true)` here power parameter is referred with name Power. +> Eg. `my_device.addHueParam(12)` here hue parameter is referred with name Hue. + +> You can specify your own name to each parameter + +> Eg. `my_device.addNameParam("NickName")` here name parameter is referred with name NickName. +> Eg. `my_device.addPowerParam(true, "FanPower")` here power parameter is referred with name FanPower. + +``` +esp_err_t addNameParam(const char *param_name = ESP_RMAKER_DEF_NAME_PARAM); +esp_err_t addPowerParam(bool val, const char *param_name = ESP_RMAKER_DEF_POWER_NAME); +esp_err_t addBrightnessParam(int val, const char *param_name = ESP_RMAKER_DEF_BRIGHTNESS_NAME); +esp_err_t addHueParam(int val, const char *param_name = ESP_RMAKER_DEF_HUE_NAME); +esp_err_t addSaturationParam(int val, const char *param_name = ESP_RMAKER_DEF_SATURATION_NAME); +esp_err_t addIntensityParam(int val, const char *param_name = ESP_RMAKER_DEF_INTENSITY_NAME); +esp_err_t addCCTParam(int val, const char *param_name = ESP_RMAKER_DEF_CCT_NAME); +esp_err_t addDirectionParam(int val, const char *param_name = ESP_RMAKER_DEF_DIRECTION_NAME); +esp_err_t addSpeedParam(int val, const char *param_name = ESP_RMAKER_DEF_SPEED_NAME); +esp_err_t addTempratureParam(float val, const char *param_name = ESP_RMAKER_DEF_TEMPERATURE_NAME); +``` +* **Standard Parameters** + +* These are the standard parameters. + * Name : ESP_RMAKER_DEF_NAME_PARAM + * Power : ESP_RMAKER_DEF_POWER_NAME + * Brightness : ESP_RMAKER_DEF_BRIGHTNESS_NAME + * Hue : ESP_RMAKER_DEF_HUE_NAME + * Saturation : ESP_RMAKER_DEF_SATURATION_NAME + * Intensity : ESP_RMAKER_DEF_INTENSITY_NAME + * CCT : ESP_RMAKER_DEF_CCT_NAME + * Direction : ESP_RMAKER_DEF_DIRECTION_NAME + * Speed : ESP_RMAKER_DEF_SPEED_NAME + * Temperature : ESP_RMAKER_DEF_TEMPERATURE_NAME +> NOTE : Care should be taken while accessing name of parameter. Above mentioned are the two ways using which default name of parameters can be accessed. Either LHS or RHS. + +### my_device.assignPrimaryParam() +It assigns a parameter (already added using addXParam() or addParam()) as a primary parameter, which can be used by clients (phone apps specifically) to give prominence to it. +``` +esp_err_t assignPrimaryParam(param_handle_t *param); +``` +* **Parameter** +1. `param` : Handle of the parameter. It is obtained using `my_device.getParamByName()`. +``` +param_handle_t * getParamByName(const char *param_name); +``` +> NOTE : +> `param_name` : It is the name of the parameter which was added using addXparam() or addParam(). + +### my_device.addParam() +It allows user to add custom parameter to the device created using `Param` class. +``` +esp_err_t addParam(Param parameter); +``` +* **Parameter** +1. `parameter` : Object of Param + +* **Return** +1. ESP_OK : On success +2. Error in case of failure +> NOTE : Param class exposes API's to create the custom parameter. + +### my_device.updateAndReportParam() +It updates the parameter assosicated with particular device on ESP RainMaker cloud. +``` +esp_err_t updateAndReportParam(const char *param_name, value); +``` +* **Parameters** +1. `param_name` : Name of the parameter +2. `value` : Value to be updated. It can be int, bool, char * , float. + +* **Return** +1. `ESP_OK` : On success +2. Error in case of failure + +### my_device.addCb() +It registers read and write callback for the device which will be invoked as per requests received from the cloud (or other paths as may be added in future). +``` +void addCb(deviceWriteCb write_cb, deviceReadCb read_cb); +``` +* **Parameters** +1. `write_cb` : Function with signature [ func_name(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx); ] +2. `read_cb` : Function with signature [ func_name(Device *device, Param *param, void *priv_data, read_ctx_t *ctx); ] + +* **param_val_t val** +Value can be accessed as below +1. `bool` : val.val.b +2. `integer` : val.val.i +3. `float` : val.val.f +4. `char *` : val.val.s + +## ESP RainMaker PARAM API's +`Param` class expose API's for creating custom parameters for the devices and report and update values associated with parameter to the ESP RainMaker cloud. Parameterized constructor is defined which creates custom parameter. +> NOTE : my_param is the object of Param class. + +``` +Param my_param(const char *param_name, const char *param_type, param_val_t val, uint8_t properties); +``` +* **Parameters** +1. `param_name` : Name of the parameter +2. `param_type` : Type of the parameter. It is optional can be kept NULL. +3. `val` : Define the default value for the parameter. It should be defined using `value(int ival)` , `value(bool bval)` , `value(float fval)` , `value(char *sval)`. +4. `properties` : Properties of the parameter, which will be a logical OR of flags. + * Flags + * PROP_FLAG_WRITE + * PROP_FLAG_READ + * PROP_FLAG_TIME_SERIES + * PROP_FLAG_PERSIST + +`Sample example : Param my_param("bright", NULL, value(30), PROP_FLAG_READ | PROP_FLAG_WRITE | PROP_FLAG_PERSIST);` +> NOTE : Parameter created using Param class should be added to the device using `my_device.addParam(my_param);` + +### my_param.addUIType() +Add a UI type to the parameter. This will be used by the Phone apps (or other clients) to render appropriate UI for the given parameter. Please refer the RainMaker documentation [here](https://rainmaker.espressif.com/docs/standard-types.html#ui-elements) for supported UI Types. +``` +esp_err_t addUIType(const char *ui_type); +``` +* **Paramter** +1. `ui_type` : String describing the UI Type. + * Standard UI Types + * ESP_RMAKER_UI_TOGGLE + * ESP_RMAKER_UI_SLIDER + * ESP_RMAKER_UI_DROPDOWN + * ESP_RMAKER_UI_TEXT + +* **Returns** +1. ESP_OK : On success. +2. Error in case of failure. + +### my_param.addBounds() +Add bounds for an integer/float parameter. This can be used to add bounds (min/max values) for a given integer/float parameter. Eg. brightness will have bounds as 0 and 100 if it is a percentage. +``` +esp_err_t addBounds(param_val_t min, param_val_t max, param_val_t step); +``` +* **Parameters** +1. `min` : Minimum value +2. `max` : Maximum value +3. `step` : step Minimum stepping + +* **Returns** +1. ESP_OK : On success. +2. Error in case of failure. + +`Sample example : my_param.addBounds(value(0), value(100), value(5));` + +### my_param.updateAndReport() +It updates the parameter and report it to ESP RainMaker cloud. This is called in callback. +``` +esp_err_t updateAndReport(param_val_t val); +``` +* **Parameters** +1. `val` : New value of the parameter + +* **Return** +1. ESP_OK : On success. +2. Error in case of failure. + +> NOTE : +> - This API should always be called inside device write callback, if you aimed at updating n reporting parameter values, changed via RainMaker Client (Phone App), to the ESP RainMaker cloud. +> - If not called then paramter values will not be updated to the ESP RainMaker cloud. + +### printQR() +This API displays QR code, which is used in provisioning. +``` +printQR(const char *serv_name, const char *pop, const char *transport); +``` +* **Parameters** +1. `name` : Service name used in provisioning API. +2. `pop` : Proof of posession used in provisioning API. +3. `transport` : + 1. `softap` : In case of provisioning using SOFTAP. + 2. `ble` : In case of provisioning using BLE. + +### RMakerFactoryReset() +Reset the device to factory defaults. + +``` +RMakerFactoryReset(2); +``` +* **Parameters** +1. `seconds` : Time in seconds after which the chip should reboot after doing a factory reset. + + +### RMakerWiFiReset() +Reset Wi-Fi credentials. +``` +RMakerWiFiReset(2); +``` + +* **Parameters** +1. `seconds` : Time in seconds after which the chip should reboot after doing a Wi-Fi reset. diff --git a/libraries/RainMaker/examples/README.md b/libraries/RainMaker/examples/README.md index e7e636ab..6c5bded0 100644 --- a/libraries/RainMaker/examples/README.md +++ b/libraries/RainMaker/examples/README.md @@ -1,434 +1,10 @@ -# APIs Introduced in ESP RainMaker Library +# ESP RainMaker Examples -IMPORTANT NOTE -=============== -1. Change partition scheme at Arduino IDE to RainMaker (Tools -> Partition Scheme -> RainMaker). +While building any examples for ESP RainMaker, take care of the following: +1. Change partition scheme in Arduino IDE to RainMaker (Tools -> Partition Scheme -> RainMaker). 2. Once ESP RainMaker gets started, compulsorily call `WiFi.beginProvision()` which is responsible for user-node mapping. -3. Care should be taken while calling provisioning API w.r.t to board used. - 1. ESP32 Board - Assisted claiming + BLE Provisioning - 2. ESP32S2 Board - Self Claiming + SOFTAP Provisioning +3. Use appropriate provisioning scheme as per the board. + - ESP32 Board: BLE Provisioning + - ESP32S2 Board: SoftAP Provisioning +4. Set debug level to Info (Tools -> Core Debug Level -> Info). This is recommended, but not mandatory. -## ESP RainMaker Agent API - -### RMaker.initNode() -This initializes the ESP RainMaker agent, wifi and creates the node. -``` -Node initNode(const char *name, const char *type); -``` -* **Parameters** -1. `name`: Name of the node -2. `type`: Type of the node - -* **Return** -1. Object of Node. - -* You can also set the configuration of the node using the following API - 1. RMaker.setTimeSync(bool val) -> NOTE: If you want to set the configuration for the node then these configuration API must be called before `RMaker.initNode()`. - -### RMaker.start() -It starts the ESP RainMaker agent. -``` -esp_err_t start() -``` -* **Return** -1. ESP_OK : On success -2. Error in case of failure - -> NOTE : -> 1. ESP RainMaker agent should be initialized before this call. -> 2. Once ESP RainMaker agent starts, compulsorily call WiFi.beginProvision() API. - -### RMaker.stop() -It stops the ESP RainMaker agent which was started using `RMaker.start()`. -``` -esp_err_t stop() -``` -* **Return** -1. ESP_OK : On success -2. Error in case of failure - -### RMaker.deinitNode() -It deinitializes the ESP RainMaker agent and the node created using `RMaker.initNode()`. -``` -esp_err_t deinitNode(Node node) -``` -* **Parameter** -1. `node` : Node object created using `RMaker.initNode()` -* **Return** -1. ESP_OK : On success -2. Error in case of failure - -### RMaker.enableOTA() -It enables OTA as per the ESP RainMaker Specification. For more details refer ESP RainMaker documentation. check [here](https://rainmaker.espressif.com/docs/ota.html) -``` -esp_err_t enableOTA(ota_type_t type); -``` -* **Parameter** -1. `type` : The OTA workflow type. - - OTA_USING_PARAMS - - OTA_USING_TOPICS -* **Return** -1. ESP_OK : On success -2. Error in case of failure - -### RMaker.enableSchedule() -This API enables the scheduling service for the node. For more information, check [here](https://rainmaker.espressif.com/docs/scheduling.html). -``` -esp_err_t enableSchedule(); -``` -* **Return** -1. ESP_OK : On success -2. Error in case of failure - -### RMaker.setTimeZone() -This API set's the timezone as a user friendly location string. Check [here](https://rainmaker.espressif.com/docs/time-service.html) for a list of valid values. -``` -esp_err_t setTimeZone(const char *tz); -``` -* **Parameter** -1. `tz' : Valid values as specified in documentation. - -* **Return** -1. ESP_OK : On success -2. Error in case of failure -> NOTE : default value is "Asia/Shanghai". -> This API comes into picture only when working with scheduling. - -## ESP RainMaker NODE APIs -`Node` class expose API's for node. -> NOTE : my_node is the object of Node class. - -### my_node.getNodeID() -It returns the unique node_id assigned to the node. This node_id is usually the MAC address of the board. -``` -char * getNodeID() -``` -* **Return** -1. `char * ` : Pointer to a NULL terminated node_id string. - -### my_node.getNodeInfo() -It returns pointer to the node_info_t as configured during node initialisation. -``` -node_info_t * getNodeInfo(); -``` -* **Return** -1. `node_info_t` : Pointer to the structure node_info_t on success. -2. `NULL` : On failure. - -* **ESP RainMaker node info** -It has following data member -1. char * name -2. char * type -3. char * fw_version -4. char * model - -### my_node.addNodeAttr() -It adds a new attribute as the metadata to the node. -``` -esp_err_t addNodeAttr(const char *attr_name, const char *val); -``` -* **Parameters** -1. `attr_name` : Name of the attribute -2. `val` : Value of the attribute - -* **Return** -1. `ESP_OK` : On success -2. Error in case of failure - -> NOTE : Only string values are allowed. - -### my_node.addDevice() -It adds a device to the node. -``` -esp_err_t addDevice(Device device); -``` -* **Parameter** -1. `device` : Device object - -* **Return** -1. `ESP_OK` : On success -2. Error in case of failure - -> NOTE : -> - This is the mandatory API to register device to node. -> - Single Node can have multiple devices. -> - Device name should be unique for each device. - -### my_node.removeDevice() -It removes a device from the node. -``` -esp_err_t removeDevice(Device device); -``` -* **Parameter** -1. `device` : Device object - -* **Return** -1. `ESP_OK` : On success -2. Error in case of failure - -## ESP RainMaker DEVICE API's -`Device` class expose API's for virtual devices on the node. -Parameterized constructor is defined which creates the virtual device on the node. Using Device class object you can create your own device. -> NOTE : my_device is the object of Device class -``` -Device my_device(const char *dev_name, const char *dev_type, void *priv_data); -``` -* **Parameters** -1. `dev_name` : Unique device name -2. `dev_type` : Optional device type. It can be kept NULL. - * Standard Device Types - * ESP_RMAKER_DEVICE_SWITCH - * ESP_RMAKER_DEVICE_LIGHTBULB - * ESP_RMAKER_DEVICE_FAN - * ESP_RMAKER_DEVICE_TEMP_SENSOR -3. `priv_data` : Private data associated with the device. This will be passed to the callbacks. - -> NOTE : This created device should be added to the node using `my_node.addDevice(my_device)`. - -- Sample example -``` -Device my_device("Switch"); -Device my_device("Switch1", NULL, NULL); -``` -> Here, dev_name is compulsory, rest are optional. -> Node can have multiple device, each device should have unique device name. - -### Standard Device -- Classes are defined for the standard devices. -- Creating object of these class creates the standard device with default parameters to it. -- Class for standard devices - * Switch - * LightBulb - * TemperatureSensor - * Fan -``` -Switch my_switch(const char *dev_name, void *priv_data, bool power); -``` -* **Parameters** -1. `dev_name` : Unique device name by default it is "switch" for switch device. -2. `priv_data` : Private data associated with the device. This will be passed to the callbacks. -3. `power` : It is the value that can be set for primary parameter. - -- Sample example for standard device. -``` -Switch switch1; -Switch switch2("switch2", NULL, true); -``` -`"switch2"` : Name for standard device. - -`NULL` : Private data for the device, which will be used in callback. - -`true` : Default value for the primary param, in case of switch it is power. - -> NOTE : No parameter are compulsory for standard devices. However if you are creating two objects of same standard class then in that case you will have to set the device name, if not then both device will have same name which is set by default, hence device will not get create. Device name should be unique for each device. - -### my_device.getDeviceName() -It returns the name of the Device. -``` -const char * getDeviceName(); -``` -* **Return** -1. `char *`: Returns Device name. - -> NOTE : Each device on the node should have unique device name. - -### my_device.addDeviceAttr() -It adds attribute to the device. Device attributes are reported only once after a boot-up as part of the node configuration. Eg. Serial Number -``` -esp_err_t addDeviceAttr(const char *attr_name, const char *val); -``` -* **Parameters** -1. `attr_name` : Name of the attribute -2. `val` : Value of the attribute - -* **Return** -1. `ESP_OK` : On success -2. Error in case of failure - -### my_device.deleteDevice() -It deletes the device created using parameterized constructor. This device should be first removed from the node using `my_node.removeDevice(my_device)`. -``` -esp_err_t deleteDevice(); -``` -* **Return** -1. `ESP_OK` : On success -2. Error in case of failure - -### my_device.addXParam() -It adds standard parameter to the device. -> NOTE : X is the default name by which parameter is referred, you can specify your own name to each parameter. - -> Default - -> Eg. `my_device.addPowerParam(true)` here power parameter is referred with name Power. -> Eg. `my_device.addHueParam(12)` here hue parameter is referred with name Hue. - -> You can specify your own name to each parameter - -> Eg. `my_device.addNameParam("NickName")` here name parameter is referred with name NickName. -> Eg. `my_device.addPowerParam(true, "FanPower")` here power parameter is referred with name FanPower. - -``` -esp_err_t addNameParam(const char *param_name = ESP_RMAKER_DEF_NAME_PARAM); -esp_err_t addPowerParam(bool val, const char *param_name = ESP_RMAKER_DEF_POWER_NAME); -esp_err_t addBrightnessParam(int val, const char *param_name = ESP_RMAKER_DEF_BRIGHTNESS_NAME); -esp_err_t addHueParam(int val, const char *param_name = ESP_RMAKER_DEF_HUE_NAME); -esp_err_t addSaturationParam(int val, const char *param_name = ESP_RMAKER_DEF_SATURATION_NAME); -esp_err_t addIntensityParam(int val, const char *param_name = ESP_RMAKER_DEF_INTENSITY_NAME); -esp_err_t addCCTParam(int val, const char *param_name = ESP_RMAKER_DEF_CCT_NAME); -esp_err_t addDirectionParam(int val, const char *param_name = ESP_RMAKER_DEF_DIRECTION_NAME); -esp_err_t addSpeedParam(int val, const char *param_name = ESP_RMAKER_DEF_SPEED_NAME); -esp_err_t addTempratureParam(float val, const char *param_name = ESP_RMAKER_DEF_TEMPERATURE_NAME); -``` -* **Standard Parameters** - -* These are the standard parameters. - * Name : ESP_RMAKER_DEF_NAME_PARAM - * Power : ESP_RMAKER_DEF_POWER_NAME - * Brightness : ESP_RMAKER_DEF_BRIGHTNESS_NAME - * Hue : ESP_RMAKER_DEF_HUE_NAME - * Saturation : ESP_RMAKER_DEF_SATURATION_NAME - * Intensity : ESP_RMAKER_DEF_INTENSITY_NAME - * CCT : ESP_RMAKER_DEF_CCT_NAME - * Direction : ESP_RMAKER_DEF_DIRECTION_NAME - * Speed : ESP_RMAKER_DEF_SPEED_NAME - * Temperature : ESP_RMAKER_DEF_TEMPERATURE_NAME -> NOTE : Care should be taken while accessing name of parameter. Above mentioned are the two ways using which default name of parameters can be accessed. Either LHS or RHS. - -### my_device.assignPrimaryParam() -It assigns a parameter (already added using addXParam() or addParam()) as a primary parameter, which can be used by clients (phone apps specifically) to give prominence to it. -``` -esp_err_t assignPrimaryParam(param_handle_t *param); -``` -* **Parameter** -1. `param` : Handle of the parameter. It is obtained using `my_device.getParamByName()`. -``` -param_handle_t * getParamByName(const char *param_name); -``` -> NOTE : -> `param_name` : It is the name of the parameter which was added using addXparam() or addParam(). - -### my_device.addParam() -It allows user to add custom parameter to the device created using `Param` class. -``` -esp_err_t addParam(Param parameter); -``` -* **Parameter** -1. `parameter` : Object of Param - -* **Return** -1. ESP_OK : On success -2. Error in case of failure -> NOTE : Param class exposes API's to create the custom parameter. - -### my_device.updateAndReportParam() -It updates the parameter assosicated with particular device on ESP RainMaker cloud. -``` -esp_err_t updateAndReportParam(const char *param_name, value); -``` -* **Parameters** -1. `param_name` : Name of the parameter -2. `value` : Value to be updated. It can be int, bool, char * , float. - -* **Return** -1. `ESP_OK` : On success -2. Error in case of failure - -### my_device.addCb() -It registers read and write callback for the device which will be invoked as per requests received from the cloud (or other paths as may be added in future). -``` -void addCb(deviceWriteCb write_cb, deviceReadCb read_cb); -``` -* **Parameters** -1. `write_cb` : Function with signature [ func_name(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx); ] -2. `read_cb` : Function with signature [ func_name(Device *device, Param *param, void *priv_data, read_ctx_t *ctx); ] - -* **param_val_t val** -Value can be accessed as below -1. `bool` : val.val.b -2. `integer` : val.val.i -3. `float` : val.val.f -4. `char *` : val.val.s - -## ESP RainMaker PARAM API's -`Param` class expose API's for creating custom parameters for the devices and report and update values associated with parameter to the ESP RainMaker cloud. Parameterized constructor is defined which creates custom parameter. -> NOTE : my_param is the object of Param class. - -``` -Param my_param(const char *param_name, const char *param_type, param_val_t val, uint8_t properties); -``` -* **Parameters** -1. `param_name` : Name of the parameter -2. `param_type` : Type of the parameter. It is optional can be kept NULL. -3. `val` : Define the default value for the parameter. It should be defined using `value(int ival)` , `value(bool bval)` , `value(float fval)` , `value(char *sval)`. -4. `properties` : Properties of the parameter, which will be a logical OR of flags. - * Flags - * PROP_FLAG_WRITE - * PROP_FLAG_READ - * PROP_FLAG_TIME_SERIES - * PROP_FLAG_PERSIST - -`Sample example : Param my_param("bright", NULL, value(30), PROP_FLAG_READ | PROP_FLAG_WRITE | PROP_FLAG_PERSIST);` -> NOTE : Parameter created using Param class should be added to the device using `my_device.addParam(my_param);` - -### my_param.addUIType() -Add a UI type to the parameter. This will be used by the Phone apps (or other clients) to render appropriate UI for the given parameter. Please refer the RainMaker documentation [here](https://rainmaker.espressif.com/docs/standard-types.html#ui-elements) for supported UI Types. -``` -esp_err_t addUIType(const char *ui_type); -``` -* **Paramter** -1. `ui_type` : String describing the UI Type. - * Standard UI Types - * ESP_RMAKER_UI_TOGGLE - * ESP_RMAKER_UI_SLIDER - * ESP_RMAKER_UI_DROPDOWN - * ESP_RMAKER_UI_TEXT - -* **Returns** -1. ESP_OK : On success. -2. Error in case of failure. - -### my_param.addBounds() -Add bounds for an integer/float parameter. This can be used to add bounds (min/max values) for a given integer/float parameter. Eg. brightness will have bounds as 0 and 100 if it is a percentage. -``` -esp_err_t addBounds(param_val_t min, param_val_t max, param_val_t step); -``` -* **Parameters** -1. `min` : Minimum value -2. `max` : Maximum value -3. `step` : step Minimum stepping - -* **Returns** -1. ESP_OK : On success. -2. Error in case of failure. - -`Sample example : my_param.addBounds(value(0), value(100), value(5));` - -### my_param.updateAndReport() -It updates the parameter and report it to ESP RainMaker cloud. This is called in callback. -``` -esp_err_t updateAndReport(param_val_t val); -``` -* **Parameters** -1. `val` : New value of the parameter - -* **Return** -1. ESP_OK : On success. -2. Error in case of failure. - -> NOTE : -> - This API should always be called inside device write callback, if you aimed at updating n reporting parameter values, changed via RainMaker Client (Phone App), to the ESP RainMaker cloud. -> - If not called then paramter values will not be updated to the ESP RainMaker cloud. - -### printQR() -This API displays QR code, which is used in provisioning. -``` -printQR(const char *serv_name, const char *pop, const char *transport); -``` -* **Parameters** -1. `name` : Service name used in provisioning API. -2. `pop` : Proof of posession used in provisioning API. -3. `transport` : - 1. `softap` : In case of provisioning using SOFTAP. - 2. `ble` : In case of provisioning using BLE. diff --git a/libraries/RainMaker/examples/RMakerDevice/.skip.esp32c3 b/libraries/RainMaker/examples/RMakerCustom/.skip.esp32c3 similarity index 100% rename from libraries/RainMaker/examples/RMakerDevice/.skip.esp32c3 rename to libraries/RainMaker/examples/RMakerCustom/.skip.esp32c3 diff --git a/libraries/RainMaker/examples/RMakerDevice/.skip.esp32s2 b/libraries/RainMaker/examples/RMakerCustom/.skip.esp32s2 similarity index 100% rename from libraries/RainMaker/examples/RMakerDevice/.skip.esp32s2 rename to libraries/RainMaker/examples/RMakerCustom/.skip.esp32s2 diff --git a/libraries/RainMaker/examples/RMakerCustom/README.md b/libraries/RainMaker/examples/RMakerCustom/README.md new file mode 100644 index 00000000..62a5017e --- /dev/null +++ b/libraries/RainMaker/examples/RMakerCustom/README.md @@ -0,0 +1,27 @@ +# ESP RainMaker Switch + +This example demonstrates how to build a switch device to be used with ESP RainMaker. + +## What to expect in this example? + +- This example sketch uses the on board Boot button and GPIO16 to demonstrate an ESP RainMaker switch device. +- After compiling and flashing the example, add your device using the [ESP RainMaker phone apps](https://rainmaker.espressif.com/docs/quick-links.html#phone-apps) by scanning the QR code. +- Toggling the state from the phone app will toggle the switch state (GPIO16). +- Pressing the Boot button will toggle the switch state (GPIO16) and the same will reflect on the phone app. + +### Output + +``` +[ 63][I][RMaker.cpp:13] event_handler(): RainMaker Initialised. +[ 69][I][WiFiProv.cpp:158] beginProvision(): Already Provisioned +[ 69][I][WiFiProv.cpp:162] beginProvision(): Attempting connect to AP: Viking007_2GEXT + +Toggle State to false. +[ 8182][I][RMakerDevice.cpp:162] updateAndReportParam(): Device : Switch, Param Name : Power, Val : false +Toggle State to true. +[ 9835][I][RMakerDevice.cpp:162] updateAndReportParam(): Device : Switch, Param Name : Power, Val : true +Received value = false for Switch - Power +Received value = true for Switch - Power +Toggle State to false. +[ 29937][I][RMakerDevice.cpp:162] updateAndReportParam(): Device : Switch, Param Name : Power, Val : false +``` diff --git a/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino b/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino new file mode 100644 index 00000000..55012e41 --- /dev/null +++ b/libraries/RainMaker/examples/RMakerCustom/RMakerCustom.ino @@ -0,0 +1,126 @@ +//This example demonstrates the ESP RainMaker with a custom device +#include "RMaker.h" +#include "WiFi.h" +#include "WiFiProv.h" + +#define DEFAULT_POWER_MODE true +#define DEFAULT_DIMMER_LEVEL 50 +const char *service_name = "PROV_1234"; +const char *pop = "abcd1234"; + +//GPIO for push button +static int gpio_0 = 0; +//GPIO for virtual device +static int gpio_dimmer = 16; +/* Variable for reading pin status*/ +bool dimmer_state = true; + +// The framework provides some standard device types like switch, lightbulb, fan, temperature sensor. +// But, you can also define custom devices using the 'Device' base class object, as shown here +static Device my_device("Dimmer", "custom.device.dimmer", &gpio_dimmer); + +void sysProvEvent(arduino_event_t *sys_event) +{ + switch (sys_event->event_id) { + case ARDUINO_EVENT_PROV_START: +#if CONFIG_IDF_TARGET_ESP32 + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); + printQR(service_name, pop, "ble"); +#else + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); + printQR(service_name, pop, "softap"); +#endif + break; + } +} + +void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx) +{ + const char *device_name = device->getDeviceName(); + const char *param_name = param->getParamName(); + + if(strcmp(param_name, "Power") == 0) { + Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); + dimmer_state = val.val.b; + (dimmer_state == false) ? digitalWrite(gpio_dimmer, LOW) : digitalWrite(gpio_dimmer, HIGH); + param->updateAndReport(val); + } else if (strcmp(param_name, "Level") == 0) { + Serial.printf("\nReceived value = %d for %s - %s\n", val.val.i, device_name, param_name); + param->updateAndReport(val); + } +} + +void setup() +{ + Serial.begin(115200); + pinMode(gpio_0, INPUT); + pinMode(gpio_dimmer, OUTPUT); + digitalWrite(gpio_dimmer, DEFAULT_POWER_MODE); + + Node my_node; + my_node = RMaker.initNode("ESP RainMaker Node"); + + //Create custom dimmer device + my_device.addNameParam(); + my_device.addPowerParam(DEFAULT_POWER_MODE); + my_device.assignPrimaryParam(my_device.getParamByName(ESP_RMAKER_DEF_POWER_NAME)); + + //Create and add a custom level parameter + Param level_param("Level", "custom.param.level", value(DEFAULT_DIMMER_LEVEL), PROP_FLAG_READ | PROP_FLAG_WRITE); + level_param.addBounds(value(0), value(100), value(1)); + level_param.addUIType(ESP_RMAKER_UI_SLIDER); + my_device.addParam(level_param); + + my_device.addCb(write_callback); + + //Add custom dimmer device to the node + my_node.addDevice(my_device); + + //This is optional + RMaker.enableOTA(OTA_USING_PARAMS); + //If you want to enable scheduling, set time zone for your region using setTimeZone(). + //The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html + // RMaker.setTimeZone("Asia/Shanghai"); + // Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone + RMaker.enableTZService(); + + RMaker.enableSchedule(); + + RMaker.start(); + + WiFi.onEvent(sysProvEvent); +#if CONFIG_IDF_TARGET_ESP32 + WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name); +#else + WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); +#endif +} + +void loop() +{ + if(digitalRead(gpio_0) == LOW) { //Push button pressed + + // Key debounce handling + delay(100); + int startTime = millis(); + while(digitalRead(gpio_0) == LOW) delay(50); + int endTime = millis(); + + if ((endTime - startTime) > 10000) { + // If key pressed for more than 10secs, reset all + Serial.printf("Reset to factory.\n"); + RMakerFactoryReset(2); + } else if ((endTime - startTime) > 3000) { + Serial.printf("Reset Wi-Fi.\n"); + // If key pressed for more than 3secs, but less than 10, reset Wi-Fi + RMakerWiFiReset(2); + } else { + // Toggle device state + dimmer_state = !dimmer_state; + Serial.printf("Toggle State to %s.\n", dimmer_state ? "true" : "false"); + my_device.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, dimmer_state); + (dimmer_state == false) ? digitalWrite(gpio_dimmer, LOW) : digitalWrite(gpio_dimmer, HIGH); + } + } + delay(100); +} diff --git a/libraries/RainMaker/examples/RMakerDevice/README.md b/libraries/RainMaker/examples/RMakerDevice/README.md deleted file mode 100644 index aec39129..00000000 --- a/libraries/RainMaker/examples/RMakerDevice/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Switch Example - -## Compile n Flash firmware - -### ESP32 Board -- Assisted Claiming + BLE Provisioning - -## What to expect in this sketch ? -### It demonstartes the toggling of power of devices using phone app and BOOT button. - -- Switch and Fan are the dummy device. Switch connected at gpio(16) and Fan connected at gpio(17). -- Toggling the power button for any device(switch/fan) on phone app will change the status(on/off) for the device connected at gpio(16/17) and also update the status to the ESP RainMaker cloud if `param.updateAndReport(val)` API is called. -- Pressing the BOOT button toggles the status(on/off) of both device(switch & fan) connected at gpio(16/17) and report values to the cloud. - -### Output - -``` -[I][WiFiProv.cpp:179] beginProvision(): Already Provisioned -[I][WiFiProv.cpp:183] beginProvision(): Attempting connect to AP: Wce***** - -Received value = false for Switch - Power - -Received value = false for Fan - Power - -Received value = true for Switch - Power - -[I][RMakerDevice.cpp:161] updateAndReportParam(): Device : Switch, Param Name : Power, Val : false - -[I][RMakerDevice.cpp:161] updateAndReportParam(): Device : Fan, Param Name : Power, Val : true - -Received value = true for Switch - Power - -Received value = false for Fan - Power -``` diff --git a/libraries/RainMaker/examples/RMakerSwitch/.skip.esp32c3 b/libraries/RainMaker/examples/RMakerSwitch/.skip.esp32c3 new file mode 100644 index 00000000..e69de29b diff --git a/libraries/RainMaker/examples/RMakerSwitch/.skip.esp32s2 b/libraries/RainMaker/examples/RMakerSwitch/.skip.esp32s2 new file mode 100644 index 00000000..e69de29b diff --git a/libraries/RainMaker/examples/RMakerSwitch/README.md b/libraries/RainMaker/examples/RMakerSwitch/README.md new file mode 100644 index 00000000..62a5017e --- /dev/null +++ b/libraries/RainMaker/examples/RMakerSwitch/README.md @@ -0,0 +1,27 @@ +# ESP RainMaker Switch + +This example demonstrates how to build a switch device to be used with ESP RainMaker. + +## What to expect in this example? + +- This example sketch uses the on board Boot button and GPIO16 to demonstrate an ESP RainMaker switch device. +- After compiling and flashing the example, add your device using the [ESP RainMaker phone apps](https://rainmaker.espressif.com/docs/quick-links.html#phone-apps) by scanning the QR code. +- Toggling the state from the phone app will toggle the switch state (GPIO16). +- Pressing the Boot button will toggle the switch state (GPIO16) and the same will reflect on the phone app. + +### Output + +``` +[ 63][I][RMaker.cpp:13] event_handler(): RainMaker Initialised. +[ 69][I][WiFiProv.cpp:158] beginProvision(): Already Provisioned +[ 69][I][WiFiProv.cpp:162] beginProvision(): Attempting connect to AP: Viking007_2GEXT + +Toggle State to false. +[ 8182][I][RMakerDevice.cpp:162] updateAndReportParam(): Device : Switch, Param Name : Power, Val : false +Toggle State to true. +[ 9835][I][RMakerDevice.cpp:162] updateAndReportParam(): Device : Switch, Param Name : Power, Val : true +Received value = false for Switch - Power +Received value = true for Switch - Power +Toggle State to false. +[ 29937][I][RMakerDevice.cpp:162] updateAndReportParam(): Device : Switch, Param Name : Power, Val : false +``` diff --git a/libraries/RainMaker/examples/RMakerDevice/RMakerDevice.ino b/libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino similarity index 52% rename from libraries/RainMaker/examples/RMakerDevice/RMakerDevice.ino rename to libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino index 44182964..e486bd20 100644 --- a/libraries/RainMaker/examples/RMakerDevice/RMakerDevice.ino +++ b/libraries/RainMaker/examples/RMakerSwitch/RMakerSwitch.ino @@ -1,34 +1,31 @@ -//This example demonstrates the ESP RainMaker with the custom device and standard Switch device. +//This example demonstrates the ESP RainMaker with a standard Switch device. #include "RMaker.h" #include "WiFi.h" #include "WiFiProv.h" -#define DEFAULT_FAN_SPEED 4 #define DEFAULT_POWER_MODE true -const char *service_name = "Prov_1234"; +const char *service_name = "PROV_1234"; const char *pop = "abcd1234"; //GPIO for push button static int gpio_0 = 0; //GPIO for virtual device static int gpio_switch = 16; -static int gpio_fan = 17; /* Variable for reading pin status*/ bool switch_state = true; -bool fan_state = true; //The framework provides some standard device types like switch, lightbulb, fan, temperaturesensor. static Switch my_switch("Switch", &gpio_switch); -//You can also define custom devices using the 'Device' base class object, as shown here -static Device my_device("Fan", ESP_RMAKER_DEVICE_FAN, &gpio_fan); void sysProvEvent(arduino_event_t *sys_event) { switch (sys_event->event_id) { case ARDUINO_EVENT_PROV_START: #if CONFIG_IDF_TARGET_ESP32 + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop); printQR(service_name, pop, "ble"); #else + Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop); printQR(service_name, pop, "softap"); #endif break; @@ -41,20 +38,11 @@ void write_callback(Device *device, Param *param, const param_val_t val, void *p const char *param_name = param->getParamName(); if(strcmp(param_name, "Power") == 0) { - Serial.printf("\nReceived value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); - if(strcmp(device_name, "Switch") == 0) { - switch_state = val.val.b; - (switch_state == false) ? digitalWrite(gpio_switch, LOW) : digitalWrite(gpio_switch, HIGH); - } - if(strcmp(device_name, "Fan") == 0) { - fan_state = val.val.b; - (fan_state == false) ? digitalWrite(gpio_fan, LOW) : digitalWrite(gpio_fan, HIGH); - } + Serial.printf("Received value = %s for %s - %s\n", val.val.b? "true" : "false", device_name, param_name); + switch_state = val.val.b; + (switch_state == false) ? digitalWrite(gpio_switch, LOW) : digitalWrite(gpio_switch, HIGH); + param->updateAndReport(val); } - else if(strcmp(param_name, "Speed") == 0) { - Serial.printf("\nReceived value = %d for %s - %s\n", val.val.i, device_name, param_name); - } - param->updateAndReport(val); } void setup() @@ -62,7 +50,7 @@ void setup() Serial.begin(115200); pinMode(gpio_0, INPUT); pinMode(gpio_switch, OUTPUT); - pinMode(gpio_fan, OUTPUT); + digitalWrite(gpio_switch, DEFAULT_POWER_MODE); Node my_node; my_node = RMaker.initNode("ESP RainMaker Node"); @@ -70,22 +58,17 @@ void setup() //Standard switch device my_switch.addCb(write_callback); - //Creating custom fan device - my_device.addNameParam(); - my_device.addPowerParam(DEFAULT_POWER_MODE); - my_device.addSpeedParam(DEFAULT_FAN_SPEED); - my_device.assignPrimaryParam(my_device.getParamByName(ESP_RMAKER_DEF_POWER_NAME)); - my_device.addCb(write_callback); - - //Add switch and fan device to the node + //Add switch device to the node my_node.addDevice(my_switch); - my_node.addDevice(my_device); //This is optional RMaker.enableOTA(OTA_USING_PARAMS); //If you want to enable scheduling, set time zone for your region using setTimeZone(). //The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html - RMaker.setTimeZone("Asia/Shanghai"); + // RMaker.setTimeZone("Asia/Shanghai"); + // Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone + RMaker.enableTZService(); + RMaker.enableSchedule(); RMaker.start(); @@ -96,18 +79,33 @@ void setup() #else WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name); #endif - } void loop() { - if(digitalRead(gpio_0) == LOW) { //Push button - switch_state = !switch_state; - fan_state = !fan_state; - my_switch.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, switch_state); - my_device.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, fan_state); - (switch_state == false) ? digitalWrite(gpio_switch, LOW) : digitalWrite(gpio_switch, HIGH); - (fan_state == false) ? digitalWrite(gpio_fan, LOW) : digitalWrite(gpio_fan, HIGH); + if(digitalRead(gpio_0) == LOW) { //Push button pressed + + // Key debounce handling + delay(100); + int startTime = millis(); + while(digitalRead(gpio_0) == LOW) delay(50); + int endTime = millis(); + + if ((endTime - startTime) > 10000) { + // If key pressed for more than 10secs, reset all + Serial.printf("Reset to factory.\n"); + RMakerFactoryReset(2); + } else if ((endTime - startTime) > 3000) { + Serial.printf("Reset Wi-Fi.\n"); + // If key pressed for more than 3secs, but less than 10, reset Wi-Fi + RMakerWiFiReset(2); + } else { + // Toggle device state + switch_state = !switch_state; + Serial.printf("Toggle State to %s.\n", switch_state ? "true" : "false"); + my_switch.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, switch_state); + (switch_state == false) ? digitalWrite(gpio_switch, LOW) : digitalWrite(gpio_switch, HIGH); + } } delay(100); } diff --git a/libraries/RainMaker/src/RMaker.cpp b/libraries/RainMaker/src/RMaker.cpp index f6f9559b..0a6239a1 100644 --- a/libraries/RainMaker/src/RMaker.cpp +++ b/libraries/RainMaker/src/RMaker.cpp @@ -92,6 +92,15 @@ esp_err_t RMakerClass::enableSchedule() return err; } +esp_err_t RMakerClass::enableTZService() +{ + err = esp_rmaker_timezone_service_enable(); + if(err != ESP_OK) { + log_e("Timezone service enable failed"); + } + return err; +} + esp_err_t RMakerClass::enableOTA(ota_type_t type, const char *cert) { esp_rmaker_ota_config_t ota_config; @@ -104,4 +113,4 @@ esp_err_t RMakerClass::enableOTA(ota_type_t type, const char *cert) } RMakerClass RMaker; -#endif \ No newline at end of file +#endif diff --git a/libraries/RainMaker/src/RMaker.h b/libraries/RainMaker/src/RMaker.h index 6efce38e..4a9ec4f6 100644 --- a/libraries/RainMaker/src/RMaker.h +++ b/libraries/RainMaker/src/RMaker.h @@ -4,6 +4,7 @@ #include "Arduino.h" #include "RMakerNode.h" #include "RMakerQR.h" +#include "RMakerUtils.h" #include class RMakerClass @@ -18,6 +19,7 @@ class RMakerClass esp_err_t deinitNode(Node node); esp_err_t setTimeZone(const char *tz = "Asia/Shanghai"); esp_err_t enableSchedule(); + esp_err_t enableTZService(); esp_err_t enableOTA(ota_type_t type, const char *cert = ESP_RMAKER_OTA_DEFAULT_SERVER_CERT); esp_err_t start(); esp_err_t stop(); @@ -25,4 +27,4 @@ class RMakerClass extern RMakerClass RMaker; -#endif \ No newline at end of file +#endif diff --git a/libraries/RainMaker/src/RMakerQR.h b/libraries/RainMaker/src/RMakerQR.h index 5dff1696..1cdeee16 100644 --- a/libraries/RainMaker/src/RMakerQR.h +++ b/libraries/RainMaker/src/RMakerQR.h @@ -16,9 +16,9 @@ static void printQR(const char *name, const char *pop, const char *transport) snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ ",\"pop\":\"%s\",\"transport\":\"%s\"}", PROV_QR_VERSION, name, pop, transport); - log_i("Scan this QR code from the phone app for Provisioning."); + Serial.printf("Scan this QR code from the ESP RainMaker phone app.\n"); qrcode_display(payload); - log_i("If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL, payload); + Serial.printf("If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s\n", QRCODE_BASE_URL, payload); } -#endif \ No newline at end of file +#endif diff --git a/libraries/RainMaker/src/RMakerUtils.h b/libraries/RainMaker/src/RMakerUtils.h new file mode 100644 index 00000000..671e600f --- /dev/null +++ b/libraries/RainMaker/src/RMakerUtils.h @@ -0,0 +1,16 @@ +#include "esp_system.h" +#if ESP_IDF_VERSION_MAJOR >= 4 && CONFIG_IDF_TARGET_ESP32 + +#include + +static void RMakerFactoryReset(int seconds) +{ + esp_rmaker_factory_reset(seconds); +} + +static void RMakerWiFiReset(int seconds) +{ + esp_rmaker_wifi_reset(seconds); +} + +#endif