添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
idf_component_register(SRCS "app_main.c" "esp_local_ctrl_service.c"
INCLUDE_DIRS "."
EMBED_TXTFILES "certs/cacert.pem" "certs/prvtkey.pem")

View File

@@ -0,0 +1,20 @@
menu "Example Configuration"
config EXAMPLE_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config EXAMPLE_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config EXAMPLE_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
endmenu

View File

@@ -0,0 +1,145 @@
/* Local Ctrl 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 <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "lwip/err.h"
#include "lwip/sys.h"
/* The examples use WiFi configuration that you can set via 'idf.py menuconfig'.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_EXAMPLE_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_EXAMPLE_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_EXAMPLE_MAXIMUM_RETRY
/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;
/* The event group allows multiple bits for each event, but we only care about two events:
* - we are connected to the AP with an IP
* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static const char *TAG = "local_ctrl_example";
static int s_retry_num = 0;
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
} else {
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
ESP_LOGI(TAG,"connect to the AP fail");
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
esp_err_t wifi_init_sta(void)
{
esp_err_t ret_value = ESP_OK;
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.password = EXAMPLE_ESP_WIFI_PASS
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init_sta finished.");
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
ret_value = ESP_FAIL;
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
ret_value = ESP_ERR_INVALID_STATE;
}
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
vEventGroupDelete(s_wifi_event_group);
return ret_value;
}
/* Function responsible for configuring and starting the esp_local_ctrl service.
* See local_ctrl_service.c for implementation */
extern void start_esp_local_ctrl_service(void);
void app_main(void)
{
//Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
if (wifi_init_sta() == ESP_OK) {
start_esp_local_ctrl_service();
} else {
ESP_LOGI(TAG, "Connection failed, not starting esp_local_ctrl service");
}
}

View File

