/* GPIO Example This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include #include #include #include #include #include #include #include #include #include #include #include "app_priv.h" #include "esp_err.h" static const char *TAG = "app_main"; static const char *gpio_device_name = "GPIO"; static const char *rgb_device_name = "RGB-Light"; static const char *switch_device_name = "Switch"; esp_rmaker_device_t *gpio_device; esp_rmaker_device_t *light_device; esp_rmaker_device_t *switch_device; #ifdef CONFIG_ESP_RMAKER_CMD_RESP_ENABLE #include "json_parser.h" #include "esp_rmaker_cmd_resp.h" #include static char resp_data[100]; /* Callback to handle commands received from the RainMaker cloud via the Command - Response Framework * * Sample payloads: * - {"on":true} * - {"brightness":30} */ esp_err_t led_light_cmd_handler(const void *in_data, size_t in_len, void **out_data, size_t *out_len, esp_rmaker_cmd_ctx_t *ctx, void *priv_data) { if (in_data == NULL) { ESP_LOGE(TAG, "No data received"); return ESP_FAIL; } ESP_LOGI(TAG, "Received command: %s", (char *)in_data); jparse_ctx_t jctx; if (json_parse_start(&jctx, (char *)in_data, in_len) != 0) { snprintf(resp_data, sizeof(resp_data), "{\"status\":\"fail\", \"description\":\"Invalid JSON\"}"); } else { int brightness; bool on_state; if (json_obj_get_int(&jctx, "brightness", &brightness) == 0) { if (brightness < 0 || brightness > 100) { snprintf(resp_data, sizeof(resp_data), "{\"status\":\"fail\", \"description\":\"Invalid brightness value\"}"); } else { app_light_set_brightness(brightness); esp_rmaker_param_update_and_report( esp_rmaker_device_get_param_by_type(light_device, ESP_RMAKER_PARAM_BRIGHTNESS), esp_rmaker_int(brightness)); snprintf(resp_data, sizeof(resp_data), "{\"status\":\"success\"}"); } } else if (json_obj_get_bool(&jctx, "on", &on_state) == 0) { app_light_set_power(on_state); esp_rmaker_param_update_and_report( esp_rmaker_device_get_param_by_type(light_device, ESP_RMAKER_PARAM_POWER), esp_rmaker_bool(on_state)); snprintf(resp_data, sizeof(resp_data), "{\"status\":\"success\"}"); } else { snprintf(resp_data, sizeof(resp_data), "{\"status\":\"fail\", \"description\":\"Invalid param\"}"); } } *out_data = resp_data; *out_len = strlen(resp_data); return ESP_OK; } #endif /* CONFIG_ESP_RMAKER_CMD_RESP_ENABLE */ // Callback to handle param updates from the Rainmaker cloud static esp_err_t bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[], uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx) { if (ctx) { ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src)); } ESP_LOGI(TAG, "Light received %d params in write", count); for (int i = 0; i < count; i++) { const esp_rmaker_param_t *param = write_req[i].param; esp_rmaker_param_val_t val = write_req[i].val; const char *device_name = esp_rmaker_device_get_name(device); const char *param_name = esp_rmaker_param_get_name(param); if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) { ESP_LOGI(TAG, "Received value = %s for %s - %s", val.val.b ? "true" : "false", device_name, param_name); app_light_set_power(val.val.b); } else if (strcmp(param_name, ESP_RMAKER_DEF_BRIGHTNESS_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); app_light_set_brightness(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_HUE_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); app_light_set_hue(val.val.i); } else if (strcmp(param_name, ESP_RMAKER_DEF_SATURATION_NAME) == 0) { ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name); app_light_set_saturation(val.val.i); } else { ESP_LOGI(TAG, "Updating for %s", param_name); } esp_rmaker_param_update(param, val); } return ESP_OK; } /* Callback to handle commands received from the RainMaker cloud */ static esp_err_t 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) { if (ctx) { ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src)); } const char *device_name = esp_rmaker_device_get_name(device); // const char *param_name = esp_rmaker_param_get_name(param); esp_err_t ret = ESP_OK; if (strcmp(device_name, gpio_device_name) == 0) { ret = app_driver_set_gpio(esp_rmaker_param_get_name(param), val.val.b); } else if (strcmp(device_name, switch_device_name) == 0) { ret = app_switch_set_state(val.val.b); } else { ESP_LOGI(TAG, "Unexpected device %s", device_name); } if (ret == ESP_OK) esp_rmaker_param_update(param, val); return ESP_OK; } void app_main() { /* Initialize Application specific hardware drivers and * set initial state. */ app_driver_init(); /* Initialize NVS. */ esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK( err ); /* Initialize Wi-Fi. Note that, this should be called before esp_rmaker_node_init() */ app_network_init(); /* Initialize the ESP RainMaker Agent. * Note that this should be called after app_network_init() but before app_network_start() * */ esp_rmaker_config_t rainmaker_cfg = { .enable_time_sync = false, }; esp_rmaker_node_t *node = esp_rmaker_node_init(&rainmaker_cfg, "ESP RainMaker Multi Device", "Multi Device"); if (!node) { ESP_LOGE(TAG, "Could not initialise node. Aborting!!!"); vTaskDelay(5000/portTICK_PERIOD_MS); abort(); } /* Create a device and add the relevant parameters to it */ gpio_device = esp_rmaker_device_create(gpio_device_name, NULL, NULL); esp_rmaker_device_add_cb(gpio_device, write_cb, NULL); esp_rmaker_param_t *red_param = esp_rmaker_param_create(GPIO_DEVICE_OUT1_NAME, NULL, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(red_param, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(gpio_device, red_param); esp_rmaker_param_t *green_param = esp_rmaker_param_create(GPIO_DEVICE_OUT2_NAME, NULL, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(green_param, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(gpio_device, green_param); esp_rmaker_param_t *blue_param = esp_rmaker_param_create(GPIO_DEVICE_OUT3_NAME, NULL, esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE); esp_rmaker_param_add_ui_type(blue_param, ESP_RMAKER_UI_TOGGLE); esp_rmaker_device_add_param(gpio_device, blue_param); esp_rmaker_node_add_device(node, gpio_device); // Create the light device light_device = esp_rmaker_lightbulb_device_create(rgb_device_name, NULL, RGB_POWER_DEFAULT); esp_rmaker_device_add_bulk_cb(light_device, bulk_write_cb, NULL); esp_rmaker_device_add_param(light_device, esp_rmaker_brightness_param_create(ESP_RMAKER_DEF_BRIGHTNESS_NAME, RGB_BRIGHTNESS_DEFAULT)); esp_rmaker_device_add_param(light_device, esp_rmaker_hue_param_create(ESP_RMAKER_DEF_HUE_NAME, RGB_HUE_DEFAULT)); esp_rmaker_device_add_param(light_device, esp_rmaker_saturation_param_create(ESP_RMAKER_DEF_SATURATION_NAME, RGB_SATURATION_DEFAULT)); esp_rmaker_node_add_device(node, light_device); // Create the switch device switch_device = esp_rmaker_switch_device_create(switch_device_name, NULL, false); esp_rmaker_device_add_cb(switch_device, write_cb, NULL); esp_rmaker_node_add_device(node, switch_device); /* Enable OTA */ esp_rmaker_ota_enable_default(); /* Enable Insights. Requires CONFIG_ESP_INSIGHTS_ENABLED=y */ app_insights_enable(); #ifdef CONFIG_ESP_RMAKER_CMD_RESP_ENABLE /* Register the command response handler */ esp_rmaker_cmd_register(ESP_RMAKER_CMD_CUSTOM_START, ESP_RMAKER_USER_ROLE_PRIMARY_USER | ESP_RMAKER_USER_ROLE_SECONDARY_USER, led_light_cmd_handler, false, NULL); #endif /* CONFIG_ESP_RMAKER_CMD_RESP_ENABLE */ /* Start the ESP RainMaker Agent */ esp_rmaker_start(); err = app_network_set_custom_mfg_data(MGF_DATA_DEVICE_TYPE_LIGHT, MFG_DATA_DEVICE_SUBTYPE_LIGHT); /* Start the Wi-Fi. * If the node is provisioned, it will start connection attempts, * else, it will start Wi-Fi provisioning. The function will return * after a connection has been successfully established */ err = app_network_start(POP_TYPE_RANDOM); if (err != ESP_OK) { ESP_LOGE(TAG, "Could not start Wifi. Aborting!!!"); vTaskDelay(5000/portTICK_PERIOD_MS); abort(); } }