mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-19 17:35:54 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -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")
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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-----
|
||||
@@ -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-----
|
||||
@@ -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-----
|
||||
@@ -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
|
||||
@@ -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(×tamp));
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user