@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICrjCCAZYCCQDGnK9OU3UN2TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARy
b290MB4XDTIwMTExMDExMzExNVoXDTMwMTExMDExMzExNVowIzEhMB8GA1UEAwwY
bXlfZXNwX2N0cmxfZGV2aWNlLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA2NgeOgHTX6yURoB8u3BAphDMTlp/Ar8oAtoO+xqIPw1sZKmhJLAS
bfKkHKhi7pr/h31xOHqzTxlPkUzWpfszFx5YiDFYtiIlcObrgk83u3CtvBw7wuZ6
BA/01hkiSGgkAFD/xnRNLKgidTu1tCIa2QY7Jnp+HdJz6yJws1/WAzn2lsXcJwSd
6tPu2U0lhE2w6ylCdLYD3upveo/80WArQqNg6bv6Wbz8iL18E87enpwfHMA7ZN+S
sDq7HACRjapAkcimjbzkrh7/f9Nr6c8KpPyeiWyHFxVTbmEj4NMG9IpbTKp9CMAt
ysmiPYAYNFXsTHjoRVf4EbfHbxGHobUwewIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQBWg9Xh1MG4d4gGGx920OJBm+qQ9XY9oV2Aap81ZYshgBlnUKoKLhYolp/CHXyr
IXy7YA01ASX2wzohguqakdo0ghYkhwuRoly+0+uzphmqyMqXnTUDCgEcZF4l90xl
jRdMenqEgfOXDNk2VAK/rmAZ2jZsaGpBI4NRbEdwH1MVd61g2NVBk0nEI73cW6Ki
BPxMw2aGFizTwcPT9gwbQgLdLZeEuvcPrdzK5swqccZ+MBHMcwW/qvcmwqJGeLL2
zmx7o2ODQyElIKLKUDWAFIYrb7DXR4oajjhUa0+SOj9Ydj/5+eZ+Wx7NJoG+oH7N
DB0jK2qB8eexplQj1KLWS2Un
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDY2B46AdNfrJRG
gHy7cECmEMxOWn8CvygC2g77Gog/DWxkqaEksBJt8qQcqGLumv+HfXE4erNPGU+R
TNal+zMXHliIMVi2IiVw5uuCTze7cK28HDvC5noED/TWGSJIaCQAUP/GdE0sqCJ1
O7W0IhrZBjsmen4d0nPrInCzX9YDOfaWxdwnBJ3q0+7ZTSWETbDrKUJ0tgPe6m96
j/zRYCtCo2Dpu/pZvPyIvXwTzt6enB8cwDtk35KwOrscAJGNqkCRyKaNvOSuHv9/
02vpzwqk/J6JbIcXFVNuYSPg0wb0iltMqn0IwC3KyaI9gBg0VexMeOhFV/gRt8dv
EYehtTB7AgMBAAECggEBAJSvM6Kgp9fdVNo2tdAsOxfjQsOjB53RhtTVwhnpamyZ
fq5TJZwrYqejDWZdC2ECRJ4ZpG2OrK5a85T0s+Whpbl/ZEMWWvaf2T5eCDQUr2lF
7MqkLVIJiLaKXl4DY990EONqpsbj7hrluqLZ61B1ZiVTQXGz4g/+wt8CgXZtCyiv
7XOTTmQueugq4f54JBX5isdB7/xLaXV3kycaEK1b6ZVFYB3ii5IKKsX7RK/ksA6O
fRrQ8702prqphPfbjZ9wPHif/zLiyiF2FG6OX1Y3aZe1npRsvuH2c3M2h+HGAQUR
3lDxMTNbsE8E+XKZFVAVdMqot2RfxENSHoJHcp1R2YECgYEA9qe1+eOZKd0w5lC1
PuG6FLAAbK1nuv/ovESEHtILTLFkMijgAqcWjtp1klS86IBJLnjv+GYxZu2n1WI9
QLnh++NNTjRGCMM2Adf5SBJ/5F85rpgzz7Yur1guqkUQx/2dmErOaWQ4IO304VlM
vrJB8+XmAiysEgJOkK0Mx8xRVcECgYEA4Q9GBADLryvwjisp/PdTRXOvd7pJRGH3
SdC1k/nBsmpmbouc0ihqzOiiN0kUjE2yLSlhwxxWBJqNSzOk9z5/LB4TNRqH9gCL
rUN67FgzwR5H70OblWpcjWRurFq34+ZWEmCG+1qUwZMT7dYe4CiDYnVjcwfUpQwN
qRpjeMLDrTsCgYEAgo1CRIGzD/WDbGRLinzvgQOnNd6SiOfqx7t8MtP6Jx29as83
wi+uQO5gTJONaYJ9OZvJaDCu9UvVCZx1z0yT0D7/K+V/LCQm8dLenscr6jR802y7
/7TuAOEr0fO8bh5Oy8zMc/wXuVY5xwz9EfJH9lA47e23JdESxIDTwuziIAECgYEA
qKQdPtqpxbUTKDTH3bomN6CcFwcL56XQ+wrdROidb+eyoZsUA5YtkSWwh+TG9Osz
XAvqKZ2OBx0YSwWD05CNEq3mjqA2yOtXvpkV/wuInGjoVi0+5BMzDu/2zkecC7WJ
QXP7MVWKqhJfmJQdxrIU4S49OvDfMl15zwDrEI5AugkCgYBn5+/KvrA8GGWD9p1r
qwjoojGBvCJn1Kj/s+IQYePYeiRe6/eSPGFHRyON9aMGjZmeiqyBA4bW71Wf8Rs1
X5LSwZhJpCTjO4B92w40u0r86Jxmp5Wz+zHUeM3mO2E6lAF+15YjhxpMT0YOmHFE
+oKD8U6dMjkTqntavBauz8M8fQ==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmjCCAYICCQCOEQkjYe2QMTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARy
b290MB4XDTIwMTExMDExMjgyOVoXDTMwMTExMDExMjgyOVowDzENMAsGA1UEAwwE
cm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOqS7H7+XeFNcf5m
qlH04t0ru56MCDYv9JV3byILgUnk1j+ld74m2q4T+Xxiw5ruMXh41W2xryMLF3+3
jql8b7isJFwCXud4/WLr4KzCEKgqvr6Nez9Hb9rIBbQsGWtDTjfe06F/D9Zioyt3
RnoT+5ItpX0+9IJn3TmAx7g1wU2dlXeaTp48RWPtJBqxp80Lq4SR3CdxI9+eVHv9
sRA3sI9ggqFWzDNJDiTLZoJU1Z+n/MnHTUBt7WRZcMToMsHbj2Gtd4LruB3J46qO
bjoL4im9oUrfXJZh87nW9KQ/+gOVv8t0zU70A/JMrazb/YnE6xO7+40JfrGNuFMm
ZyylUyECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAvCJMjXDNO/zUv7SBlr8hlHse
KprCDEp91DlXsewpTB3h6s1gyZzDCygPtz80qRD6zy+T4r1veaYQeLecsIyfYNV1
qnhNPpHnxjuXrrVwpEYOk/aP0yVlv0PiHsjyxzblLQPomX4m43Ec8/wW0Nlw0Aau
K0sD5+Mv/3NNQIneGFsLF4JPRkJwLjSbjPdKLpjWdLsTKQwVg0FIslzI9RmBIQIq
Nz2RWNHSqfGzsRpne9deqx9/9M4N8URUcmo0j7Ly7mYuxTkF7sft6sxbWDYQx1S1
4GjAEFWe4352O0sFl0PWr+o8rd245yAu5SEahRFvjvnSNg8VlYcnezBmsp2rbQ==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,7 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
COMPONENT_EMBED_TXTFILES := certs/cacert.pem
COMPONENT_EMBED_TXTFILES += certs/prvtkey.pem

View File

@@ -0,0 +1,274 @@
/* Local Ctrl 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 <stdlib.h>
#include <stdint.h>
#include <sys/param.h>
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <mdns.h>
#include <esp_log.h>
#include <esp_timer.h>
#include <esp_local_ctrl.h>
#include <esp_https_server.h>
static const char *TAG = "control";
#define SERVICE_NAME "my_esp_ctrl_device"
/* Custom allowed property types */
enum property_types {
PROP_TYPE_TIMESTAMP = 0,
PROP_TYPE_INT32,
PROP_TYPE_BOOLEAN,
PROP_TYPE_STRING,
};
/* Custom flags that can be set for a property */
enum property_flags {
PROP_FLAG_READONLY = (1 << 0)
};
/********* Handler functions for responding to control requests / commands *********/
static esp_err_t get_property_values(size_t props_count,
const esp_local_ctrl_prop_t props[],
esp_local_ctrl_prop_val_t prop_values[],
void *usr_ctx)
{
for (uint32_t i = 0; i < props_count; i++) {
ESP_LOGI(TAG, "Reading property : %s", props[i].name);
/* For the purpose of this example, to keep things simple
* we have set the context pointer of each property to
* point to its value (except for timestamp) */
switch (props[i].type) {
case PROP_TYPE_INT32:
case PROP_TYPE_BOOLEAN:
/* No need to set size for these types as sizes where
* specified when declaring the properties, unlike for
* string type. */
prop_values[i].data = props[i].ctx;
break;
case PROP_TYPE_TIMESTAMP: {
/* Get the time stamp */
static int64_t ts = 0;
ts = esp_timer_get_time();
/* Set the current time. Since this is statically
* allocated, we don't need to provide a free_fn */
prop_values[i].data = &ts;
break;
}
case PROP_TYPE_STRING: {
char **prop3_value = (char **) props[i].ctx;
if (*prop3_value == NULL) {
prop_values[i].size = 0;
prop_values[i].data = NULL;
} else {
/* We could try dynamically allocating the output value,
* and it should get freed automatically after use, as
* `esp_local_ctrl` internally calls the provided `free_fn` */
prop_values[i].size = strlen(*prop3_value);
prop_values[i].data = strdup(*prop3_value);
if (!prop_values[i].data) {
return ESP_ERR_NO_MEM;
}
prop_values[i].free_fn = free;
}
}
default:
break;
}
}
return ESP_OK;
}
static esp_err_t set_property_values(size_t props_count,
const esp_local_ctrl_prop_t props[],
const esp_local_ctrl_prop_val_t prop_values[],
void *usr_ctx)
{
for (uint32_t i = 0; i < props_count; i++) {
/* Cannot set the value of a read-only property */
if (props[i].flags & PROP_FLAG_READONLY) {
ESP_LOGE(TAG, "%s is read-only", props[i].name);
return ESP_ERR_INVALID_ARG;
}
/* For the purpose of this example, to keep things simple
* we have set the context pointer of each property to
* point to its value (except for timestamp) */
switch (props[i].type) {
case PROP_TYPE_STRING: {
/* Free the previously set string */
char **prop3_value = (char **) props[i].ctx;
free(*prop3_value);
*prop3_value = NULL;
/* Copy the input string */
if (prop_values[i].size) {
*prop3_value = strndup((const char *)prop_values[i].data, prop_values[i].size);
if (*prop3_value == NULL) {
return ESP_ERR_NO_MEM;
}
ESP_LOGI(TAG, "Setting %s value to %s", props[i].name, (const char*)*prop3_value);
}
}
break;
case PROP_TYPE_INT32: {
const int32_t *new_value = (const int32_t *) prop_values[i].data;
ESP_LOGI(TAG, "Setting %s value to %d", props[i].name, *new_value);
memcpy(props[i].ctx, new_value, sizeof(int32_t));
}
break;
case PROP_TYPE_BOOLEAN: {
const bool *value = (const bool *) prop_values[i].data;
ESP_LOGI(TAG, "Setting %s value to %d", props[i].name, *value);
memcpy(props[i].ctx, value, sizeof(bool));
}
break;
default:
break;
}
}
return ESP_OK;
}
/******************************************************************************/
/* A custom free_fn to free a pointer to a string as
* well as the string being pointed to */
static void free_str(void *arg)
{
char **ptr_to_strptr = (char **)arg;
if (ptr_to_strptr) {
free(*ptr_to_strptr);
free(ptr_to_strptr);
}
}
/* Function used by app_main to start the esp_local_ctrl service */
void start_esp_local_ctrl_service(void)
{
/* Set the configuration */
httpd_ssl_config_t https_conf = HTTPD_SSL_CONFIG_DEFAULT();
/* Load server certificate */
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
https_conf.cacert_pem = cacert_pem_start;
https_conf.cacert_len = cacert_pem_end - cacert_pem_start;
/* Load server private key */
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
https_conf.prvtkey_pem = prvtkey_pem_start;
https_conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
esp_local_ctrl_config_t config = {
.transport = ESP_LOCAL_CTRL_TRANSPORT_HTTPD,
.transport_config = {
.httpd = &https_conf
},
.handlers = {
/* User defined handler functions */
.get_prop_values = get_property_values,
.set_prop_values = set_property_values,
.usr_ctx = NULL,
.usr_ctx_free_fn = NULL
},
/* Maximum number of properties that may be set */
.max_properties = 10
};
mdns_init();
mdns_hostname_set(SERVICE_NAME);
/* Start esp_local_ctrl service */
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
ESP_LOGI(TAG, "esp_local_ctrl service started with name : %s", SERVICE_NAME);
/* Create a timestamp property. The client should see this as a read-only property.
* Property value is fetched using `esp_timer_get_time()` in the `get_prop_values`
* handler */
esp_local_ctrl_prop_t timestamp = {
.name = "timestamp (us)",
.type = PROP_TYPE_TIMESTAMP,
.size = sizeof(int64_t),
.flags = PROP_FLAG_READONLY,
.ctx = NULL,
.ctx_free_fn = NULL
};
/* Create a writable integer property. Use dynamically allocated memory
* for storing its value and pass it as context, so that it can be accessed
* inside the set / get handlers. */
int32_t *prop1_value = malloc(sizeof(int32_t));
assert(prop1_value != NULL);
/* Initialize the property value */
*prop1_value = 123456789;
/* Populate the property structure accordingly. Since, we would want the memory
* occupied by the property value to be freed automatically upon call to
* `esp_local_ctrl_stop()` or `esp_local_ctrl_remove_property()`, the `ctx_free_fn`
* field will need to be set with the appropriate de-allocation function,
* which in this case is simply `free()` */
esp_local_ctrl_prop_t property1 = {
.name = "property1",
.type = PROP_TYPE_INT32,
.size = sizeof(int32_t),
.flags = 0,
.ctx = prop1_value,
.ctx_free_fn = free
};
/* Create another read-only property. Just for demonstration, we use statically
* allocated value. No `ctx_free_fn` needs to be set for this */
static bool prop2_value = false;
esp_local_ctrl_prop_t property2 = {
.name = "property2",
.type = PROP_TYPE_BOOLEAN,
.size = sizeof(bool),
.flags = PROP_FLAG_READONLY,
.ctx = &prop2_value,
.ctx_free_fn = NULL
};
/* Create a variable sized property. Its context is a pointer for storing the
* pointer to a dynamically allocate string, therefore it will require a
* customized free function `free_str()` */
char **prop3_value = calloc(1, sizeof(char *));
assert(prop3_value != NULL);
esp_local_ctrl_prop_t property3 = {
.name = "property3",
.type = PROP_TYPE_STRING,
.size = 0, // When zero, this is assumed to be of variable size
.flags = 0,
.ctx = prop3_value,
.ctx_free_fn = free_str
};
/* Now register the properties */
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&timestamp));
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&property1));
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&property2));
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&property3));
/* Just for fun, let us keep toggling the value
* of the boolean property2, every 1 second */
while (1) {
vTaskDelay(1000 / portTICK_RATE_MS);
prop2_value = !prop2_value;
}
}