├── .gitignore ├── ESP32RevK.pages ├── component.mk ├── include ├── esp8266_flash_compat.h ├── esp8266_ota_compat.h ├── esp8266_tls_compat.h ├── esp8266_gpio_compat.h ├── esp8266_httpd_compat.h ├── esp8266_wdt_compat.h ├── esp8266_netif_compat.h ├── lwmqtt.h ├── lecert.h ├── jo.h └── revk.h ├── partitions_4m.csv ├── partitions_8m.csv ├── README.md ├── CMakeLists.txt ├── esp8266_compat.c ├── setbuildsuffix ├── Kconfig ├── revk-user.md ├── revk-dev.md ├── lwmqtt.c ├── LICENSE ├── jo.c └── sdkconfig.defaults /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *~ 3 | *.swp 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /ESP32RevK.pages: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/njh/ESP32-RevK/master/ESP32RevK.pages -------------------------------------------------------------------------------- /component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | COMPONENT_EMBED_FILES := ../../build/partitions_4m.bin 7 | 8 | -------------------------------------------------------------------------------- /include/esp8266_flash_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_FLASH_COMPAT_H 2 | #define REVK_ESP8266_FLASH_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | esp_err_t esp_flash_get_size(void *chip, uint32_t *out_size); 7 | 8 | #else 9 | #include "esp_flash_spi_init.h" 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/esp8266_ota_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_OTA_COMPAT_H 2 | #define REVK_ESP8266_OTA_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | static const esp_app_desc_t *esp_app_get_description(void) 7 | { 8 | return esp_ota_get_app_description(); 9 | } 10 | 11 | #endif 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /include/esp8266_tls_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_TLS_COMPAT_H 2 | #define REVK_ESP8266_TLS_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | static inline int esp_tls_conn_destroy(esp_tls_t *tls) 7 | { 8 | esp_tls_conn_delete(tls); 9 | return 0; 10 | } 11 | 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/esp8266_gpio_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_GPIO_COMPAT_H 2 | #define REVK_ESP8266_GPIO_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | static inline esp_err_t gpio_reset_pin(gpio_num_t gpio_num) 7 | { 8 | // According to the documentation. We don't have alternate functions. 9 | return gpio_pullup_en(gpio_num); 10 | } 11 | 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /partitions_4m.csv: -------------------------------------------------------------------------------- 1 | # Espressif ESP32 Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | RevK, data, nvs, 0x9000, 0x4000, 4 | otadata, data, ota, 0xd000, 0x2000, 5 | phy_init, data, phy, 0xf000, 0x1000, 6 | ota_0, 0, ota_0, 0x10000, 0x1f0000, 7 | ota_1, 0, ota_1, , 0x1f0000, 8 | nvs, data, nvs, 0x3F0000,0xF000, 9 | nvs_key, data, nvs_keys,0x3FF000,0x1000, 10 | -------------------------------------------------------------------------------- /partitions_8m.csv: -------------------------------------------------------------------------------- 1 | # Espressif ESP32 Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | RevK, data, nvs, 0x9000, 0x4000, 4 | otadata, data, ota, 0xd000, 0x2000, 5 | phy_init, data, phy, 0xf000, 0x1000, 6 | ota_0, 0, ota_0, 0x10000, 0x3e0000, 7 | nvs, data, nvs, 0x3F0000,0xF000, 8 | nvs_key, data, nvs_keys,0x3FF000,0x1000, 9 | ota_1, 0, ota_1, , 0x3e0000, 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32RevK 2 | 3 | Library of tools used for ESP32 development. 4 | 5 | This includes functions for management of settins in NVS using MQTT controls. 6 | 7 | This includes Kconfig settings to enable/disable key functions, such as AP mode config, Multiple WiFi handling, MQTT handling, etc. 8 | 9 | User guide: [Details of using devices that use this library](revk-user.md) 10 | 11 | Dev guide: [Details for apps using this library](revk-dev.md) 12 | -------------------------------------------------------------------------------- /include/esp8266_httpd_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_HTTPD_COMPAT_H 2 | #define REVK_ESP8266_HTTPD_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | static inline esp_err_t httpd_resp_sendstr_chunk(httpd_req_t *r, const char *buf) 7 | { 8 | return httpd_resp_send_chunk(r, buf, buf ? strlen(buf) : 0); 9 | } 10 | 11 | static inline esp_err_t httpd_resp_sendstr(httpd_req_t *r, const char *buf) 12 | { 13 | return httpd_resp_send(r, buf, strlen(buf)); 14 | } 15 | 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/esp8266_wdt_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_WDT_COMPAT_H 2 | #define REVK_ESP8266_WDT_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | static inline esp_err_t compat_task_wdt_add(void) 7 | { 8 | return esp_task_wdt_init(); 9 | } 10 | 11 | static inline esp_err_t compat_task_wdt_reconfigure(bool init, uint32_t timeout, bool panic) 12 | { 13 | return ESP_OK; 14 | } 15 | 16 | #else // ESP32 17 | 18 | static inline esp_err_t compat_task_wdt_add(void) 19 | { 20 | return esp_task_wdt_add(NULL); 21 | } 22 | 23 | static inline esp_err_t compat_task_wdt_reconfigure(bool init, uint32_t timeout, bool panic) 24 | { 25 | esp_task_wdt_config_t config = { 26 | .timeout_ms = timeout, 27 | .trigger_panic = panic, 28 | }; 29 | #ifndef CONFIG_ESP_TASK_WDT_INIT 30 | if (init && esp_task_wdt_init(&config) == ESP_OK) 31 | return ESP_OK; 32 | #endif 33 | return esp_task_wdt_reconfigure(&config); 34 | } 35 | 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES "revk.c" "jo.c" "lwmqtt.c") 2 | set(RECS nvs_flash app_update esp_http_client esp-tls esp_http_server spi_flash esp_wifi esp_timer esp_system driver bt) 3 | 4 | # Add extra dependancies 5 | 6 | # Unfortunately we can't simply test for ${CONFIG_IDF_TARGET_ESP8266} here 7 | # because requirements are evaluated in a separate pass, where any CONFIG_ 8 | # settings haven't been evaluated yet. 9 | # The same applied to mdns check below 10 | if(EXISTS $ENV{IDF_PATH}/components/esp8266) 11 | set(SOURCES ${SOURCES} "esp8266_compat.c") 12 | set(RECS nvs_flash app_update esp_http_client esp-tls esp_http_server esp8266 spi_flash) 13 | endif() 14 | 15 | if(EXISTS "../managed_components/espressif__mdns") 16 | set(RECS ${RECS} mdns) 17 | endif() 18 | 19 | idf_component_register( 20 | SRCS ${SOURCES} 21 | INCLUDE_DIRS "include" 22 | REQUIRES ${RECS} 23 | EMBED_FILES "../../build/partition_table/partition-table.bin" 24 | ) 25 | 26 | add_definitions(-DBUILD_ESP32_USING_CMAKE) 27 | set_property(SOURCE "../../build/partition_table/partition-table.bin" PROPERTY GENERATED 1) 28 | -------------------------------------------------------------------------------- /esp8266_compat.c: -------------------------------------------------------------------------------- 1 | #include "sdkconfig.h" 2 | 3 | #include "esp8266_netif_compat.h" 4 | #include "esp8266_flash_compat.h" 5 | 6 | esp_netif_t* esp_netif_create_default_wifi_sta(void) 7 | { 8 | static esp_netif_t netif = {TCPIP_ADAPTER_IF_STA}; 9 | return &netif; 10 | } 11 | 12 | esp_netif_t* esp_netif_create_default_wifi_ap(void) 13 | { 14 | static esp_netif_t netif = {TCPIP_ADAPTER_IF_AP}; 15 | return &netif; 16 | } 17 | 18 | esp_err_t esp_flash_get_size(void *chip, uint32_t *out_size) 19 | { 20 | switch (system_get_flash_size_map()) 21 | { 22 | case FLASH_SIZE_4M_MAP_256_256: 23 | *out_size = 4; 24 | break; 25 | case FLASH_SIZE_2M: 26 | *out_size = 2; 27 | break; 28 | case FLASH_SIZE_8M_MAP_512_512: 29 | *out_size = 8; 30 | break; 31 | case FLASH_SIZE_16M_MAP_512_512: 32 | case FLASH_SIZE_16M_MAP_1024_1024: 33 | *out_size = 16; 34 | break; 35 | case FLASH_SIZE_32M_MAP_512_512: 36 | case FLASH_SIZE_32M_MAP_1024_1024: 37 | case FLASH_SIZE_32M_MAP_2048_2048: 38 | *out_size = 32; 39 | break; 40 | case FLASH_SIZE_64M_MAP_1024_1024: 41 | *out_size = 64; 42 | break; 43 | case FLASH_SIZE_128M_MAP_1024_1024: 44 | *out_size = 128; 45 | break; 46 | default: 47 | return ESP_FAIL; 48 | } 49 | 50 | return ESP_OK; 51 | } 52 | -------------------------------------------------------------------------------- /include/esp8266_netif_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef REVK_ESP8266_COMPAT_H 2 | #define REVK_ESP8266_COMPAT_H 3 | 4 | #ifdef CONFIG_IDF_TARGET_ESP8266 5 | 6 | #include "tcpip_adapter.h" 7 | 8 | typedef struct 9 | { 10 | tcpip_adapter_if_t adapter; 11 | } esp_netif_t; 12 | 13 | typedef enum 14 | { 15 | ESP_NETIF_DNS_MAIN = TCPIP_ADAPTER_DNS_MAIN, 16 | ESP_NETIF_DNS_BACKUP = TCPIP_ADAPTER_DNS_BACKUP, 17 | ESP_NETIF_DNS_FALLBACK = TCPIP_ADAPTER_DNS_FALLBACK 18 | } esp_netif_dns_type_t; 19 | 20 | typedef tcpip_adapter_ip_info_t esp_netif_ip_info_t; 21 | typedef tcpip_adapter_dns_info_t esp_netif_dns_info_t; 22 | typedef ip6_addr_t esp_ip6_addr_t; 23 | 24 | static inline void esp_netif_set_ip4_addr(ip4_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d) 25 | { 26 | IP4_ADDR(addr, a, b, c, d); 27 | } 28 | 29 | static inline esp_err_t esp_netif_str_to_ip4(const char *src, ip4_addr_t *dst) 30 | { 31 | return ip4addr_aton(src, dst) ? ESP_OK : ESP_FAIL; 32 | } 33 | 34 | static inline esp_err_t esp_netif_str_to_ip6(const char *src, ip6_addr_t *dst) 35 | { 36 | return ip6addr_aton(src, dst) ? ESP_OK : ESP_FAIL; 37 | } 38 | 39 | static inline esp_err_t esp_netif_get_old_ip_info(esp_netif_t *tcpip_if, tcpip_adapter_ip_info_t *ip_info) 40 | { 41 | return tcpip_adapter_get_old_ip_info(tcpip_if->adapter, ip_info); 42 | } 43 | 44 | static inline esp_err_t esp_netif_get_ip_info(esp_netif_t *tcpip_if, tcpip_adapter_ip_info_t *ip_info) 45 | { 46 | return tcpip_adapter_get_ip_info(tcpip_if->adapter, ip_info); 47 | } 48 | 49 | static inline esp_err_t esp_netif_set_ip_info(esp_netif_t *tcpip_if, tcpip_adapter_ip_info_t *ip_info) 50 | { 51 | return tcpip_adapter_set_ip_info(tcpip_if->adapter, ip_info); 52 | } 53 | 54 | static inline esp_err_t esp_netif_dhcpc_stop(esp_netif_t *tcpip_if) 55 | { 56 | return tcpip_adapter_dhcpc_stop(tcpip_if->adapter); 57 | } 58 | 59 | static inline esp_err_t esp_netif_dhcpc_start(esp_netif_t *tcpip_if) 60 | { 61 | return tcpip_adapter_dhcpc_start(tcpip_if->adapter); 62 | } 63 | 64 | static inline esp_err_t esp_netif_dhcps_stop(esp_netif_t *tcpip_if) 65 | { 66 | return tcpip_adapter_dhcps_stop(tcpip_if->adapter); 67 | } 68 | 69 | static inline esp_err_t esp_netif_dhcps_start(esp_netif_t *tcpip_if) 70 | { 71 | return tcpip_adapter_dhcps_start(tcpip_if->adapter); 72 | } 73 | 74 | static inline esp_err_t esp_netif_set_dns_info(esp_netif_t *tcpip_if, esp_netif_dns_type_t type, tcpip_adapter_dns_info_t *dns) 75 | { 76 | return tcpip_adapter_set_dns_info(tcpip_if->adapter, type, dns); 77 | } 78 | 79 | static inline esp_err_t esp_netif_create_ip6_linklocal(esp_netif_t *tcpip_if) 80 | { 81 | return tcpip_adapter_create_ip6_linklocal(tcpip_if->adapter); 82 | } 83 | 84 | static inline esp_err_t esp_netif_get_ip6_global(esp_netif_t *tcpip_if, ip6_addr_t *if_ip6) 85 | { 86 | return tcpip_adapter_get_ip6_global(tcpip_if->adapter, if_ip6); 87 | } 88 | 89 | static inline void esp_netif_init(void) 90 | { 91 | tcpip_adapter_init(); 92 | } 93 | 94 | static inline esp_err_t esp_netif_set_hostname(esp_netif_t *tcpip_if, const char *hostname) 95 | { 96 | return tcpip_adapter_set_hostname(tcpip_if->adapter, hostname); 97 | } 98 | 99 | esp_netif_t *esp_netif_create_default_wifi_sta(void); 100 | esp_netif_t *esp_netif_create_default_wifi_ap(void); 101 | 102 | #endif 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /setbuildsuffix: -------------------------------------------------------------------------------- 1 | #!/bin/csh -f 2 | if("$1" == "") then 3 | echo "Specify suffix" 4 | exit 1 5 | endif 6 | setenv BUILDSUFFIX "$1" 7 | shift 8 | setenv SDKCONFIG "sdkconfig" 9 | if("$1" != "") setenv SDKCONFIG "$1" 10 | 11 | if(! -e "$SDKCONFIG") then 12 | echo "Missing $SDKCONFIG" 13 | exit 0 14 | endif 15 | 16 | # We don't seem to have any SoC variations with 8266 17 | grep -q CONFIG_IDF_TARGET_ESP8266=y "$SDKCONFIG" 18 | if(! $status) then 19 | echo setbuildsuffix is not supported on ESP8266 20 | exit 255 21 | endif 22 | 23 | set add=() 24 | set rem=() 25 | set part="" 26 | 27 | if("$BUILDSUFFIX" =~ *-PICO*) then 28 | set add=($add CONFIG_ESP32_SPIRAM_SUPPORT CONFIG_ESPTOOLPY_FLASHSIZE_8MB CONFIG_SPIRAM CONFIG_REVK_PICO) 29 | set rem=($rem CONFIG_ESPTOOLPY_FLASHSIZE_4MB CONFIG_FREERTOS_UNICORE CONFIG_REVK_D4) 30 | set part="components/ESP32-RevK/partitions_8m.csv" 31 | else if("$BUILDSUFFIX" =~ *-D4*) then 32 | set add=($add CONFIG_ESPTOOLPY_FLASHSIZE_4MB CONFIG_FREERTOS_UNICORE CONFIG_REVK_D4) 33 | set rem=($rem CONFIG_ESP32_SPIRAM_SUPPORT CONFIG_ESPTOOLPY_FLASHSIZE_8MB CONFIG_SPIRAM CONFIG_REVK_PICO) 34 | set part="components/ESP32-RevK/partitions_4m.csv" 35 | else if("$BUILDSUFFIX" =~ *-SOLO*) then 36 | set add=($add CONFIG_ESPTOOLPY_FLASHSIZE_4MB CONFIG_FREERTOS_UNICORE) 37 | set rem=($rem CONFIG_ESP32_SPIRAM_SUPPORT CONFIG_ESPTOOLPY_FLASHSIZE_8MB CONFIG_SPIRAM CONFIG_REVK_PICO CONFIG_REVK_D4) 38 | set part="components/ESP32-RevK/partitions_4m.csv" 39 | else 40 | set add=($add CONFIG_ESPTOOLPY_FLASHSIZE_4MB) 41 | set rem=($rem CONFIG_ESP32_SPIRAM_SUPPORT CONFIG_ESPTOOLPY_FLASHSIZE_8MB CONFIG_FREERTOS_UNICORE CONFIG_SPIRAM CONFIG_REVK_PICO CONFIG_REVK_D4) 42 | set part="components/ESP32-RevK/partitions_4m.csv" 43 | endif 44 | 45 | if("$BUILDSUFFIX" =~ *-V3*) then 46 | set add=($add CONFIG_ESP32_REV_MIN_3) 47 | set rem=($rem CONFIG_ESP32_REV_MIN_2 CONFIG_ESP32_REV_MIN_1 CONFIG_ESP32_REV_MIN_0 CONFIG_ESP32_REV_MIN_1_1 CONFIG_ESP32_REV_MIN_3_1) 48 | else if("$BUILDSUFFIX" =~ *-V2*) then 49 | set add=($add CONFIG_ESP32_REV_MIN_2) 50 | set rem=($rem CONFIG_ESP32_REV_MIN_3 CONFIG_ESP32_REV_MIN_1 CONFIG_ESP32_REV_MIN_0 CONFIG_ESP32_REV_MIN_1_1 CONFIG_ESP32_REV_MIN_3_1) 51 | else if("$BUILDSUFFIX" =~ *-V1*) then 52 | set add=($add CONFIG_ESP32_REV_MIN_1) 53 | set rem=($rem CONFIG_ESP32_REV_MIN_3 CONFIG_ESP32_REV_MIN_2 CONFIG_ESP32_REV_MIN_0 CONFIG_ESP32_REV_MIN_1_1 CONFIG_ESP32_REV_MIN_3_1) 54 | else if("$BUILDSUFFIX" =~ *-V0*) then 55 | set add=($add CONFIG_ESP32_REV_MIN_0) 56 | set rem=($rem CONFIG_ESP32_REV_MIN_3 CONFIG_ESP32_REV_MIN_2 CONFIG_ESP32_REV_MIN_1 CONFIG_ESP32_REV_MIN_1_1 CONFIG_ESP32_REV_MIN_3_1) 57 | else # Default is V3 58 | set add=($add CONFIG_ESP32_REV_MIN_3) 59 | set rem=($rem CONFIG_ESP32_REV_MIN_2 CONFIG_ESP32_REV_MIN_1 CONFIG_ESP32_REV_MIN_0 CONFIG_ESP32_REV_MIN_1_1 CONFIG_ESP32_REV_MIN_3_1) 60 | endif 61 | 62 | set bs=(`grep _BUILD_SUFFIX_ sdkconfig | sed 's/.*\(CONFIG_[A-Z0-9_]*_BUILD_SUFFIX_[A-Z0-9]*\).*/\1/'`) 63 | foreach c ($bs) 64 | echo -n "$BUILDSUFFIX" | grep -q -- "-"`echo -n "$c" | sed 's/CONFIG_.*_BUILD_SUFFIX_\(.*\)/\1/'` 65 | if(! $status) then 66 | set add=($add $c) 67 | else 68 | set rem=($rem $c) 69 | endif 70 | end 71 | 72 | rm -f "$SDKCONFIG".new 73 | foreach c ($add) 74 | grep -q "^# $c is not set" "$SDKCONFIG" 75 | if(! $status) then 76 | sed "s/^# $c is not set/$c=y/" "$SDKCONFIG" > "$SDKCONFIG.new" 77 | mv -f "$SDKCONFIG".new "$SDKCONFIG" 78 | endif 79 | end 80 | foreach c ($rem) 81 | grep -q "^$c=y" "$SDKCONFIG" 82 | if(! $status) then 83 | sed "s/^$c=y/# $c is not set/" "$SDKCONFIG" > "$SDKCONFIG.new" 84 | mv -f "$SDKCONFIG".new "$SDKCONFIG" 85 | endif 86 | end 87 | if($part != "") then 88 | foreach t (CONFIG_PARTITION_TABLE_CUSTOM_FILENAME CONFIG_PARTITION_TABLE_FILENAME) 89 | grep -q "^$t="'"'"$part"'"' "$SDKCONFIG" 90 | if($status) then 91 | sed "s:^$t.*:$t="'"'"$part"'"'":" "$SDKCONFIG" > "$SDKCONFIG.new" 92 | mv -f "$SDKCONFIG".new "$SDKCONFIG" 93 | endif 94 | end 95 | endif 96 | 97 | -------------------------------------------------------------------------------- /include/lwmqtt.h: -------------------------------------------------------------------------------- 1 | #ifndef LWMQTT_H 2 | #define LWMQTT_H 3 | // Light weight MQTT client 4 | // QoS 0 only, no queuing or resending (using TCP to do that for us) 5 | // Live sending to TCP for outgoing messages 6 | // Simple callback for incoming messages 7 | // Automatic reconnect 8 | 9 | // Callback function for a connection (client or server) 10 | // For client, the arg passed is as specified in the client config 11 | // For server, the arg passed is the lwmqtt_t for the new connection 12 | // Called for incoming message 13 | // - Topic is NULL terminated string, even if zero length topic has been used, and can be overwritten in situ 14 | // - Payload is also NULL terminated at len, for convenience, and can be overwritten in situ 15 | // Called for connect 16 | // - Topic is NULL 17 | // - Payload is server/client name 18 | // Called for disconnect 19 | // - Topic is NULL 20 | // - Payload is NULL 21 | // Called as server for subscribe 22 | // - Topic is subscribe pattern 23 | // - Payload is NULL 24 | typedef void lwmqtt_callback_t (void *arg, char *topic, unsigned short len, unsigned char *payload); 25 | 26 | typedef struct lwmqtt_client_config_s lwmqtt_client_config_t; 27 | 28 | // Config for connection 29 | struct lwmqtt_client_config_s 30 | { 31 | lwmqtt_callback_t *callback; 32 | void *arg; 33 | const char *client; 34 | const char *hostname; // Name or IP 35 | const char *username; 36 | const char *password; 37 | const char *tlsname; // Name of cert if not host name 38 | unsigned short port; // Port 0=auto 39 | unsigned short keepalive; // 0=default 40 | // Will 41 | const char *topic; // Will topic 42 | int plen; // Will payload len (-1 does strlen) 43 | const unsigned char *payload; // Will payload 44 | uint8_t retain:1; // Will retain 45 | // TLS 46 | void *ca_cert_buf; // For checking server - assumed we need to make a copy 47 | int ca_cert_bytes; 48 | void *client_cert_buf; // For client auth 49 | int client_cert_bytes; 50 | void *client_key_buf; // For client auth 51 | int client_key_bytes; 52 | esp_err_t (*crt_bundle_attach) (void *conf); 53 | uint8_t hostname_ref:1; // The _buf above is fixed and so we do not need to make a copy 54 | uint8_t tlsname_ref:1; // The _buf above is fixed and so we do not need to make a copy 55 | uint8_t ca_cert_ref:1; // The _buf above is fixed and so we do not need to make a copy 56 | uint8_t client_cert_ref:1; // The _buf above is fixed and so we do not need to make a copy 57 | uint8_t client_key_ref:1; // The _buf above is fixed and so we do not need to make a copy 58 | }; 59 | 60 | #ifdef CONFIG_REVK_MQTT_SERVER 61 | typedef struct lwmqtt_server_config_s lwmqtt_server_config_t; 62 | 63 | // Config for connection 64 | struct lwmqtt_server_config_s 65 | { 66 | lwmqtt_callback_t *callback; 67 | unsigned short port; // Port 0=auto 68 | // TLS 69 | void *ca_cert_buf; // For checking server 70 | int ca_cert_bytes; 71 | void *server_cert_buf; // For server auth 72 | int server_cert_bytes; 73 | void *server_key_buf; // For server auth 74 | int server_key_bytes; 75 | uint8_t ca_cert_ref:1; // The _buf above is fixed and so we do not need to make a copy 76 | uint8_t server_cert_ref:1; // The _buf above is fixed and so we do not need to make a copy 77 | uint8_t server_key_ref:1; // The _buf above is fixed and so we do not need to make a copy 78 | }; 79 | #endif 80 | 81 | // Handle for connection 82 | typedef struct lwmqtt_s *lwmqtt_t; 83 | 84 | uint32_t uptime (void); // Seconds uptime 85 | 86 | int lwmqtt_connected (lwmqtt_t); // If connected 87 | int lwmqtt_failed (lwmqtt_t); // If failed connect 88 | 89 | // Create a client connection (NULL if failed) 90 | lwmqtt_t lwmqtt_client (lwmqtt_client_config_t *); 91 | 92 | #ifdef CONFIG_REVK_MQTT_SERVER 93 | // Start a server (the return value is only usable in lwmqtt_end) 94 | lwmqtt_t lwmqtt_server (lwmqtt_server_config_t *); 95 | #endif 96 | 97 | // End connection - actually freed later as part of task. Will do a callback when closed if was connected 98 | // NULLs the passed handle - do not use handle after this call 99 | void lwmqtt_end (lwmqtt_t *); 100 | 101 | // Subscribe (return is non null error message if failed) 102 | const char *lwmqtt_subscribeub (lwmqtt_t, const char *topic, char unsubscribe); 103 | #define lwmqtt_subscribe(h,t) lwmqtt_subscribeub(h,t,0); 104 | #define lwmqtt_unsubscribe(h,t) lwmqtt_subscribeub(h,t,1); 105 | 106 | // Send (return is non null error message if failed) (-1 tlen or plen do strlen) 107 | const char *lwmqtt_send_full (lwmqtt_t, int tlen, const char *topic, int plen, const unsigned char *payload, char retain); 108 | // Simpler 109 | #define lwmqtt_send(h,t,l,p) lwmqtt_send_full(h,-1,t,l,p,0,0); 110 | 111 | // Simple send - non retained no wait topic ends on space then payload 112 | const char *lwmqtt_send_str (lwmqtt_t, const char *msg); 113 | #endif 114 | -------------------------------------------------------------------------------- /include/lecert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #warning LECert expiry 2021-09 - use CA bundle instead maybe (CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) 3 | const unsigned char LECert[] = { 4 | 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, 5 | 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, 6 | 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 7 | 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, 8 | 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, 9 | 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 10 | 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 11 | 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 12 | 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 13 | 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, 14 | 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, 15 | 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, 16 | 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 17 | 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 18 | 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 19 | 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 20 | 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 21 | 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 22 | 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 23 | 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 24 | 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, 25 | 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, 26 | 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, 27 | 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, 28 | 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, 29 | 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, 30 | 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, 31 | 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, 32 | 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, 33 | 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, 34 | 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, 35 | 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, 36 | 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, 37 | 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, 38 | 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, 39 | 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, 40 | 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, 41 | 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, 42 | 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, 43 | 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, 44 | 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, 45 | 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 46 | 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 47 | 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 48 | 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 49 | 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, 50 | 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, 51 | 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 52 | 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 53 | 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, 54 | 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, 55 | 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, 56 | 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, 57 | 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, 58 | 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, 59 | 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, 60 | 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, 61 | 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, 62 | 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, 63 | 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, 64 | 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, 65 | 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, 66 | 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, 67 | 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, 68 | 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, 69 | 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, 70 | 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, 71 | 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, 72 | 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, 73 | 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, 74 | 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 75 | }; 76 | -------------------------------------------------------------------------------- /include/jo.h: -------------------------------------------------------------------------------- 1 | // Lightweight JSON syntax management tool kit 2 | // This toolkit works solely at a syntax level, and does not all management of whole JSON object hierarchy 3 | 4 | #include 5 | #include 6 | 7 | // Types 8 | 9 | typedef struct jo_s *jo_t; // The JSON cursor used by all calls 10 | typedef enum { // The parse data value type we are at 11 | JO_END, // Not a value, we are at the end, or in an error state 12 | // JO_END always at start 13 | JO_CLOSE, // at close of object or array 14 | // After JO_END 15 | JO_TAG, // at a tag 16 | JO_OBJECT, // value is the '{' of an object, jo_next() goes in to object if it has things in it 17 | JO_ARRAY, // value is the '[' of an array, jo_next() goes in to array if it has things in it 18 | JO_STRING, // value is the '"' of a string 19 | JO_NUMBER, // value is start of an number 20 | // Can test >= JO_NULL as test for literal 21 | JO_NULL, // value is the 'n' in a null 22 | // Can test >= JO_TRUE as test for bool 23 | JO_TRUE, // value is the 't' in true, can compare >= JO_TRUE for boolean 24 | JO_FALSE, // value if the 'f' in false 25 | } jo_type_t; 26 | 27 | const char *jo_debug(jo_t j); // Debug string 28 | 29 | // Setting up 30 | 31 | jo_t jo_parse_str(const char *buf); 32 | // Start parsing a null terminated JSON object string 33 | 34 | jo_t jo_parse_query(const char *buf); 35 | // Parse a query string format into a JSON object string (allocated) 36 | 37 | jo_t jo_parse_mem(const void *buf, size_t len); 38 | // Start parsing a JSON string in memory - does not need a null 39 | 40 | jo_t jo_create_mem(void *buf, size_t len); 41 | // Start creating JSON in memory at buf, max space len. 42 | 43 | jo_t jo_create_alloc(void); 44 | // Start creating JSON in memory, allocating space as needed. 45 | 46 | jo_t jo_object_alloc(void); 47 | // As so common, this does jo_create_alloc(), and jo_object() 48 | 49 | jo_t jo_pad(jo_t *, int); 50 | // Attempt to ensure padding on jo, else free jo and return NULL 51 | 52 | jo_t jo_copy(jo_t); 53 | // Copy object - copies the object, and if allocating memory, makes copy of the allocated memory too 54 | 55 | const char *jo_rewind(jo_t); 56 | // Move to start for parsing. If was writing, closed and set up to read instead. Clears error if reading. Safe to call with NULL 57 | // If safe with terminating NULL then returns pointer to the complete JSON 58 | 59 | int jo_level(jo_t); 60 | // Current level, 0 being the top level 61 | 62 | const char *jo_error(jo_t, int *pos); 63 | // Return NULL if no error, else returns an error string. 64 | // Note, for creating JSON, this reports and error if not enough space to finish creating 65 | // If pos is set then the offset in to the JSON is retported 66 | 67 | void jo_free(jo_t *); 68 | // Free jo_t and any allocated memory (safe to call with NULL or pointer to NULL) 69 | 70 | int jo_isalloc(jo_t); 71 | // If it is allocated so finisha can be used 72 | 73 | char *jo_finish(jo_t *); 74 | // Finish creating static JSON, return start of static JSON if no error. Frees j. It is an error to use with jo_create_alloc 75 | 76 | char *jo_finisha(jo_t *); 77 | // Finish creating allocated JSON, returns start of alloc'd memory if no error. Frees j. If NULL returned then any allocated space also freed 78 | // It is an error to use with non jo_create_alloc 79 | 80 | int jo_len(jo_t); // Current length of object (including any closing needed) 81 | 82 | // Creating 83 | // Note that tag is required if in an object and must be null if not 84 | 85 | void jo_array(jo_t, const char *tag); 86 | // Start an array 87 | 88 | void jo_object(jo_t, const char *tag); 89 | // Start an object 90 | 91 | void jo_close(jo_t); 92 | // Close current array or object 93 | 94 | void jo_json(jo_t j,const char *tag,jo_t json); 95 | // Add a json sub object 96 | 97 | void jo_stringn(jo_t, const char *tag, const char *string, ssize_t len); 98 | #define jo_string(j,t,s) jo_stringn(j,t,s,-1) 99 | // Add a string 100 | 101 | void jo_stringf(jo_t, const char *tag, const char *format, ...); 102 | // Add a string (formatted) 103 | 104 | void jo_lit(jo_t, const char *tag, const char *lit); 105 | void jo_litf(jo_t, const char *tag, const char *format, ...); 106 | // Add a literal string (formatted) - caller is expected to meet JSON rules - used typically for numeric values 107 | 108 | void jo_datetime(jo_t j, const char *tag, time_t t); 109 | // Add a datetime (ISO, Z) 110 | 111 | extern const char JO_BASE64[]; 112 | extern const char JO_BASE32[]; 113 | extern const char JO_BASE16[]; 114 | 115 | void jo_baseN(jo_t j, const char *tag, const void *src, size_t slen, uint8_t bits, const char *alphabet); 116 | // Store string in different bases 117 | #define jo_base64(j,t,m,l) jo_baseN(j,t,m,l,6,JO_BASE64) 118 | #define jo_base32(j,t,m,l) jo_baseN(j,t,m,l,5,JO_BASE32) 119 | #define jo_base16(j,t,m,l) jo_baseN(j,t,m,l,4,JO_BASE16) 120 | 121 | ssize_t jo_strncpyd(jo_t j, void *dst, size_t dlen, uint8_t bits, const char *alphabet); 122 | #define jo_strncpy64(j,d,dl) jo_strncpyd(j,d,dl,6,JO_BASE64) 123 | #define jo_strncpy32(j,d,dl) jo_strncpyd(j,d,dl,5,JO_BASE32) 124 | #define jo_strncpy16(j,d,dl) jo_strncpyd(j,d,dl,4,JO_BASE16) 125 | 126 | void jo_int(jo_t, const char *tag, int64_t); 127 | // Add an integer 128 | 129 | void jo_bool(jo_t, const char *tag, int); 130 | // Add a bool (true if non zero passed) 131 | 132 | void jo_null(jo_t, const char *tag); 133 | // Add a null 134 | 135 | // Parsing 136 | 137 | jo_type_t jo_here(jo_t); 138 | // Here returns where we are in the parse 139 | 140 | jo_type_t jo_next(jo_t); 141 | // Move to next element we can parse (validating what we move over as we go) 142 | 143 | jo_type_t jo_skip(jo_t); 144 | // Skip this value to next value AT THE SAME LEVEL, typically used where a tag is not what you are looking for, etc 145 | 146 | jo_type_t jo_find(jo_t,const char *); 147 | // Rewind and look for path, e.g. tag.tag... and return type of value for that point. Does not do arrays, yet. JO_END for no find 148 | 149 | ssize_t jo_strlen(jo_t); 150 | // Return byte length, if a string or tag this is the decoded byte length, else length of literal 151 | 152 | ssize_t jo_strncpy(jo_t, void *, size_t max); 153 | // Copy from current point to a string. If a string or a tag, remove quotes and decode/deescape - max is size of target in to which a null is always added 154 | 155 | ssize_t jo_strncmp(jo_t, void *, size_t max); 156 | // Compare from current point to a string. If a string or a tag, remove quotes and decode/deescape 157 | 158 | #define jo_strcmp(j,s) jo_strncmp(j,s,strlen(s)) 159 | 160 | // Allocate a copy of string 161 | char *jo_strdup(jo_t); 162 | 163 | // Get a number 164 | int64_t jo_read_int(jo_t); 165 | long double jo_read_float(jo_t); 166 | 167 | // Get a datetime 168 | time_t jo_read_datetime(jo_t); 169 | -------------------------------------------------------------------------------- /include/revk.h: -------------------------------------------------------------------------------- 1 | // Include file for revk.c 2 | 3 | #ifndef REVK_H 4 | #define REVK_H 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "esp_wifi.h" 13 | #include "esp_system.h" 14 | #include "nvs_flash.h" 15 | #include "esp_event.h" 16 | #include "esp_timer.h" 17 | 18 | #include "freertos/FreeRTOS.h" 19 | #include "freertos/task.h" 20 | #include "freertos/semphr.h" 21 | #include "freertos/queue.h" 22 | #include "freertos/event_groups.h" 23 | 24 | #include "lwip/sockets.h" 25 | #include "lwip/dns.h" 26 | #include "lwip/netdb.h" 27 | 28 | #include "esp_log.h" 29 | #ifdef CONFIG_REVK_MQTT 30 | #include "lwmqtt.h" 31 | #endif 32 | #ifdef CONFIG_REVK_APMODE 33 | #include "esp_http_server.h" 34 | #endif 35 | #include "jo.h" 36 | 37 | #include "esp8266_httpd_compat.h" 38 | #include "esp8266_netif_compat.h" 39 | 40 | // Types 41 | 42 | // MQTT rx callback: Do not consume jo_t! Return error or NULL. Returning "" means handled the command with no error. 43 | // You will want to check prefix matches prefixcommand 44 | // Target can be something not for us if extra subscribes done, but if it is for us, or internal, it is passes as NULL 45 | // Suffix can be NULL 46 | typedef const char *app_callback_t(int client, const char *prefix, const char *target, const char *suffix, jo_t); 47 | typedef uint8_t mac_t[6]; 48 | 49 | // Data 50 | extern const char *revk_app; // App name 51 | extern const char *revk_version; // App version 52 | extern const char revk_build_suffix[]; // App build suffix 53 | extern char revk_id[13]; // Chip ID hex (from MAC) 54 | extern mac_t revk_mac; // Our mac 55 | extern uint64_t revk_binid; // Chip ID binary 56 | extern char *prefixcommand; 57 | extern char *prefixsetting; 58 | extern char *prefixstate; 59 | extern char *prefixevent; 60 | extern char *prefixinfo; 61 | extern char *prefixerror; 62 | extern char *appname; 63 | extern char *hostname; 64 | extern char *nodename; // Node name 65 | extern esp_netif_t *sta_netif; 66 | extern esp_netif_t *ap_netif; 67 | 68 | jo_t jo_make(const char *nodename); // Start object with node name 69 | 70 | typedef struct { // Dynamic binary data 71 | uint16_t len; 72 | uint8_t data[]; 73 | } revk_bindata_t; 74 | 75 | #define freez(x) do{if(x){free((void*)x);x=NULL;}}while(0) // Just useful - yes free(x) is valid when x is NULL, but this sets x NULL as a result as well 76 | 77 | // Calls 78 | void revk_boot(app_callback_t * app_callback); 79 | void revk_start(void); 80 | void revk_pre_shutdown(void); 81 | // Register a setting, call from init (i.e. this is not expecting to be thread safe) - sets the value when called and on revk_setting/MQTT changes 82 | // Note, a setting that is SECRET that is a root name followed by sub names creates parent/child. Only shown if parent has value or default value (usually overlap a key child) 83 | void revk_register(const char *name, // Setting name (note max 15 characters inc any number suffix) 84 | uint8_t array, // If non zero then settings are suffixed numerically 1 to array 85 | uint16_t size, // Base setting size, -8/-4/-2/-1 signed, 1/2/4/8 unsigned, 0=null terminated string. 86 | void *data, // The setting itself (for string this points to a char* pointer) 87 | const char *defval, // default value (default value text, or bitmask[space]default) 88 | int flags); // Setting flags 89 | #define SETTING_LIVE 1 // Setting update live (else reboots shortly after any change) 90 | #define SETTING_BINDATA 2 // Binary block (text is base64 or hex) rather than numeric. Fixed is just the data (malloc), variable is pointer to revk_bin_t 91 | #define SETTING_SIGNED 4 // Numeric is signed 92 | #define SETTING_BOOLEAN 8 // Boolean value (array sets bits) 93 | #define SETTING_BITFIELD 16 // Numeric value has bit field prefix (from defval string) 94 | #define SETTING_HEX 32 // Source string is hex coded 95 | #define SETTING_SET 64 // Set top bit of numeric if a value is present at all 96 | #define SETTING_SECRET 128 // Don't dump setting 97 | #define SETTING_FIX 256 // Store in flash regardless, so default only used on initial s/w run 98 | 99 | #if CONFIG_LOG_DEFAULT_LEVEL > 2 100 | esp_err_t revk_err_check(esp_err_t, const char *file, int line, const char *func, const char *cmd); // Log if error 101 | #define REVK_ERR_CHECK(x) revk_err_check(x,__FILE__,__LINE__,__FUNCTION__,#x) 102 | #else 103 | esp_err_t revk_err_check(esp_err_t e); 104 | #define REVK_ERR_CHECK(x) revk_err_check(x) 105 | #endif 106 | 107 | // Make a task 108 | TaskHandle_t revk_task(const char *tag, TaskFunction_t t, const void *param,int kstack); 109 | 110 | // reporting via main MQTT, copy option is how many additional MQTT to copy, normally 0 or 1. Setting -N means send only to specific additional MQTT, return NULL for no error 111 | const char* revk_mqtt_send_raw(const char *topic, int retain, const char *payload, uint8_t clients); 112 | const char* revk_mqtt_send_payload_clients(const char *prefix, int retain, const char *suffix, const char *payload, uint8_t clients); 113 | const char* revk_mqtt_send_str_clients(const char *str, int retain, uint8_t clients); 114 | #define revk_mqtt_send_str(s) revk_mqtt_send_str_clients(s,0,1); 115 | const char* revk_state_clients(const char *suffix, jo_t *, uint8_t clients); 116 | #define revk_state(t,j) revk_state_clients(t,j,1) 117 | const char* revk_event_clients(const char *suffix, jo_t *, uint8_t clients); 118 | #define revk_event(t,j) revk_event_clients(t,j,1) 119 | const char* revk_error_clients(const char *suffix, jo_t *, uint8_t clients); 120 | #define revk_error(t,j) revk_error_clients(t,j,1) 121 | const char* revk_info_clients(const char *suffix, jo_t *, uint8_t clients); 122 | #define revk_info(t,j) revk_info_clients(t,j,1) 123 | 124 | const char* revk_mqtt_send_clients(const char *prefix, int retain, const char *suffix, jo_t * jp, uint8_t clients); 125 | #define revk_mqtt_send(p,r,t,j) revk_mqtt_send_clients(p,r,t,j,1) 126 | 127 | const char *revk_setting(jo_t); // Store settings 128 | const char *revk_command(const char *tag, jo_t); // Do an internal command 129 | const char *revk_restart(const char *reason, int delay); // Restart cleanly 130 | const char *revk_ota(const char *host, const char *target); // OTA and restart cleanly (target NULL for self as root node) 131 | uint32_t revk_shutting_down(const char **); // If we are shutting down (how many seconds to go) - sets reason if not null 132 | const char *revk_build_date(char d[20]); // Get build date ISO formatted 133 | int8_t revk_ota_progress(void); // Progress (-2=up to date, -1=not, 0-100 is progress, 101=done) 134 | 135 | #ifdef CONFIG_REVK_MQTT 136 | void revk_mqtt_init(void); 137 | lwmqtt_t revk_mqtt(int); 138 | void revk_mqtt_close(const char *reason); // Clean close MQTT 139 | int revk_wait_mqtt(int seconds); 140 | #endif 141 | #if defined(CONFIG_REVK_WIFI) || defined(CONFIG_REVK_MESH) 142 | uint32_t revk_link_down(void); // How long link down (no IP or no parent if mesh) 143 | #define MESH_PAD 32 // Max extra allocated bytes required on data 144 | const char *revk_wifi(void); // Return the wifi SSID 145 | void revk_wifi_close(void); // Close wifi 146 | int revk_wait_wifi(int seconds); // Wait for wifi 147 | #endif 148 | #ifdef CONFIG_REVK_MESH 149 | extern uint16_t meshmax; 150 | void revk_send_sub(int client, const mac_t); 151 | void revk_send_unsub(int client, const mac_t); 152 | void revk_mesh_send_json(const mac_t mac, jo_t * jp); 153 | #endif 154 | void revk_blink(uint8_t on, uint8_t off, const char *colours); // Set LED blink rate and colour sequence for on state (for RGB LED) 155 | 156 | #ifdef CONFIG_REVK_APMODE 157 | esp_err_t revk_web_settings_add(httpd_handle_t webserver); // Add URLs 158 | esp_err_t revk_web_settings_remove(httpd_handle_t webserver); // Remove URLs 159 | esp_err_t revk_web_settings(httpd_req_t * req); // Call for web config for SSID/password/mqtt (GET/POST) - needs 4 URLS 160 | esp_err_t revk_web_status(httpd_req_t * req); // Call for web config for SSID/password/mqtt (WS) 161 | esp_err_t revk_web_wifilist(httpd_req_t * req); // WS for list of SSIDs 162 | void revk_web_head(httpd_req_t * req,const char *title); // Generic html heading 163 | esp_err_t revk_web_foot(httpd_req_t * req,uint8_t home,uint8_t wifi); // Generic html footing and return 164 | 165 | #endif 166 | #endif 167 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | menu "RevK" 2 | 3 | config REVK_APPNAME 4 | string "Override app name" 5 | default "" 6 | help 7 | Default app name to use 8 | 9 | config REVK_PREFIXAPP 10 | bool "MQTT uses appname as a prefix" 11 | default y 12 | help 13 | The MQTT strings have prefix (e.g. command) then appname then the hostname. The appname can be turned off 14 | 15 | config REVK_BLINK 16 | string "Blink GPIOs" 17 | default "" 18 | help 19 | One or more (space separated) LED GPIOs 20 | 21 | config REVK_WIFI 22 | bool "Manage WiFi client" 23 | default y 24 | help 25 | Manage client WiFi 26 | 27 | config REVK_MESH 28 | bool "Mesh WiFi mode" 29 | default n 30 | depends on !REVK_WIFI 31 | help 32 | Enable WiFi Mesh operation 33 | 34 | config REVK_MESHRESET 35 | int "Reset if we are offline too long" 36 | default 3600 37 | depends on REVK_MESH 38 | help 39 | Number of seconds for mesh root with no IP before reset 40 | 41 | config REVK_MESHID 42 | string "Mesh ID (6 byte hex)" 43 | default "" 44 | depends on REVK_MESH 45 | help 46 | Mesh network ID (12 characters hex) 47 | 48 | config REVK_MESHPASS 49 | string "Mesh network passphrase" 50 | default "" 51 | depends on REVK_MESH 52 | help 53 | Mesh network passphrase 54 | 55 | config REVK_MESHWIDTH 56 | int "Mesh network connections per node" 57 | default 10 58 | depends on REVK_MESH 59 | help 60 | Mesh network connections per node 61 | 62 | config REVK_MESHDEPTH 63 | int "Mesh network max depth" 64 | default 10 65 | depends on REVK_MESH 66 | help 67 | Mesh network connections max depth 68 | 69 | config REVK_MESHMAX 70 | int "Mesh max capacity" 71 | default 100 72 | depends on REVK_MESH 73 | help 74 | Total nodes allowed 75 | 76 | config REVK_MESHLR 77 | bool "Mesh LR mode" 78 | default n 79 | depends on REVK_MESH 80 | help 81 | Run mesh in LR mode 82 | 83 | config REVK_WIFISSID 84 | string "Default WiFi SSID" 85 | default "IoT" 86 | depends on REVK_WIFI || REVK_MESH 87 | help 88 | This defines the factory reset default WiFi SSID 89 | 90 | config REVK_WIFIPASS 91 | string "Default WiFi passphrase" 92 | default "security" 93 | depends on REVK_WIFI || REVK_MESH 94 | help 95 | This defines the factory reset default WiFi passphrase 96 | 97 | config REVK_WIFIBSSID 98 | string "Default WiFi BSSID (6 bytes)" 99 | default "" 100 | depends on REVK_WIFI || REVK_MESH 101 | help 102 | This defines the factory reset default WiFi BSSID (hex 12 characters) 103 | 104 | config REVK_WIFICHAN 105 | int "WiFi channel" 106 | default 0 107 | depends on REVK_WIFI || REVK_MESH 108 | help 109 | This defines the factory reset WiFi channel 110 | 111 | config REVK_WIFIIP 112 | string "Default WiFi Static IP" 113 | default "" 114 | depends on REVK_WIFI || REVK_MESH 115 | help 116 | This defines the factory reset default WiFi client static IP / CIDR 117 | 118 | config REVK_WIFIGW 119 | string "Default WiFi Static gateway" 120 | default "" 121 | depends on REVK_WIFI || REVK_MESH 122 | help 123 | This defines the factory reset default WiFi client static gateway 124 | 125 | config REVK_WIFIDNS 126 | string "Default WiFi DNS" 127 | default "" 128 | depends on REVK_WIFI || REVK_MESH 129 | help 130 | This defines the factory reset default WiFi client DNS 131 | 132 | config REVK_WIFIRESET 133 | int "Reset if we are offline too long" 134 | default 3600 135 | depends on REVK_WIFI || REVK_MESH 136 | help 137 | Number of seconds off line before we completely reset 138 | 139 | config REVK_WIFIPS 140 | bool "WiFi power save" 141 | default n 142 | depends on REVK_WIFI || REVK_MESH 143 | help 144 | Set WiFi power save mode 145 | 146 | config REVK_WIFIMAXPS 147 | bool "WiFi max power save" 148 | default n 149 | depends on REVK_WIFIPS 150 | help 151 | Set WiFi to maximum power save mode 152 | 153 | config REVK_APGPIO 154 | string "AP mode GPIO" 155 | default "" 156 | depends on REVK_WIFI 157 | help 158 | GPIO to force AP mode 159 | 160 | config REVK_APSSID 161 | string "Access point SSID" 162 | default "" 163 | depends on REVK_WIFI 164 | help 165 | SSID for access point mode 166 | 167 | config REVK_APPASS 168 | string "Access point passphrase" 169 | default "" 170 | depends on REVK_WIFI 171 | help 172 | Passphrase for access point mode 173 | 174 | config REVK_APMAX 175 | int "Max AP connections" 176 | default 10 177 | depends on REVK_WIFI 178 | help 179 | Max concurrent AP connections 180 | 181 | config REVK_APIP 182 | string "Access point IP" 183 | default "10.0.0.1/24" 184 | depends on REVK_WIFI 185 | help 186 | IP allocation for access point mode 187 | 188 | config REVK_APLR 189 | bool "Access point LR mode" 190 | default n 191 | depends on REVK_WIFI 192 | help 193 | Run access point in LR mode 194 | 195 | config REVK_APHIDE 196 | bool "Access point hidden SSID" 197 | default n 198 | depends on REVK_WIFI 199 | help 200 | Run AP in hidden SSID mode 201 | 202 | config REVK_MQTT 203 | bool "Manage MQTT client" 204 | default y 205 | help 206 | Manage client MQTT 207 | 208 | config REVK_MQTTHOST 209 | string "Default MQTT host" 210 | default "mqtt.iot" 211 | depends on REVK_MQTT 212 | help 213 | This defines the factory reset default MQTT host 214 | 215 | config REVK_MQTTUSER 216 | string "Default MQTT username" 217 | default "" 218 | depends on REVK_MQTT 219 | help 220 | This defines the factory reset MQTT username 221 | 222 | config REVK_MQTTPASS 223 | string "Default MQTT password" 224 | default "" 225 | depends on REVK_MQTT 226 | help 227 | This defines the factory reset MQTT password 228 | 229 | config REVK_MQTTCERT 230 | string "Default MQTT certificate" 231 | default "" 232 | depends on REVK_MQTT 233 | help 234 | This defines the factory reset MQTT certificate 235 | 236 | config REVK_MQTTPORT 237 | int "Default MQTT port" 238 | default 0 239 | depends on REVK_MQTT 240 | help 241 | This defines the factory reset MQTT port (0 for standard) 242 | 243 | config REVK_MQTTSIZE 244 | int "Default MQTT packet size" 245 | default 2048 246 | depends on REVK_MQTT 247 | help 248 | This defines the factory reset MQTT packet size 249 | 250 | config REVK_OTAHOST 251 | string "Default OTA host" 252 | default "ota.iot" 253 | help 254 | This defines the factory reset default OTA host (https) 255 | 256 | config REVK_OTAAUTO 257 | int "Default auto upgrade check (days)" 258 | default 7 259 | help 260 | Number of days between checks for auto upgrade (0 for don't auto upgrade) 261 | 262 | config REVK_OTACERT 263 | string "Default OTA certificate" 264 | default "" 265 | help 266 | This defines the factory reset default OTA certificate 267 | 268 | config REVK_NTPHOST 269 | string "Default NTP host" 270 | default "pool.ntp.org" 271 | help 272 | This defines the factory reset default NTP host 273 | 274 | config REVK_TZ 275 | string "Default TZ (timezone)" 276 | default "GMT+0BST,M3.5.0,M10.5.0" 277 | help 278 | This defines the TZ (timezone) control 279 | 280 | config REVK_APMODE 281 | bool "Enable AP when not connected to WiFi, or on button, etc" 282 | default y 283 | depends on REVK_WIFI 284 | help 285 | Enable Access point mode 286 | 287 | config REVK_APDNS 288 | bool "Enable dummy DNS in AP mode" 289 | default y 290 | depends on REVK_APMODE 291 | help 292 | Enable dummy DNS returning our IP to allow splash screen 293 | 294 | config REVK_APCONFIG 295 | bool "Enable web page to set basic settings when APMODE active" 296 | default y 297 | depends on REVK_APMODE 298 | help 299 | Enable web page for basic settings when in AP MODE 300 | 301 | config REVK_APPORT 302 | int "Default AP mode port" 303 | depends on REVK_APCONFIG 304 | default 0 305 | help 306 | The TCP port for web setup page in AP mode 307 | 308 | config REVK_APWAIT 309 | int "Default AP mode delay" 310 | depends on REVK_APMODE 311 | default 10 312 | help 313 | Default time for starting AP mode 314 | 315 | config REVK_APTIME 316 | int "Default AP active time" 317 | depends on REVK_APMODE 318 | default 600 319 | help 320 | Default time for AP mode 321 | 322 | config REVK_PARTITION_CHECK 323 | bool "Check and update partition table" 324 | depends on SPI_FLASH_DANGEROUS_WRITE_ALLOWED 325 | default n 326 | help 327 | Enable automatic checking of partition table, and update if necessary 328 | 329 | config REVK_LOCK_CPU1 330 | bool "Lock tasks to CPU1" 331 | default y 332 | help 333 | Lock user tasks to CPU 1 334 | 335 | config REVK_SHORT_ID 336 | bool "Make a short ID" 337 | default n 338 | help 339 | Make a short (6 hex chars) ID rather than full MAC 340 | 341 | config REVK_BUILD_SUFFIX 342 | string "Build suffix" 343 | default "" 344 | help 345 | Don't set this manually - it is normally set by Makefile (buildsuffix script) 346 | 347 | config REVK_PICO 348 | bool "ESP32-PICO" 349 | default n 350 | help 351 | If this is built for ESP32-PICO 352 | 353 | config REVK_D4 354 | bool "ESP32-D4" 355 | default n 356 | help 357 | If this is built for ESP32-D4 358 | 359 | endmenu 360 | -------------------------------------------------------------------------------- /revk-user.md: -------------------------------------------------------------------------------- 1 | # ESP32 RevK support library 2 | 3 | The `ESP32-RevK` support library is used in almost all of the ESP32 projects on this repository. It provides basic management of WiFi connections, settings, MQTT, and JSON. 4 | 5 | This manual covers the user view of this library in terms of interacting with any of the projects using it over MQTT. 6 | 7 | 8 | ## App name 9 | 10 | The application will have a name. A good example is the Daikin appi, e.g. see https://github.com/revk/ESP32-Daikin which is, as you may guess `Daikin`. 11 | 12 | ## WiFi Settings 13 | 14 | One of the key features is allowing WiFi to be configured on a new unit. This is a config option so does not have to be enabled, but if it is then when a unit is unable to connect to local WiFI, it changes to be an access point. 15 | The WiFI name you see starts with the app name. 16 | 17 | ![IMG_2446](https://user-images.githubusercontent.com/996983/218394248-b409626b-2614-439d-95f4-71527c00aaa7.PNG) 18 | 19 | If you select this on an iPhone, it auto loads the config page. On other devices you have to check the router IP for the subnet and enter that in to a browser. Either way you get the WiFi settings page that will look something like this (other fields may be added over time). 20 | 21 | ![IMG_2448](https://user-images.githubusercontent.com/996983/218394254-e03537f7-09a0-490d-aa38-b6964a5cd77f.PNG) 22 | 23 | You can click the buttons for existing SSID, or enter manually, and enter password. It then tries to connect and shows the IP so you can connect to any web interface on the device. Not all devices have a web interface. 24 | 25 | However, the MQTT settings allow control and settings to be configured over MQTT. 26 | 27 | ## Software updates 28 | 29 | It is usually a good idea to ensure software is up to date. The system has a setting for the `otahost` which will default to `ota.revk.uk` but can be your own server, obviously. 30 | 31 | You can do an upgrade from the web control pages for most apps with a link from the WiFi settings page. You can also do an `upgrade` command from MQTT (which allows the full URL and file to be specified, if needed). 32 | 33 | However, for most apps (based on the `otaauto` settings) upgrades will be checked every few days, and done if needed. This is normally within one to two hours of start up (to allow you time to make any changes if needed, including turning off auto update), or the middle of the night (to minimise disruption). The server is checked and the update and restart is only done if there is a new version. 34 | 35 | 36 | 37 | ## MQTT 38 | 39 | The system will connect to an MQTT server and provide information via MQTT, allow commands over MQTT, and allow settings over MQTT. 40 | 41 | ### Topics 42 | 43 | There are two styles, which depend on a config option. One style has (`/` separated) *prefix*, then *app name*, then *device id*, then an optional suffix. The other format omits the *app name*. 44 | 45 | The *device id* is either a hex device ID, its MAC address, or the `hostname` setting value if set. 46 | 47 | Where the topic has an *app name* you can command all of the device with that *app name* by using a *device name* of `*`. 48 | Where the topic does not have the *app name* you can command all of the devices with the same *app name* by using the *app name* as the *device name*. 49 | 50 | #### Messages to the device 51 | 52 | In most cases the payload, if any, is JSON. This could however by a JSON data type such as a number, or string, rather than an actual object. 53 | 54 | |Prefix|Meaning| 55 | |------|-------| 56 | |`command`|Does a command. This does not change settings but could change some live status of some sort, or do an action. In some cases commands can talk to external devices, such as the SDC41 in the Environmental monitor.| 57 | |`setting`|Changes a setting value, or gets settings. See below| 58 | 59 | #### Messages from the device 60 | 61 | In most cases the payload is JSON, usually as a JSON object. 62 | 63 | |Prefix|Meaning| 64 | |------|-------| 65 | |`state`|This is sent with *retain* and relates to the state of some aspect of the device. With no suffix, this is a top level state for the device, in JSON, including either `"up":false` or `"up":`*time*. With a suffix this is the state of some aspect of the device.| 66 | |`event`|This is for an event, rather than a state change. A good example might be a key press on a device.| 67 | |`info`|This is information of some sort| 68 | |`error`|This is an error message| 69 | |`setting`|This is the current settings, as a JSON object, if requested| 70 | 71 | ### Commands 72 | 73 | The device may have any number of commands documents, but there are some commands provided directly by the library for all devices. 74 | 75 | |Command|Meaning| 76 | |-------|-------| 77 | |`upgrade`|This does an *over the air* upgrade from the setting defined `otahost`. You can include a URL as the argument (`http://` only, not `https`). Usually the device will be build with code signing to ensure the file is genuine.| 78 | |`restart`|This does a restart of the device| 79 | |`factory`|This does a factory reset of all settings, the argument has to be a string of the MAC address and the app name, e.g. `112233445566TestApp`| 80 | |`ps`|This provides a process list, if `FREERTOS_USE_TRACE_FACILITY` is set in `sdkconfig`| 81 | 82 | ### Settings 83 | 84 | The settings system currently uses JSON, but does also have a fallback for a single setting using the full setting name. 85 | 86 | For example, setting the `otahost` could be done by sending `setting/App/Dev/otahost example.com` or by sending `setting/App/Dev {"otahost":"example.com"}`. The recommended method is to use JSON, which means no suffix on the `setting` message. 87 | 88 | Sending a `setting` message with no suffix and no payload causes a `setting` response to be sent with current settings. If the settings are too long for one message then multiple messages are sent covering all of th settings using a number of distinct objects. 89 | 90 | All settings have a simple name, but some settings can also be accessed in a nested style, as a sub object. The settings sent back from the device use this. Also, some settings have have a number of values, and these can be sent as a JSON array. For example ther are settings `mqtthost`, `mqttuser`, `mqttpass`, etc. These can be sent as as `{"mqtt":{"host":"whatever","user":"whatever","pass":"whatever"}`. Sending an object like this will mean clearing any sub objects not included in the object, e.g. sending `{"mqtt":{"host":"example.com"}` means that `mqttuser` and `mqttpass` are unset (set to empty string). 91 | 92 | #### Main settings 93 | 94 | |Setting|Meaning| 95 | |-------|-------| 96 | |`appname`|The name of the application. You do not normally want to override this.| 97 | |`hostname`|The name to use for this device in topic, and DHCP and so on. This defaults the hex MAC address if not set or set to an empty string.| 98 | |`otahost`|Hostname for *over the air* updates| 99 | |`otaauto`|If not `0` then check for updates periodically (this many days, approx), and do upgrade if needed.| 100 | |`wifissid`|WiFi SSID to use| 101 | |`wifipass`|WiFi passphrase to use| 102 | |`mqtthost`|MQTT hostname| 103 | 104 | #### Advanced settings 105 | 106 | |Setting|Meaning| 107 | |-------|-------| 108 | |`mqttuser`|MQTT username| 109 | |`mqttpass`|MQTT password| 110 | |`mqttport`|MQTT TCP port| 111 | |`mqttcert`|MQTT certificate - PEM format TLS certificate for the server. If set this forces MQTT over TLS and a default port of `8883`| 112 | |`clientkey`|PEM format TLS client private key for use on TLS (e.g. for MQTTS and HTTPS)| 113 | |`clientcert`|PEM format TLS client certificate for use on TLS (e.g. for MQTTS and HTTPS)| 114 | |`otacert`|PEM format TLS certificate for the server, forces OTA using HTTPS - only sensible on devices with enough RAM. Default is to use HTTP and have signed code.| 115 | |`nodename`|This is not usually used, but if set it means `"node":`*nodename* will be included in various types of message sent.| 116 | |`wifichan`|WiFi channel to use, default is scan all channels| 117 | |`wifibssid`|Hex WiFi BSSID to use, default is any| 118 | |`wifireset`|Time (in seconds) with no WiFI before resetting device| 119 | |`wifiip`|Static IPv4 for WiFi| 120 | |`wifigw`|Static IPv4 gateway for WiFi| 121 | |`wifidns`|Static IPv4 DNS server for WiFi| 122 | |`wifimqtt`|This is a special case, an SSID to use if possible (falls back to normal `wifissid`), and connect via MQTT to the router IP address received.| 123 | |`blink`|Either one GPIO number or an array of GPIO numbers for *R*, *G*, *B* LEDs, prefix each with `-` for active low LED.| 124 | |`apport`|The TCP port for access point web page (normally 80)| 125 | |`apwait`|The time in seconds before entering AP mode when no WiFi| 126 | |`aptime`|The time to stay in AP mode| 127 | |`apgpio`|The GPIO to check to force in to AP mode, this allows a button to force AP mode, for example.| 128 | |`apssid`|The SSID to use in AP mode, defaults to the `appname` based AP name| 129 | |`appass`|The passphrase to use in AP mode, usually you want this as an empty string for no password| 130 | |`aplr`|Do AP mode using ESP specific *long range* WiFi mode| 131 | |`aphide`|Do AP mode as hidden SSID| 132 | |`meshid`|Work in mesh mode and use this as the mesh ID, a 12 character HEX string| 133 | |`mesgpass`|The passphrase for mesh mode working| 134 | |`prefixcommand`|The prefix for `command`| 135 | |`prefixsetting`|The prefix for `setting`| 136 | |`prefixstate`|The prefix for `state`| 137 | |`prefixevent`|The prefix for `event`| 138 | |`prefixinfo`|The prefix for `info`| 139 | |`prefixerror`|The prefix for `error`| 140 | -------------------------------------------------------------------------------- /revk-dev.md: -------------------------------------------------------------------------------- 1 | # ESP32 RevK support library 2 | 3 | The `ESP32-RevK` support library is used in almost all of the ESP32 projects on this repository. It provides basic management of WiFi connections, settings, MQTT, and JSON. 4 | 5 | This manual covers the use of teh library in an app. 6 | 7 | ## Software update server 8 | 9 | If you are running your own server for software upgrades you need to ensure `http://` is allowed with access to the `.bin` file at the top level. This is because multiple TLS connections are a memory issue on many ESP32 modules. One trick is to allow `http://` if the `User-Agent` is `ESP32 HTTP Client/1.0` and redirect to `https://` for all other cases. As it is not `https://`, you should always build with code signing and checking. Your server also needs to allow `Range:` header for the version check to be done. 10 | 11 | The upgrade checks the `.bin` file using `Range:`, and does not upgrade if no change, so make sure new code has a new `version`, `product_name`, `date` or `time` set, touching `${IDF_PATH}/components/esp_app_format/esp_app_desc.c` as part of your build can ensure this. The `Makefile` for apps usually uses the `buildsuffix` script provided, which does this for you. 12 | 13 | ## RevK 14 | 15 | This is how an application uses the RevK library. 16 | 17 | ### Include 18 | 19 | To use the libraries simply add the include file 20 | ``` 21 | #include "revk.h" 22 | ``` 23 | This includes necessary system includes and `lwmqtt.h` and `jo.h` include files needed. 24 | 25 | ### CMake 26 | 27 | In you `main/CMakeLists.txt ` have 28 | ``` 29 | set (COMPONENT_REQUIRES "ESP32-RevK) 30 | ``` 31 | 32 | ### Init 33 | 34 | In `void app_main()` you need, close to the start 35 | ``` 36 | revk_boot(&app_callback); 37 | ``` 38 | And once you have done any settings (see below) do 39 | ``` 40 | revk_start(); 41 | ``` 42 | 43 | The `app_callback` is `const char *app_callback(int client, const char *prefix, const char *target, const char *suffix, jo_t j)` which is called for any received MQTT messages. The return value is an empty string for all OK, or an error message. NULL means not handled and not an error (which usually means an error as unknown command). 44 | 45 | ### Settings 46 | 47 | Between `revk_boot` and `revk_start` you should add necessary calls to `revk_register(...)` to add any settings you need. 48 | ``` 49 | void revk_register(const char *name, // Setting name (note max 15 characters inc any number suffix) 50 | uint8_t array, // If non zero then settings are suffixed numerically 1 to array 51 | uint16_t size, // Base setting size, -8/-4/-2/-1 signed, 1/2/4/8 unsigned, 0=null terminated string. 52 | void *data, // The setting itself (for string this points to a char* pointer) 53 | const char *defval, // default value (default value text, or bitmask[space]default) 54 | uint8_t flags); // Setting flags 55 | ``` 56 | The way this is typically done is a list of settings in a macro, allowing the definition of the settings and the calling of the `revk_register` all to be done from the same list. 57 | 58 | For example, define settings like this 59 | 60 | ``` 61 | #define settings \ 62 | u8(webcontrol,2) \ 63 | bl(debug) \ 64 | ``` 65 | 66 | You can then define the values, e.g. 67 | 68 | ``` 69 | #define u8(n,d) uint8_t n; 70 | #define bl(n) uint8_t n; 71 | settings 72 | #undef u8 73 | #undef bl 74 | ``` 75 | 76 | And in `app_main` call the `revk_register` like this. 77 | 78 | ``` 79 | #define bl(n) revk_register(#n,0,sizeof(n),&n,NULL,SETTING_BOOLEAN|SETTING_LIVE); 80 | #define u8(n,d) revk_register(#n,0,sizeof(n),&n,str(d),0); 81 | settings 82 | #undef u8 83 | #undef bl 84 | ``` 85 | 86 | Obviously there could be way more types and flags you can use for different types of settings. This example uses `bl()` for "Boolean, live update", and `u8()` for `uint8_t` with a default value. 87 | 88 | It is possible to flag fields as needing various bit tags based on a string of characters, and even as needing hex encoding of the value. Settings can live, and apply when sent, or by default they are stored and a reboot is done in a few seconds. It is a good idea to look at some of the existing apps to see the ways settings can be used. 89 | 90 | #### Flags 91 | 92 | |Flag|meaning| 93 | |----|-------| 94 | |`LIVE`|The setting is always applied live, it also gets written to flash but does not cause a reboot.| 95 | |`BINDATA`|This is a binary block. If fixed size then this is just a malloc'd block. If variable then this is a pointer to `revk_bin_t` which incldes a length| 96 | |`SIGNED`|Numeric value is signed| 97 | |`BOOLEAN`|Boolean - if an array then an array of bits in a value| 98 | |`BITFIELD`|Numeric value has high bits reserved for a series of character flags (initial string in the default value string followed by a space and actual default)| 99 | |`HEX`|Source is hex coded| 100 | |`SET`|Top bit of numeric value is reserved - set if the value has been set| 101 | |`SECRET`|Don't output this setting| 102 | |`FIX`|This setting is always written to flash, meaning any defaults are only every used on first run| 103 | 104 | ### Useful functions tracking state 105 | 106 | There are a number of functions to keep track of things... 107 | ``` 108 | uint32_t revk_link_down(void); // How long link down (no IP or no parent if mesh) 109 | const char *revk_wifi(void); // Return wifi SSID 110 | void revk_wifi_close(void); // Close WiFi 111 | int revk_wait_wifi(int seconds); // Wait for WiFi to be ready 112 | char *revk_setting(jo_t); // Store settings 113 | const char *revk_command(const char *tag, jo_t); // Do an internal command 114 | const char *revk_restart(const char *reason, int delay); // Restart cleanly 115 | const char *revk_ota(const char *host, const char *target); // OTA and restart cleanly (target NULL for self as root node) 116 | uint32_t revk_shutting_down(void); // If we are shutting down (how many seconds to go) 117 | ``` 118 | 119 | ## LWMQTT 120 | 121 | The `lwmqtt` library is a *light weight MQTT* server and client library used internally by the RevK library. 122 | ``` 123 | lwmqtt_t revk_mqtt(int); // Return the current LWMQTT handle 124 | void revk_mqtt_close(const char *reason); // Clean close MQTT 125 | int revk_wait_mqtt(int seconds); // Wait for MQTT to connect 126 | ``` 127 | 128 | Generally you do not need to directly interact with MQTT, but there are some simple functions to generate MQTT messages. 129 | 130 | To use these you construct a JSON object then call these to send the message and free the object. 131 | ``` 132 | revk_state(const char *suffix,jo_t j); // Send a state message 133 | revk_event(const char *suffix,jo_t j); // Send a event message 134 | revk_info(const char *suffix,jo_t j); // Send a info message 135 | revk_error(const char *suffix,jo_t j); // Send a error message 136 | ``` 137 | Additional lower level functions are defined in `revk.h` and `lwmqtt.h` 138 | 139 | ### Example 140 | 141 | ``` 142 | jo_t j = jo_object_alloc(); 143 | jo_string(j, "field", tag); 144 | jo_string(j, "error", err); 145 | revk_error("control", &j); 146 | ``` 147 | 148 | ## Build tools 149 | 150 | There are also some useful scripts. 151 | 152 | ### `buildsuffix` 153 | 154 | This returns a build suffix, based on the `sdkconfig`. The idea is that you can build different versions for different target chips and accessories, and make a build file for each case. e.g. 155 | 156 | E.g. `Makefile` or other build script having: 157 | 158 | ``` 159 | PROJECT_NAME := LED 160 | SUFFIX := $(shell components/ESP32-RevK/buildsuffix) 161 | 162 | all: 163 | @echo Make: build/$(PROJECT_NAME)$(SUFFIX).bin 164 | @idf.py build 165 | @cp --remove-destination build/$(PROJECT_NAME).bin $(PROJECT_NAME)$(SUFFIX).bin 166 | @echo Done: build/$(PROJECT_NAME)$(SUFFIX).bin 167 | ``` 168 | 169 | ### `setbuildsuffix` 170 | 171 | This sets `sdkconfig` based on a requested build suffix. This can link in to some other components in some cases (see [GFX](https://github.com/revk/ESP32-GFX)), but the simple factors are `S1` for the `S1` silicon, or `S2`, `S3`, etc, and `PICO` for the `ESP32-PICO` chips, and `SOLO` for single processor chips as used in Shelly modules. This means you can make targets, e.g. 172 | 173 | ``` 174 | pico: 175 | components/ESP32-RevK/setbuildsuffix -S1-PICO 176 | @make 177 | 178 | wroom: 179 | components/ESP32-RevK/setbuildsuffix -S1 180 | @make 181 | 182 | solo: 183 | components/ESP32-RevK/setbuildsuffix -S1-SOLO 184 | @make 185 | ``` 186 | 187 | The suffix is then known in the code as `CONFIG_REVK_BUILD_SUFFIX` and used as part of the upgrade process, e.g. in the above examples, the binary file would be `LED-S1-PICO.bin` for the `pico` build. 188 | 189 | ## JO 190 | 191 | The JSON OBJECT library is designed to allow a JSON object to be constructed or parsed to/from a simple in memory string. This is intended to be very memory efficient as it does not create memory structures for the JSON object itself, and for parsing it literally just scans the string itself with minimum overhead. 192 | 193 | The main type used is `jo_t` which is an object to handle either constructing or parsing a JSON string. It is possible to construct a string and then rewind and parse the same string. 194 | 195 | The `jo_t` type has a pointer in to the object. For creating this is constantly moving forward adding fields and values. For parsing it is possible to rewind and go back and move forward through the object. 196 | 197 | Use `jo_free` to free an object, but some functions such as `revk_info`, etc, free for you. 198 | 199 | ### Error handling 200 | 201 | If at any point there is an error, e.g. bad parsing, or bad creating, or memory overrun creating then an error flag is set. You can check with `jo_error` to see if an error. Once set parsing stops (`JO_END` returned) and creating stops (no action). 202 | 203 | ### Parsing JSON 204 | 205 | To parse a JSON object in memory you start with `jo_parse_mem` which is given a buffer and length. 206 | 207 | To move through the object you can use `jo_here` to tell what is at this point, `jo_next` to move to next point and tell what is at that point, `jo_skip` to skip the next value at the same level, e.g. if the next value is an object it skips the whole object, and finally `jo_find` to find a named field in the JSON where you pass a tag that can be *tag*, or *tag.tag*, etc, returning the type of the value it finds. 208 | 209 | The type of where you are can be one of:- 210 | 211 | |Type|Meaning| 212 | |----|-------| 213 | |`JO_END`|End of JSON parsing| 214 | |`JO_CLOSE`|End of object or array, i.e. `}` or `]`| 215 | |`JO_TAG`|The name/tag in an object| 216 | |`JO_OBJECT`|The `{` at the start of an object| 217 | |`JO_ARRAY`|The `[` at the start of an array| 218 | |`JO_STRING`|A string value| 219 | |`JO_NUMBER`|A number value| 220 | |`JO_NULL`|A `null` value| 221 | |`JO_TRUE`|A `true` value| 222 | |`JO_FALSE`|A `faluse` value| 223 | 224 | Walking through an object using `jo_next` sees the start (`JO_OBJECT` or `JO_ARRAY`) and end (`JO_CLOSE`) of objects and arrays, and in objects it sees the `JO_TAG` and then the value type of that tag. 225 | 226 | Once on the value, e.g. after a `JO_TAG` or within an array, you can get the value using functions. For literals you see if `JO_TRUE`/`JO_FALSE`/`JO_NULL` and can get values using `jo_read_int` or `jo_read_float`. 227 | 228 | However strings are more complex as the raw JSON has escaping. `jo_strlen` gives the length of a `JO_STRING` value after de-escaping. `jo_strncpy` can be used to copy and de-escape. `jo_strncmp` can be used to compare to a normal string. `jo_strdup` can be used to copy and de-escape in to malloc'd memory. These string functions can be used at a `JO_STRING` or `JO_TAG` point. There are also `jo_strncpy64` (and `32` and `16`) for decoding base64 string and copying. 229 | 230 | There are additional functions such as `jo_level` to tell you what level of nesting you are at, `jo_rewind` to start parsing again. 231 | 232 | The function `jo_copy` can copy a whole JSON object if needed. 233 | 234 | ### Creating JSON 235 | 236 | You create a new object for creating a JSON object using either `jo_create_alloc` which returns an empty JSON object ready to create, or `jo_object_alloc` which returns a JSON structure which has opened an object, i.e. the initial `{` exists and a final `}` will be added when closed. These allocate memory using `malloc` and `realloc` as needed. You can also create one using static memory using `jo_create_mem` which is passed a buffer and length. 237 | 238 | The functions to create JSON handle the commands and `{`/`}` and `[`/`]` and tags and so on for you. When done you use `jo_finish` (for static JSON) or `jo_finisha` for malloc'd JSON to get the formatted JSON string. If not sure which then `jo_isalloc` will tell you. The reason for two separate calls is that for malloc'd you have to `free()` the value but not for static, so you are expected to know which it is you are getting. 239 | 240 | You build up the JSON with functions... These functions take a *tag* which is needed if adding within an object and must be NULL when adding within an array. 241 | 242 | |Functions|Meaning| 243 | |---------|-------| 244 | |`jo_array`|Start an array (i.e. add `[`)| 245 | |`jo_object`|Start an object (i.e. add '{')| 246 | |`jo_close`|Close currect object or array (i.e. add `}` or `]`)| 247 | |`jo_json`|Add a JSON value from another JSON pointer| 248 | |`jo_int`|Add an integer| 249 | |`jo_bool`|Add a Boolean, e.g. `true` or `false`| 250 | |`jo_null`|Add a `null`| 251 | |`jo_string`|Add a string| 252 | |`jo_stringn`|Add a string with specified length, so allows nulls in the string| 253 | |`jo_stringf`|Add printf formatted string| 254 | |`jo_lit`|Add a literal, e.g. `"true"` or `"null`", or a numeric literal, etc.| 255 | |`jo_litf`|Add a literal using printf formatting, usually for adding a number of some sort.| 256 | |`jo_datetime`|Add a `time_t` as ISO datetime string| 257 | |`jo_base64`|Add a base 64 coded value, also `jo_base32` and `jo_base16`| 258 | 259 | You do not need to close everything, when you finish the construction all necessary closes are applied for you. 260 | -------------------------------------------------------------------------------- /lwmqtt.c: -------------------------------------------------------------------------------- 1 | // Light weight MQTT client 2 | // QoS 0 only, no queuing or resending (using TCP to do that for us) 3 | // Live sending to TCP for outgoing messages 4 | // Simple callback for incoming messages 5 | // Automatic reconnect 6 | static const char __attribute__((unused)) * TAG = "LWMQTT"; 7 | 8 | #include "config.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "esp_wifi.h" 16 | #include "esp_system.h" 17 | #include "nvs_flash.h" 18 | #include "esp_event.h" 19 | #include "esp_timer.h" 20 | #include "esp_log.h" 21 | #include "esp_tls.h" 22 | 23 | #include "freertos/FreeRTOS.h" 24 | #include "freertos/task.h" 25 | #include "freertos/semphr.h" 26 | 27 | #include "lwip/sockets.h" 28 | #include "lwip/dns.h" 29 | #include "lwip/netdb.h" 30 | 31 | #include "esp_tls.h" 32 | #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 33 | #include "esp_crt_bundle.h" 34 | #endif 35 | 36 | #include "lwmqtt.h" 37 | #include "esp8266_tls_compat.h" 38 | 39 | #ifdef CONFIG_REVK_MQTT_SERVER 40 | #warning MQTT server code is not complete 41 | #endif 42 | 43 | uint32_t 44 | uptime (void) 45 | { 46 | return esp_timer_get_time () / 1000000LL ? : 1; 47 | } 48 | 49 | struct lwmqtt_s 50 | { // mallocd copies 51 | lwmqtt_callback_t *callback; 52 | void *arg; 53 | char *hostname; 54 | char *tlsname; 55 | unsigned short port; 56 | unsigned short connectlen; 57 | unsigned char *connect; 58 | SemaphoreHandle_t mutex; // atomic send mutex 59 | esp_tls_t *tls; // Connection handle 60 | int sock; // Connection socket 61 | unsigned short keepalive; 62 | unsigned short seq; 63 | uint32_t ka; // Keep alive next ping 64 | uint8_t backoff; // Reconnect backoff 65 | uint8_t running:1; // Should still run 66 | uint8_t server:1; // This is a server 67 | uint8_t connected:1; // Login sent/received 68 | uint8_t failed:1; // Login sent/received 69 | uint8_t hostname_ref; // The buf below is not malloc'd 70 | uint8_t tlsname_ref; // The buf below is not malloc'd 71 | uint8_t ca_cert_ref:1; // The _buf below is not malloc'd 72 | uint8_t our_cert_ref:1; // The _buf below is not malloc'd 73 | uint8_t our_key_ref:1; // The _buf below is not malloc'd 74 | void *ca_cert_buf; // For checking server 75 | int ca_cert_bytes; 76 | void *our_cert_buf; // For auth 77 | int our_cert_bytes; 78 | void *our_key_buf; // For auth 79 | int our_key_bytes; 80 | esp_err_t (*crt_bundle_attach) (void *conf); 81 | }; 82 | 83 | #define hread(handle,buf,len) (handle->tls?esp_tls_conn_read(handle->tls,buf,len):read(handle->sock,buf,len)) 84 | 85 | static int 86 | hwrite (lwmqtt_t handle, uint8_t * buf, int len) 87 | { // Send (all of) a block 88 | int pos = 0; 89 | while (pos < len) 90 | { 91 | int sent = 92 | (handle->tls ? esp_tls_conn_write (handle->tls, buf + pos, len - pos) : write (handle->sock, buf + pos, len - pos)); 93 | if (sent <= 0) 94 | return sent; 95 | pos += sent; 96 | } 97 | return pos; 98 | } 99 | 100 | #define freez(x) do{if(x){free(x);x=NULL;}}while(0) 101 | static void * 102 | handle_free (lwmqtt_t handle) 103 | { 104 | if (handle) 105 | { 106 | freez (handle->connect); 107 | if (!handle->hostname_ref) 108 | freez (handle->hostname); 109 | if (!handle->tlsname_ref) 110 | freez (handle->tlsname); 111 | if (!handle->ca_cert_ref) 112 | freez (handle->ca_cert_buf); 113 | if (!handle->our_cert_ref) 114 | freez (handle->our_cert_buf); 115 | if (!handle->our_key_ref) 116 | freez (handle->our_key_buf); 117 | if (handle->mutex) 118 | vSemaphoreDelete (handle->mutex); 119 | freez (handle); 120 | } 121 | return NULL; 122 | } 123 | 124 | void 125 | handle_close (lwmqtt_t handle) 126 | { 127 | esp_tls_t *tls = handle->tls; 128 | int sock = handle->sock; 129 | handle->tls = NULL; 130 | handle->sock = -1; 131 | if (tls) 132 | { // TLS 133 | if (handle->server) 134 | { 135 | #ifdef CONFIG_ESP_TLS_SERVER 136 | esp_tls_server_session_delete (tls); 137 | #endif 138 | close (sock); 139 | } else 140 | esp_tls_conn_destroy (tls); 141 | } else if (sock >= 0) 142 | close (sock); 143 | } 144 | 145 | static int 146 | handle_certs (lwmqtt_t h, uint8_t ca_cert_ref, int ca_cert_bytes, void *ca_cert_buf, uint8_t our_cert_ref, int our_cert_bytes, 147 | void *our_cert_buf, uint8_t our_key_ref, int our_key_bytes, void *our_key_buf) 148 | { 149 | int fail = 0; 150 | if (ca_cert_bytes && ca_cert_buf) 151 | { 152 | h->ca_cert_bytes = ca_cert_bytes; 153 | if ((h->ca_cert_ref = ca_cert_ref)) 154 | h->ca_cert_buf = ca_cert_buf; // No malloc as reference will stay valid 155 | else if (!(h->ca_cert_buf = malloc (ca_cert_bytes))) 156 | fail++; // malloc failed 157 | else 158 | memcpy (h->ca_cert_buf, ca_cert_buf, ca_cert_bytes); 159 | } 160 | if (our_cert_bytes && our_cert_buf) 161 | { 162 | h->our_cert_bytes = our_cert_bytes; 163 | if ((h->our_cert_ref = our_cert_ref)) 164 | h->our_cert_buf = our_cert_buf; // No malloc as reference will stay valid 165 | else if (!(h->our_cert_buf = malloc (our_cert_bytes))) 166 | fail++; // malloc failed 167 | else 168 | memcpy (h->our_cert_buf, our_cert_buf, our_cert_bytes); 169 | } 170 | if (our_key_bytes && our_key_buf) 171 | { 172 | h->our_key_bytes = our_key_bytes; 173 | if ((h->our_key_ref = our_cert_ref)) 174 | h->our_key_buf = our_key_buf; // No malloc as reference will stay valid 175 | else if (!(h->our_key_buf = malloc (our_key_bytes))) 176 | fail++; // malloc failed 177 | else 178 | memcpy (h->our_key_buf, our_key_buf, our_key_bytes); 179 | } 180 | return fail; 181 | } 182 | 183 | static void client_task (void *pvParameters); 184 | #ifdef CONFIG_REVK_MQTT_SERVER 185 | static void listen_task (void *pvParameters); 186 | #endif 187 | 188 | // Create a connection 189 | lwmqtt_t 190 | lwmqtt_client (lwmqtt_client_config_t * config) 191 | { 192 | if (!config || !config->hostname) 193 | return NULL; 194 | lwmqtt_t handle = malloc (sizeof (*handle)); 195 | if (!handle) 196 | return handle_free (handle); 197 | memset (handle, 0, sizeof (*handle)); 198 | handle->sock = -1; 199 | handle->callback = config->callback; 200 | handle->arg = config->arg; 201 | handle->keepalive = config->keepalive ? : 60; 202 | if ((handle->hostname_ref = config->hostname_ref)) 203 | handle->hostname = (void *) config->hostname; 204 | else if (!(handle->hostname = strdup (config->hostname))) 205 | return handle_free (handle); 206 | handle->port = (config->port ? : (config->ca_cert_bytes || config->crt_bundle_attach) ? 8883 : 1883); 207 | if ((handle->tlsname_ref = config->tlsname_ref)) 208 | handle->tlsname = (void *) config->tlsname; 209 | else if (config->tlsname && *config->tlsname && !(handle->tlsname = strdup (config->tlsname))) 210 | return handle_free (handle); 211 | // Make connection message 212 | int mlen = 6 + 1 + 1 + 2 + strlen (config->client ? : ""); 213 | if (config->plen < 0) 214 | config->plen = strlen ((char *) config->payload ? : ""); 215 | if (config->topic) 216 | mlen += 2 + strlen (config->topic) + 2 + config->plen; 217 | if (config->username) 218 | mlen += 2 + strlen (config->username); 219 | if (config->password) 220 | mlen += 2 + strlen (config->password); 221 | if (handle_certs 222 | (handle, config->ca_cert_ref, config->ca_cert_bytes, config->ca_cert_buf, config->client_cert_ref, config->client_cert_bytes, 223 | config->client_cert_buf, config->client_key_ref, config->client_key_bytes, config->client_key_buf)) 224 | return handle_free (handle); // Nope 225 | handle->crt_bundle_attach = config->crt_bundle_attach; 226 | if (mlen >= 128 * 128) 227 | return handle_free (handle); // Nope 228 | mlen += 2; // keepalive 229 | if (mlen >= 128) 230 | mlen++; // two byte len 231 | mlen += 2; // header and one byte len 232 | if (!(handle->connect = malloc (mlen))) 233 | return handle_free (handle); 234 | unsigned char *p = handle->connect; 235 | void str (int l, const char *s) 236 | { 237 | if (l < 0) 238 | l = strlen (s ? : ""); 239 | *p++ = l >> 8; 240 | *p++ = l; 241 | if (l && s) 242 | memcpy (p, s, l); 243 | p += l; 244 | } 245 | *p++ = 0x10; // connect 246 | if (mlen > 129) 247 | { // Two byte len 248 | *p++ = (((mlen - 3) & 0x7F) | 0x80); 249 | *p++ = ((mlen - 3) >> 7); 250 | } else 251 | *p++ = mlen - 2; // 1 byte len 252 | str (4, "MQTT"); 253 | *p++ = 4; // protocol level 254 | *p = 0x02; // connect flags (clean) 255 | if (config->username) 256 | { 257 | *p |= 0x80; // Username 258 | if (config->password) 259 | *p |= 0x40; // Password 260 | } 261 | if (config->topic) 262 | { 263 | *p |= 0x04; // Will 264 | if (config->retain) 265 | *p |= 0x20; // Will retain 266 | } 267 | p++; 268 | *p++ = handle->keepalive >> 8; // keep alive 269 | *p++ = handle->keepalive; 270 | str (-1, config->client); // Client ID 271 | if (config->topic) 272 | { // Will 273 | str (-1, config->topic); // Topic 274 | str (config->plen, (void *) config->payload); // Payload 275 | } 276 | if (config->username) 277 | { 278 | str (-1, config->username); 279 | if (config->password) 280 | str (-1, config->password); 281 | } 282 | assert ((p - handle->connect) == mlen); 283 | handle->connectlen = mlen; 284 | handle->mutex = xSemaphoreCreateBinary (); 285 | xSemaphoreGive (handle->mutex); 286 | handle->running = 1; 287 | TaskHandle_t task_id = NULL; 288 | xTaskCreate (client_task, "mqtt-client", 4 * 1024, (void *) handle, 2, &task_id); 289 | return handle; 290 | } 291 | 292 | #ifdef CONFIG_REVK_MQTT_SERVER 293 | // Start a server 294 | lwmqtt_t 295 | lwmqtt_server (lwmqtt_server_config_t * config) 296 | { 297 | if (!config) 298 | return NULL; 299 | lwmqtt_t handle = malloc (sizeof (*handle)); 300 | if (!handle) 301 | return handle_free (handle); 302 | memset (handle, 0, sizeof (*handle)); 303 | handle->callback = config->callback; 304 | handle->port = (config->port ? : config->ca_cert_bytes ? 8883 : 1883); 305 | if (handle_certs 306 | (handle, config->ca_cert_ref, config->ca_cert_bytes, config->ca_cert_buf, config->server_cert_ref, config->server_cert_bytes, 307 | config->server_cert_buf, config->server_key_ref, config->server_key_bytes, config->server_key_buf)) 308 | return handle_free (handle); 309 | handle->running = 1; 310 | TaskHandle_t task_id = NULL; 311 | xTaskCreate (listen_task, "mqtt-server", 5 * 1024, (void *) handle, 2, &task_id); 312 | return handle; 313 | } 314 | #endif 315 | 316 | // End connection - actually freed later as part of task. Will do a callback when closed if was connected 317 | // NULLs the passed handle - do not use handle after this call 318 | void 319 | lwmqtt_end (lwmqtt_t * handle) 320 | { 321 | if (!handle || !*handle) 322 | return; 323 | if ((*handle)->running) 324 | { 325 | ESP_LOGD (TAG, "Ending"); 326 | (*handle)->running = 0; 327 | } 328 | *handle = NULL; 329 | } 330 | 331 | // Subscribe (return is non null error message if failed) 332 | const char * 333 | lwmqtt_subscribeub (lwmqtt_t handle, const char *topic, char unsubscribe) 334 | { 335 | const char *ret = NULL; 336 | if (!handle) 337 | ret = "No handle"; 338 | else if (handle->server) 339 | ret = "We are server"; 340 | else 341 | { 342 | int tlen = strlen (topic ? : ""); 343 | int mlen = 2 + 2 + tlen; 344 | if (!unsubscribe) 345 | mlen++; // QoS requested 346 | if (mlen >= 128 * 128) 347 | ret = "Too big"; 348 | else 349 | { 350 | if (mlen >= 128) 351 | mlen++; // two byte len 352 | mlen += 2; // header and one byte len 353 | unsigned char *buf = malloc (mlen); 354 | if (!buf) 355 | ret = "Malloc"; 356 | else 357 | { 358 | if (!xSemaphoreTake (handle->mutex, portMAX_DELAY)) 359 | ret = "Failed to get lock"; 360 | else 361 | { 362 | if (handle->sock < 0) 363 | ret = "Not connected"; 364 | else 365 | { 366 | unsigned char *p = buf; 367 | *p++ = (unsubscribe ? 0xA2 : 0x82); // subscribe/unsubscribe 368 | if (mlen > 129) 369 | { // Two byte len 370 | *p++ = (((mlen - 3) & 0x7F) | 0x80); 371 | *p++ = ((mlen - 3) >> 7); 372 | } else 373 | *p++ = mlen - 2; // 1 byte len 374 | if (!++(handle->seq)) 375 | handle->seq++; // Non zero 376 | *p++ = handle->seq >> 8; 377 | *p++ = handle->seq; 378 | *p++ = tlen >> 8; 379 | *p++ = tlen; 380 | if (tlen) 381 | memcpy (p, topic, tlen); 382 | p += tlen; 383 | if (!unsubscribe) 384 | *p++ = 0x00; // QoS requested 385 | assert ((p - buf) == mlen); 386 | if (hwrite (handle, buf, mlen) < mlen) 387 | ret = "Failed to send"; 388 | else 389 | handle->ka = uptime () + handle->keepalive; 390 | } 391 | xSemaphoreGive (handle->mutex); 392 | } 393 | freez (buf); 394 | } 395 | } 396 | } 397 | if (ret) 398 | ESP_LOGD (TAG, "Sub/unsub: %s", ret); 399 | return ret; 400 | } 401 | 402 | // Send (return is non null error message if failed) 403 | const char * 404 | lwmqtt_send_full (lwmqtt_t handle, int tlen, const char *topic, int plen, const unsigned char *payload, char retain) 405 | { 406 | const char *ret = NULL; 407 | if (!handle) 408 | ret = "No handle"; 409 | else 410 | { 411 | if (tlen < 0) 412 | tlen = strlen (topic ? : ""); 413 | if (plen < 0) 414 | plen = strlen ((char *) payload ? : ""); 415 | int mlen = 2 + tlen + plen; 416 | if (mlen >= 128 * 128) 417 | ret = "Too big"; 418 | else 419 | { 420 | if (mlen >= 128) 421 | mlen++; // two byte len 422 | mlen += 2; // header and one byte len 423 | unsigned char *buf = malloc (mlen); 424 | if (!buf) 425 | ret = "Malloc"; 426 | else 427 | { 428 | if (!xSemaphoreTake (handle->mutex, portMAX_DELAY)) 429 | ret = "Failed to get lock"; 430 | else 431 | { 432 | if (handle->sock < 0) 433 | ret = "Not connected"; 434 | else 435 | { 436 | unsigned char *p = buf; 437 | *p++ = 0x30 + (retain ? 1 : 0); // message 438 | if (mlen > 129) 439 | { // Two byte len 440 | *p++ = (((mlen - 3) & 0x7F) | 0x80); 441 | *p++ = ((mlen - 3) >> 7); 442 | } else 443 | *p++ = mlen - 2; // 1 byte len 444 | *p++ = tlen >> 8; 445 | *p++ = tlen; 446 | if (tlen) 447 | memcpy (p, topic, tlen); 448 | p += tlen; 449 | if (plen && payload) 450 | memcpy (p, payload, plen); 451 | p += plen; 452 | assert ((p - buf) == mlen); 453 | if (hwrite (handle, buf, mlen) < mlen) 454 | ret = "Failed to send"; 455 | else if (!handle->server) 456 | handle->ka = uptime () + handle->keepalive; // client KA refresh 457 | } 458 | xSemaphoreGive (handle->mutex); 459 | } 460 | freez (buf); 461 | } 462 | } 463 | } 464 | if (ret) 465 | ESP_LOGD (TAG, "Send: %s", ret); 466 | return ret; 467 | } 468 | 469 | static void 470 | lwmqtt_loop (lwmqtt_t handle) 471 | { 472 | // Handle rx messages 473 | unsigned char *buf = 0; 474 | int buflen = 0; 475 | int pos = 0; 476 | handle->ka = uptime () + (handle->server ? 5 : handle->keepalive); // Server does not know KA initially 477 | while (handle->running) 478 | { // Loop handling messages received, and timeouts 479 | int need = 0; 480 | if (pos < 2) 481 | need = 2; 482 | else if (!(buf[1] & 0x80)) 483 | need = 2 + buf[1]; // One byte len 484 | else if (pos < 3) 485 | need = 3; 486 | else if (!(buf[2] & 0x80)) 487 | need = 3 + (buf[2] << 7) + (buf[1] & 0x7F); // Two byte len 488 | else 489 | { 490 | ESP_LOGE (TAG, "Silly len %02X %02X %02X", buf[0], buf[1], buf[2]); 491 | break; 492 | } 493 | if (pos < need) 494 | { 495 | uint32_t now = uptime (); 496 | if (now >= handle->ka) 497 | { 498 | if (handle->server) 499 | break; // timeout 500 | // client, so send ping 501 | uint8_t b[] = { 0xC0, 0x00 }; // Ping 502 | xSemaphoreTake (handle->mutex, portMAX_DELAY); 503 | if (hwrite (handle, b, sizeof (b)) == sizeof (b)) 504 | handle->ka = uptime () + handle->keepalive; // Client KA refresh 505 | xSemaphoreGive (handle->mutex); 506 | } 507 | if (!handle->tls || esp_tls_get_bytes_avail (handle->tls) <= 0) 508 | { // Wait for data to arrive 509 | fd_set r; 510 | FD_ZERO (&r); 511 | FD_SET (handle->sock, &r); 512 | struct timeval to = { 1, 0 }; // Keeps us checking running but is light load at once a second 513 | int sel = select (handle->sock + 1, &r, NULL, NULL, &to); 514 | if (sel < 0) 515 | { 516 | ESP_LOGE (TAG, "Select failed"); 517 | break; 518 | } 519 | if (!FD_ISSET (handle->sock, &r)) 520 | continue; // Nothing waiting 521 | } 522 | if (need > buflen) 523 | { // Make sure we have enough space 524 | buf = realloc (buf, (buflen = need) + 1); // One more to allow extra null on end in all cases 525 | if (!buf) 526 | { 527 | ESP_LOGE (TAG, "realloc fail %d", need); 528 | break; 529 | } 530 | } 531 | int got = hread (handle, buf + pos, need - pos); 532 | if (got <= 0) 533 | { 534 | ESP_LOGD (TAG, "Connection closed"); 535 | break; // Error or close 536 | } 537 | pos += got; 538 | continue; 539 | } 540 | if (handle->server) 541 | handle->ka = uptime () + handle->keepalive * 3 / 2; // timeout for client resent on message received 542 | unsigned char *p = buf + 1, 543 | *e = buf + pos; 544 | while (p < e && (*p & 0x80)) 545 | p++; 546 | p++; 547 | if (handle->server && !handle->connected && (*buf >> 4) != 1) 548 | break; // Expect login as first message 549 | switch (*buf >> 4) 550 | { 551 | case 1: 552 | #ifdef CONFIG_REVK_MQTT_SERVER 553 | if (!handle->server) 554 | break; 555 | handle->connected = 1; 556 | ESP_LOGI (TAG, "Connected incoming %d", handle->port); 557 | // TODO incoming connect 558 | handle->keepalive = 10; // TODO get from message 559 | uint8_t b[4] = { 0x20 }; // conn ack 560 | xSemaphoreTake (handle->mutex, portMAX_DELAY); 561 | if (hwrite (handle, b, sizeof (b)) == sizeof (b) && !handle->server) 562 | handle->ka = uptime () + handle->keepalive; // KA client refresh 563 | xSemaphoreGive (handle->mutex); 564 | #endif 565 | break; 566 | case 2: // conack 567 | if (handle->server) 568 | break; 569 | ESP_LOGI (TAG, "Connected %s:%d", handle->hostname, handle->port); 570 | handle->backoff = 1; 571 | if (handle->callback) 572 | handle->callback (handle->arg, NULL, strlen (handle->hostname), (void *) handle->hostname); 573 | handle->connected = 1; 574 | break; 575 | case 3: // pub 576 | { // Topic 577 | int tlen = (p[0] << 8) + p[1]; 578 | p += 2; 579 | char *topic = (char *) p; 580 | p += tlen; 581 | unsigned short id = 0; 582 | if (*buf & 0x06) 583 | { 584 | id = (p[0] << 8) + p[1]; 585 | p += 2; 586 | } 587 | if (p > e) 588 | { 589 | ESP_LOGE (TAG, "Bad msg"); 590 | break; 591 | } 592 | if (*buf & 0x06) 593 | { // reply 594 | uint8_t b[4] = { (*buf & 0x4) ? 0x50 : 0x40, 2, id >> 8, id }; 595 | xSemaphoreTake (handle->mutex, portMAX_DELAY); 596 | if (hwrite (handle, b, sizeof (b)) == sizeof (b) && !handle->server) 597 | handle->ka = uptime () + handle->keepalive; // KA client refresh 598 | xSemaphoreGive (handle->mutex); 599 | } 600 | int plen = e - p; 601 | if (handle->callback) 602 | { 603 | if (plen && !(*buf & 0x06)) 604 | { // Move back a byte for null termination to be added without hitting payload 605 | memmove (topic - 1, topic, tlen); 606 | topic--; 607 | } 608 | topic[tlen] = 0; 609 | p[plen] = 0; 610 | handle->callback (handle->arg, topic, plen, p); 611 | } 612 | } 613 | break; 614 | case 4: // puback - no action as we don't use non QoS 0 615 | break; 616 | case 5: // pubrec - not expected as we don't use non QoS 0 617 | if (handle->server) 618 | break; 619 | { 620 | uint8_t b[4] = { 0x60, p[0], p[1] }; 621 | xSemaphoreTake (handle->mutex, portMAX_DELAY); 622 | if (hwrite (handle, b, sizeof (b)) == sizeof (b) && !handle->server) 623 | handle->ka = uptime () + handle->keepalive; // KA client refresh 624 | xSemaphoreGive (handle->mutex); 625 | } 626 | break; 627 | case 6: // pubcomp - no action as we don't use non QoS 0 628 | break; 629 | case 8: // sub 630 | #ifdef CONFIG_REVK_MQTT_SERVER 631 | if (!handle->server) 632 | break; 633 | // TODO 634 | #endif 635 | break; 636 | case 9: // suback - no action 637 | break; 638 | case 10: // unsub - no action 639 | break; 640 | case 11: // unsuback - ok 641 | if (handle->server) 642 | break; 643 | break; 644 | case 12: // ping (no action as resets ka anyway) 645 | break; 646 | case 13: // pingresp - no action - though we could use lack of reply to indicate broken connection I guess 647 | break; 648 | default: 649 | ESP_LOGE (TAG, "Unknown MQTT %02X (%d)", *buf, pos); 650 | } 651 | pos = 0; 652 | } 653 | handle->connected = 0; 654 | freez (buf); 655 | if (!handle->server && !handle->running) 656 | { // Close connection - as was clean 657 | ESP_LOGD (TAG, "Close cleanly"); 658 | uint8_t b[] = { 0xE0, 0x00 }; // Disconnect cleanly 659 | xSemaphoreTake (handle->mutex, portMAX_DELAY); 660 | hwrite (handle, b, sizeof (b)); 661 | xSemaphoreGive (handle->mutex); 662 | } 663 | handle_close (handle); 664 | if (handle->callback) 665 | handle->callback (handle->arg, NULL, 0, NULL); 666 | } 667 | 668 | static void 669 | client_task (void *pvParameters) 670 | { 671 | lwmqtt_t handle = pvParameters; 672 | if (!handle) 673 | { 674 | vTaskDelete (NULL); 675 | return; 676 | } 677 | handle->backoff = 1; 678 | while (handle->running) 679 | { // Loop connecting and trying repeatedly 680 | handle->sock = -1; 681 | // Connect 682 | ESP_LOGD (TAG, "Connecting %s:%d", handle->hostname, handle->port); 683 | // Can connect using TLS or non TLS with just sock set instead 684 | if (handle->ca_cert_bytes || handle->crt_bundle_attach) 685 | { 686 | esp_tls_t *tls = NULL; 687 | esp_tls_cfg_t cfg = { 688 | .cacert_buf = handle->ca_cert_buf, 689 | .cacert_bytes = handle->ca_cert_bytes, 690 | .common_name = handle->tlsname, 691 | .clientcert_buf = handle->our_cert_buf, 692 | .clientcert_bytes = handle->our_cert_bytes, 693 | .clientkey_buf = handle->our_key_buf, 694 | .clientkey_bytes = handle->our_key_bytes, 695 | .crt_bundle_attach = handle->crt_bundle_attach, 696 | }; 697 | tls = esp_tls_init (); 698 | if (esp_tls_conn_new_sync (handle->hostname, strlen (handle->hostname), handle->port, &cfg, tls) != 1) 699 | { 700 | ESP_LOGE (TAG, "Could not TLS connect to %s:%d", handle->hostname, handle->port); 701 | free (tls); 702 | } else 703 | { 704 | handle->tls = tls; 705 | esp_tls_get_conn_sockfd (handle->tls, &handle->sock); 706 | } 707 | } else 708 | { // Non TLS 709 | // This is annoying as it should just pick IPv6 as preferred, but it sort of works 710 | // May be better as a generic connect, and we are also rather assuming TLS ^ will connect IPv6 is available 711 | int tryconnect (int fam) 712 | { 713 | if (handle->sock >= 0) 714 | return 0; // connected 715 | struct addrinfo base = { ai_family: fam, ai_socktype:SOCK_STREAM }; 716 | struct addrinfo *a = 0, 717 | *p = NULL; 718 | char sport[6]; 719 | snprintf (sport, sizeof (sport), "%d", handle->port); 720 | if (getaddrinfo (handle->hostname, sport, &base, &a) || !a) 721 | return 0; 722 | for (p = a; p; p = p->ai_next) 723 | { 724 | handle->sock = socket (p->ai_family, p->ai_socktype, p->ai_protocol); 725 | if (handle->sock < 0) 726 | continue; 727 | if (connect (handle->sock, p->ai_addr, p->ai_addrlen)) 728 | { 729 | close (handle->sock); 730 | handle->sock = -1; 731 | continue; 732 | } 733 | break; 734 | } 735 | freeaddrinfo (a); 736 | return 1; 737 | } 738 | if (!tryconnect (AF_INET6) || uptime () > 20) // Gives IPv6 a chance to actually get started if there is IPv6 DNS for this. 739 | tryconnect (AF_INET); 740 | if (handle->sock < 0) 741 | ESP_LOGD (TAG, "Could not connect to %s:%d", handle->hostname, handle->port); 742 | } 743 | if (handle->sock < 0) 744 | { // Failed before we even start 745 | handle->failed = 1; 746 | if (handle->callback) 747 | handle->callback (handle->arg, NULL, 0, NULL); 748 | } else 749 | { 750 | handle->failed = 0; 751 | hwrite (handle, handle->connect, handle->connectlen); 752 | lwmqtt_loop (handle); 753 | } 754 | if (!handle->running) 755 | break; // client was stopped 756 | if (handle->backoff < 128) 757 | handle->backoff *= 2; 758 | else 759 | handle->backoff = 255; 760 | // On ESP32 uint32_t, returned by this func, appears to be long, while on ESP8266 it's a pure unsigned int 761 | // The easiest and least ugly way to get around is to cast to long explicitly 762 | ESP_LOGI (TAG, "Waiting %d (mem:%ld)", handle->backoff / 5, (long)esp_get_free_heap_size ()); 763 | sleep (handle->backoff < 5 ? 1 : handle->backoff / 5); 764 | } 765 | handle_free (handle); 766 | vTaskDelete (NULL); 767 | } 768 | 769 | #ifdef CONFIG_REVK_MQTT_SERVER 770 | static void 771 | server_task (void *pvParameters) 772 | { 773 | lwmqtt_t handle = pvParameters; 774 | lwmqtt_loop (handle); 775 | handle_free (handle); 776 | vTaskDelete (NULL); 777 | } 778 | 779 | static void 780 | listen_task (void *pvParameters) 781 | { 782 | lwmqtt_t handle = pvParameters; 783 | if (handle) 784 | { 785 | struct sockaddr_in dst = { // Yep IPv4 local 786 | .sin_addr.s_addr = htonl (INADDR_ANY), 787 | .sin_family = AF_INET, 788 | .sin_port = htons (handle->port), 789 | }; 790 | int sock = socket (AF_INET, SOCK_STREAM, IPPROTO_IP); 791 | if (sock >= 0) 792 | { 793 | if (bind (sock, (void *) &dst, sizeof (dst)) < 0 || listen (sock, 1) < 0) 794 | close (sock); 795 | else 796 | { 797 | ESP_LOGD (TAG, "Listening for MQTT on %d", handle->port); 798 | while (handle->running) 799 | { // Loop connecting and trying repeatedly 800 | struct sockaddr_in addr; 801 | socklen_t addrlen = sizeof (addr); 802 | int s = accept (sock, (void *) &addr, &addrlen); 803 | if (s < 0) 804 | break; 805 | ESP_LOGD (TAG, "Connect on MQTT %d", handle->port); 806 | lwmqtt_t h = malloc (sizeof (*h)); 807 | if (!h) 808 | break; 809 | memset (h, 0, sizeof (*h)); 810 | h->port = handle->port; // Only for debugging 811 | h->callback = handle->callback; 812 | h->arg = h; 813 | h->mutex = xSemaphoreCreateBinary (); 814 | h->server = 1; 815 | h->sock = s; 816 | h->running = 1; 817 | if (handle->ca_cert_bytes) 818 | { // TLS 819 | #ifdef CONFIG_ESP_TLS_SERVER 820 | esp_tls_cfg_server_t cfg = { 821 | .cacert_buf = handle->ca_cert_buf, 822 | .cacert_bytes = handle->ca_cert_bytes, 823 | .servercert_buf = handle->our_cert_buf, 824 | .servercert_bytes = handle->our_cert_bytes, 825 | .serverkey_buf = handle->our_key_buf, 826 | .serverkey_bytes = handle->our_key_bytes, 827 | }; 828 | h->tls = esp_tls_init (); 829 | esp_err_t e = 0; 830 | if (!h->tls || (e = esp_tls_server_session_create (&cfg, s, h->tls))) 831 | { 832 | ESP_LOGE (TAG, "TLS server failed %s", h->tls ? esp_err_to_name (e) : "No TLS"); 833 | h->running = 0; 834 | } else 835 | { // Check client name? Do login callback 836 | // TODO server client name check 837 | } 838 | #else 839 | ESP_LOGE (TAG, "Not built for TLS server"); 840 | h->running = 0; 841 | #endif 842 | } 843 | if (h->running) 844 | { 845 | TaskHandle_t task_id = NULL; 846 | xTaskCreate (server_task, "mqtt-listen", 5 * 1024, (void *) h, 2, &task_id); 847 | } else 848 | { // Close 849 | ESP_LOGI (TAG, "MQTT aborted"); 850 | #ifdef CONFIG_ESP_TLS_SERVER 851 | if (h->tls) 852 | esp_tls_server_session_delete (h->tls); 853 | #endif 854 | close (h->sock); 855 | } 856 | 857 | } 858 | } 859 | } 860 | handle_free (handle); 861 | } 862 | vTaskDelete (NULL); 863 | } 864 | #endif 865 | 866 | // Simple send - non retained no wait topic ends on space then payload 867 | const char * 868 | lwmqtt_send_str (lwmqtt_t handle, const char *msg) 869 | { 870 | if (!handle || !*msg) 871 | return NULL; 872 | const char *p; 873 | for (p = msg; *p && *p != '\t'; p++); 874 | if (!*p) 875 | for (p = msg; *p && *p != ' '; p++); 876 | int tlen = p - msg; 877 | if (*p) 878 | p++; 879 | return lwmqtt_send_full (handle, tlen, msg, strlen (p), (void *) p, 0); 880 | } 881 | 882 | int 883 | lwmqtt_connected (lwmqtt_t handle) 884 | { // Confirm connected 885 | return handle && handle->connected; 886 | } 887 | 888 | int 889 | lwmqtt_failed (lwmqtt_t handle) 890 | { // Confirm failed 891 | return handle && handle->failed; 892 | } 893 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /jo.c: -------------------------------------------------------------------------------- 1 | // Lightweight JSON syntax management tool kit 2 | // This toolkit works solely at a syntax level, and does not all management of whole JSON object hierarchy 3 | 4 | #include "jo.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "esp_log.h" 14 | 15 | #ifndef JO_MAX 16 | #define JO_MAX 64 17 | #endif 18 | 19 | struct jo_s 20 | { // cursor to JSON object 21 | char *buf; // Start of JSON string 22 | const char *err; // If in error state 23 | size_t ptr; // Pointer in to buf 24 | size_t len; // Max space for buf 25 | uint8_t parse:1; // This is parsing, not generating 26 | uint8_t alloc:1; // buf is malloced space 27 | uint8_t comma:1; // Set if comma needed / expected 28 | uint8_t tagok:1; // We have skipped an expected tag already in parsing 29 | uint8_t null:1; // We have a null termination 30 | uint8_t level; // Current level 31 | uint8_t o[(JO_MAX + 7) / 8]; // Bit set at each level if level is object, else it is array 32 | }; 33 | 34 | const char JO_BASE64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 35 | const char JO_BASE32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 36 | const char JO_BASE16[] = "0123456789ABCDEF"; 37 | 38 | // Note escaping / is optional but done always to avoid issues 39 | #define escapes \ 40 | esc ('"', '"') \ 41 | esc ('\\', '\\') \ 42 | esc ('/', '/') \ 43 | esc ('b', '\b') \ 44 | esc ('f', '\f') \ 45 | esc ('n', '\n') \ 46 | esc ('r', '\r') \ 47 | esc ('t', '\t') \ 48 | 49 | static jo_t 50 | jo_new (void) 51 | { // Create a jo_t 52 | jo_t j = malloc (sizeof (*j)); 53 | if (!j) 54 | return j; // Malloc fail 55 | memset (j, 0, sizeof (*j)); 56 | return j; 57 | } 58 | 59 | static void * 60 | saferealloc (void *m, size_t len) 61 | { 62 | void *n = realloc (m, len); 63 | if (m && !n) 64 | free (m); // Failed, clear existing 65 | return n; 66 | } 67 | 68 | static inline void 69 | jo_store (jo_t j, uint8_t c) 70 | { // Write out byte 71 | if (!j || j->err) 72 | return; 73 | if (j->parse) 74 | { 75 | j->err = "Writing to read only JSON"; 76 | return; 77 | } 78 | if (j->ptr >= j->len && (!j->alloc || !(j->buf = saferealloc (j->buf, j->len += 100)))) 79 | { 80 | j->err = (j->alloc ? "Cannot allocate space" : "Out of space"); 81 | return; 82 | } 83 | j->buf[j->ptr] = c; 84 | j->null = (c ? 0 : 1); 85 | } 86 | 87 | static inline void 88 | jo_write (jo_t j, uint8_t c) 89 | { // Write a byte and advance 90 | jo_store (j, c); 91 | if (j && !j->err) 92 | j->ptr++; 93 | } 94 | 95 | jo_t 96 | jo_pad (jo_t * jp, int n) 97 | { // Ensure padding available 98 | if (!jp) 99 | return NULL; 100 | jo_t j = *jp; 101 | if (!j->parse) 102 | n += j->level + 1; // Allow space to close and null 103 | if (!j->alloc 104 | || ((j->parse || j->ptr + n > j->len) && !(j->buf = saferealloc (j->buf, j->len = (j->parse ? j->len : j->ptr) + n)))) 105 | { // Cannot pad 106 | jo_free (jp); 107 | return NULL; 108 | } 109 | return j; 110 | } 111 | 112 | static inline int 113 | jo_peek (jo_t j) 114 | { // Peek next raw byte (-1 for end/fail) 115 | if (!j || j->err || !j->parse || j->ptr >= j->len) 116 | return -1; 117 | return j->buf[j->ptr]; 118 | } 119 | 120 | static inline int 121 | jo_read (jo_t j) 122 | { // Read and advance next raw byte (-1 for end/fail) 123 | if (!j || j->err || !j->parse || j->ptr >= j->len) 124 | return -1; 125 | return j->buf[j->ptr++]; 126 | } 127 | 128 | static int 129 | jo_read_str (jo_t j) 130 | { // Read next (UTF-8) within a string, so decode escaping (-1 for end/fail) 131 | if (!j || !j->parse || j->err) 132 | return -1; 133 | int bad (const char *e) 134 | { // Fail 135 | if (!j->err) 136 | j->err = e; 137 | return -1; 138 | } 139 | int utf8 (void) 140 | { // next character 141 | if (jo_peek (j) == '"') 142 | return -1; // Clean end of string 143 | int c = jo_read (j), 144 | q = 0; 145 | if (c < 0) 146 | return c; 147 | if (c >= 0xF7) 148 | return bad ("Bad UTF-8"); 149 | if (c >= 0xF0) 150 | { // Note could check for F0 and next byte as bad 151 | c &= 0x07; 152 | q = 3; 153 | } else if (c >= 0xE0) 154 | { // Note could check for E0 and next byte as bad 155 | c &= 0x0F; 156 | q = 2; 157 | } else if (c >= 0xC0) 158 | { 159 | if (c < 0xC2) 160 | return bad ("Bad UTF-8"); 161 | c &= 0x1F; 162 | q = 1; 163 | } else if (c >= 0x80) 164 | return bad ("Bat UTF-8"); 165 | else if (c == '\\') 166 | { // Escape 167 | c = jo_read (j); 168 | if (c == 'u') 169 | { // Hex 170 | c = 0; 171 | for (int q = 4; q; q--) 172 | { 173 | int u = jo_read (j); 174 | if (u >= '0' && u <= '9') 175 | c = (c << 4) + (u & 0xF); 176 | else if ((u >= 'A' && u <= 'F') || (u >= 'a' && u <= 'f')) 177 | c = (c << 4) + 9 + (u & 0xF); 178 | else 179 | return bad ("bad hex escape"); 180 | } 181 | } 182 | #define esc(a,b) else if(c==a)c=b; 183 | escapes 184 | #undef esc 185 | else 186 | return bad ("Bad escape"); 187 | } 188 | while (q--) 189 | { // More UTF-8 characters 190 | int u = jo_read (j); 191 | if (u < 0x80 || u >= 0xC0) 192 | return bad ("Bad UTF-8"); 193 | c = (c << 6) + (u & 0x3F); 194 | } 195 | return c; 196 | } 197 | int c = utf8 (); 198 | if (c >= 0xD800 && c <= 0xDBFF) 199 | { // UTF16 Surrogates 200 | int c2 = utf8 (); 201 | if (c2 < 0xDC00 || c2 > 0xDFFF) 202 | return bad ("Bad UTF-16, second part invalid"); 203 | c = ((c & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000; 204 | } 205 | return c; 206 | } 207 | 208 | // Setting up 209 | 210 | jo_t 211 | jo_parse_str (const char *buf) 212 | { // Start parsing a null terminated JSON object string 213 | if (!buf) 214 | return NULL; 215 | jo_t j = jo_parse_mem (buf, strlen (buf) + 1); // Include the null so we set null tag 216 | return j; 217 | } 218 | 219 | jo_t 220 | jo_parse_mem (const void *buf, size_t len) 221 | { // Start parsing a JSON string in memory - does not need a null 222 | if (!buf) 223 | return NULL; // No buf 224 | jo_t j = jo_new (); 225 | if (!j) 226 | return j; // malloc fail 227 | j->parse = 1; 228 | j->buf = (char *) buf; 229 | if (len && !j->buf[len - 1]) 230 | { // We provided a null, nice 231 | len--; 232 | j->null = 1; 233 | } 234 | j->len = len; 235 | return j; 236 | } 237 | 238 | jo_t 239 | jo_create_mem (void *buf, size_t len) 240 | { // Start creating JSON in memory at buf, max space len. 241 | jo_t j = jo_new (); 242 | if (!j) 243 | return j; // malloc fail 244 | j->buf = buf; 245 | j->len = len; 246 | return j; 247 | } 248 | 249 | jo_t 250 | jo_create_alloc (void) 251 | { // Start creating JSON in memory, allocating space as needed. 252 | jo_t j = jo_new (); 253 | if (!j) 254 | return j; // malloc fail 255 | j->alloc = 1; 256 | return j; 257 | } 258 | 259 | jo_t 260 | jo_object_alloc (void) 261 | { // Common 262 | jo_t j = jo_create_alloc (); 263 | jo_object (j, NULL); 264 | return j; 265 | } 266 | 267 | static jo_t 268 | jo_link (jo_t j) 269 | { // Internal use: Copy control without copying the allocated content - copied object has to stay valid 270 | if (!j || j->err) 271 | return NULL; // No j 272 | jo_t n = jo_new (); 273 | if (!n) 274 | return n; // malloc fail 275 | memcpy (n, j, sizeof (*j)); 276 | n->alloc = 0; 277 | return n; 278 | } 279 | 280 | jo_t 281 | jo_copy (jo_t j) 282 | { // Copy object - copies the object, and if allocating memory, makes copy of the allocated memory too 283 | if (!j || j->err) 284 | return NULL; // No j 285 | jo_t n = jo_new (); 286 | if (!n) 287 | return n; // malloc fail 288 | memcpy (n, j, sizeof (*j)); 289 | if (j->alloc && j->buf) 290 | { 291 | j->null = 0; 292 | n->buf = malloc (j->parse ? j->len + 1 : j->len ? : 1); 293 | if (!n->buf) 294 | { 295 | jo_free (&n); 296 | return NULL; // malloc 297 | } 298 | if (j->parse) 299 | { // Ensure null 300 | n->buf[j->len] = 0; 301 | j->null = 1; 302 | } 303 | memcpy (n->buf, j->buf, j->parse ? j->len : j->ptr); 304 | } 305 | return n; 306 | } 307 | 308 | const char * 309 | jo_rewind (jo_t j) 310 | { // Move to start for parsing. If was writing, closed and set up to read instead. Clears error is reading. 311 | if (!j) 312 | return NULL; 313 | if (!j->parse) 314 | { // Finish, if possible 315 | while (j->level) 316 | jo_close (j); 317 | jo_store (j, 0); 318 | if (j->err) 319 | return NULL; 320 | j->len = j->ptr; 321 | j->parse = 1; 322 | } 323 | j->err = NULL; 324 | j->ptr = 0; 325 | j->comma = 0; 326 | j->level = 0; 327 | j->tagok = 0; 328 | if (!j->null) 329 | return NULL; 330 | return j->buf; 331 | } 332 | 333 | int 334 | jo_level (jo_t j) 335 | { // Current level, 0 being the top level 336 | if (!j) 337 | return -1; 338 | return j->level; 339 | } 340 | 341 | const char * 342 | jo_error (jo_t j, int *pos) 343 | { // Return NULL if no error, else returns an error string. 344 | if (pos) 345 | *pos = (j ? j->ptr : -1); 346 | if (j && !j->err && !j->parse && !j->alloc && j->ptr + j->level + 1 > j->len) 347 | return "No space to finish JSON"; 348 | if (!j) 349 | return "No j"; 350 | return j->err; 351 | } 352 | 353 | void 354 | jo_free (jo_t * jp) 355 | { // Free j 356 | if (!jp) 357 | return; 358 | jo_t j = *jp; 359 | if (!j) 360 | return; 361 | *jp = NULL; 362 | if (j->alloc && j->buf) 363 | free (j->buf); 364 | free (j); 365 | } 366 | 367 | int 368 | jo_isalloc (jo_t j) 369 | { 370 | if (j && j->alloc) 371 | return 1; 372 | return 0; 373 | } 374 | 375 | char * 376 | jo_finish (jo_t * jp) 377 | { // Finish creating static JSON, return start of static JSON if no error. Frees j. It is an error to use with jo_create_alloc 378 | if (!jp) 379 | return NULL; 380 | jo_t j = *jp; 381 | if (!j) 382 | return NULL; 383 | *jp = NULL; 384 | if (!j->parse) 385 | { 386 | while (j->level) 387 | jo_close (j); 388 | jo_store (j, 0); 389 | } 390 | char *res = j->buf; 391 | if (j->err || j->alloc) 392 | res = NULL; 393 | if (!res && j->alloc && j->buf) 394 | free (j->buf); 395 | free (j); 396 | return res; 397 | } 398 | 399 | char * 400 | jo_finisha (jo_t * jp) 401 | { // Finish creating allocated JSON, returns start of alloc'd memory if no error. 402 | // Frees j. If NULL returned then any allocated space also freed 403 | // It is an error to use with non jo_create_alloc 404 | if (!jp) 405 | return NULL; 406 | jo_t j = *jp; 407 | if (!j) 408 | return NULL; 409 | *jp = NULL; 410 | if (!j->parse) 411 | { 412 | while (j->level) 413 | jo_close (j); 414 | jo_store (j, 0); 415 | } 416 | char *res = j->buf; 417 | if (j->err || !j->alloc) 418 | res = NULL; 419 | if (!res && j->alloc && j->buf) 420 | free (j->buf); 421 | free (j); 422 | return res; 423 | } 424 | 425 | int 426 | jo_len (jo_t j) 427 | { // Return length, including any closing 428 | if (!j) 429 | return -1; 430 | if (j->parse) 431 | return j->len; 432 | return j->ptr + j->level; 433 | } 434 | 435 | // Creating 436 | // Note that tag is required if in an object and must be null if not 437 | 438 | static void 439 | jo_write_char (jo_t j, uint32_t c) 440 | { 441 | 442 | #define esc(a,b) if(c==b){jo_write(j,'\\');jo_write(j,a);return;} 443 | escapes 444 | #undef esc 445 | if (c < ' ' || c >= 0xFF) 446 | { 447 | jo_write (j, '\\'); 448 | jo_write (j, 'u'); 449 | jo_write (j, JO_BASE16[(c >> 12) & 0xF]); 450 | jo_write (j, JO_BASE16[(c >> 8) & 0xF]); 451 | jo_write (j, JO_BASE16[(c >> 4) & 0xF]); 452 | jo_write (j, JO_BASE16[c & 0xF]); 453 | return; 454 | } 455 | jo_write (j, c); 456 | } 457 | 458 | 459 | static void 460 | jo_write_str (jo_t j, const char *s, ssize_t len) 461 | { 462 | jo_write (j, '"'); 463 | if (len < 0) 464 | len = strlen (s); 465 | while (len--) 466 | jo_write_char (j, *s++); 467 | jo_write (j, '"'); 468 | } 469 | 470 | static const char * 471 | jo_write_check (jo_t j, const char *tag) 472 | { // Check if we are able to write, and write the tag 473 | if (!j) 474 | return "No j"; 475 | if (j->err) 476 | return j->err; 477 | if (j->parse) 478 | return (j->err = "Writing to parse"); 479 | if (j->level && (j->o[(j->level - 1) / 8] & (1 << ((j->level - 1) & 7)))) 480 | { 481 | if (!tag) 482 | return (j->err = "missing tag in object"); 483 | } else if (tag) 484 | return (j->err = "tag in non object"); 485 | if (!j->level && j->ptr) 486 | return (j->err = "second value at top level"); 487 | if (j->comma) 488 | jo_write (j, ','); 489 | j->comma = 1; 490 | if (tag) 491 | { 492 | jo_write_str (j, tag, -1); 493 | jo_write (j, ':'); 494 | } 495 | return j->err; 496 | } 497 | 498 | void 499 | jo_json (jo_t j, const char *tag, jo_t json) 500 | { // Add JSON, if NULL tag, and in object, and JSON is object, add its content 501 | if (!json) 502 | { 503 | jo_null (j, tag); 504 | return; 505 | } 506 | if (!json->parse) 507 | { // Close the json 508 | while (json->level) 509 | jo_close (json); 510 | jo_store (json, 0); 511 | } 512 | char *p = json->buf, 513 | *e = p + json->ptr; 514 | if (json->parse) 515 | e = p + json->len; 516 | if (!tag && p && *p == '{' && j->level && (j->o[(j->level - 1) / 8] & (1 << ((j->level - 1) & 7)))) 517 | { // Special case of adding in-line object content 518 | p++; 519 | e--; 520 | if (j->comma) 521 | jo_write (j, ','); 522 | j->comma = 1; 523 | } else 524 | { // Normal add as value (possibly tagged) 525 | if (jo_write_check (j, tag)) 526 | return; 527 | } 528 | while (p < e) 529 | jo_write (j, *p++); 530 | } 531 | 532 | void 533 | jo_lit (jo_t j, const char *tag, const char *lit) 534 | { // Add literal 535 | if (jo_write_check (j, tag)) 536 | return; 537 | while (*lit) 538 | jo_write (j, *lit++); 539 | } 540 | 541 | void 542 | jo_array (jo_t j, const char *tag) 543 | { // Start an array 544 | if (jo_write_check (j, tag)) 545 | return; 546 | if (j->level >= JO_MAX) 547 | { 548 | j->err = "JSON too deep"; 549 | return; 550 | } 551 | j->o[j->level / 8] &= ~(1 << (j->level & 7)); 552 | j->level++; 553 | j->comma = 0; 554 | jo_write (j, '['); 555 | } 556 | 557 | void 558 | jo_object (jo_t j, const char *tag) 559 | { // Start an object 560 | if (jo_write_check (j, tag)) 561 | return; 562 | if (j->level >= JO_MAX) 563 | { 564 | if (!j->err) 565 | j->err = "JSON too deep"; 566 | return; 567 | } 568 | j->o[j->level / 8] |= (1 << (j->level & 7)); 569 | j->level++; 570 | j->comma = 0; 571 | jo_write (j, '{'); 572 | } 573 | 574 | void 575 | jo_close (jo_t j) 576 | { // Close current array or object 577 | if (!j->level) 578 | { 579 | if (!j->err) 580 | j->err = "JSON too many closes"; 581 | return; 582 | } 583 | j->level--; 584 | j->comma = 1; 585 | jo_write (j, (j->o[j->level / 8] & (1 << (j->level & 7))) ? '}' : ']'); 586 | } 587 | 588 | void 589 | jo_stringn (jo_t j, const char *tag, const char *string, ssize_t len) 590 | { // Add a string 591 | if (!string) 592 | { 593 | jo_null (j, tag); 594 | return; 595 | } 596 | if (jo_write_check (j, tag)) 597 | return; 598 | jo_write_str (j, string, len); 599 | } 600 | 601 | void 602 | jo_stringf (jo_t j, const char *tag, const char *format, ...) 603 | { // Add a string (formatted) 604 | if (jo_write_check (j, tag)) 605 | return; 606 | char *v = NULL; 607 | va_list ap; 608 | va_start (ap, format); 609 | ssize_t len = vasprintf (&v, format, ap); 610 | va_end (ap); 611 | if (!v) 612 | { 613 | j->err = "malloc for printf"; 614 | return; 615 | } 616 | jo_write_str (j, v, len); 617 | free (v); 618 | } 619 | 620 | void 621 | jo_litf (jo_t j, const char *tag, const char *format, ...) 622 | { // Add a literal (formatted) 623 | char temp[100]; 624 | va_list ap; 625 | va_start (ap, format); 626 | vsnprintf (temp, sizeof (temp), format, ap); 627 | va_end (ap); 628 | jo_lit (j, tag, temp); 629 | } 630 | 631 | void 632 | jo_baseN (jo_t j, const char *tag, const void *src, size_t slen, uint8_t bits, const char *alphabet) 633 | { // base 16/32/64 binary to string 634 | if (jo_write_check (j, tag)) 635 | return; 636 | jo_write (j, '"'); 637 | unsigned int i = 0, 638 | b = 0, 639 | v = 0; 640 | while (i < slen) 641 | { 642 | b += 8; 643 | v = (v << 8) + ((uint8_t *) src)[i++]; 644 | while (b >= bits) 645 | { 646 | b -= bits; 647 | jo_write (j, alphabet[(v >> b) & ((1 << bits) - 1)]); 648 | } 649 | } 650 | if (b) 651 | { // final bits 652 | b += 8; 653 | v <<= 8; 654 | b -= bits; 655 | jo_write (j, alphabet[(v >> b) & ((1 << bits) - 1)]); 656 | while (b) 657 | { // padding 658 | while (b >= bits) 659 | { 660 | b -= bits; 661 | jo_write (j, '='); 662 | } 663 | if (b) 664 | b += 8; 665 | } 666 | } 667 | jo_write (j, '"'); 668 | } 669 | 670 | void 671 | jo_datetime (jo_t j, const char *tag, time_t t) 672 | { 673 | if (t < 1000000000) 674 | jo_null (j, tag); 675 | else 676 | { 677 | struct tm tm; 678 | gmtime_r (&t, &tm); 679 | jo_stringf (j, tag, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, 680 | tm.tm_sec); 681 | } 682 | } 683 | 684 | ssize_t 685 | jo_strncpyd (jo_t j, void *dstv, size_t dlen, uint8_t bits, const char *alphabet) 686 | { // Base16/32/64 string to binary 687 | uint8_t *dst = dstv; 688 | if (!j || j->err || !j->parse) 689 | return -1; 690 | if (jo_peek (j) != '"') 691 | return -1; // Not a string 692 | jo_t p = jo_link (j); 693 | jo_read (p); // skip " 694 | int b = 0, 695 | v = 0, 696 | c, 697 | ptr = 0; 698 | while ((c = jo_read_str (p)) >= 0 && c != '=') 699 | { 700 | char *q = strchr (alphabet, bits < 6 ? toupper (c) : c); 701 | if (!c || !q) 702 | { // Bad character 703 | if (!c || isspace (c) || c == '\r' || c == '\n') 704 | continue; // space 705 | jo_free (&p); 706 | return -1; // Bad 707 | } 708 | v = (v << bits) + (q - alphabet); 709 | b += bits; 710 | if (b >= 8) 711 | { // output byte 712 | b -= 8; 713 | if (dst && ptr < dlen) 714 | dst[ptr] = (v >> b); 715 | ptr++; 716 | } 717 | } 718 | jo_free (&p); 719 | return ptr; 720 | } 721 | 722 | char * 723 | jo_strdup (jo_t j) 724 | { // Malloc copy of string 725 | ssize_t len = jo_strlen (j); 726 | if (len < 0) 727 | return NULL; 728 | char *str = malloc (len + 1); 729 | jo_strncpy (j, str, len + 1); 730 | return str; 731 | } 732 | 733 | void 734 | jo_int (jo_t j, const char *tag, int64_t val) 735 | { // Add an integer 736 | jo_litf (j, tag, "%lld", val); 737 | } 738 | 739 | void 740 | jo_bool (jo_t j, const char *tag, int val) 741 | { // Add a bool (true if non zero passed) 742 | jo_lit (j, tag, val ? "true" : "false"); 743 | } 744 | 745 | void 746 | jo_null (jo_t j, const char *tag) 747 | { // Add a null 748 | jo_lit (j, tag, "null"); 749 | } 750 | 751 | // Parsing 752 | 753 | static inline int 754 | jo_ws (jo_t j) 755 | { // Skip white space, and return peek at next 756 | int c = jo_peek (j); 757 | while (c == ' ' || c == '\t' || c == '\r' || c == '\n') 758 | { 759 | jo_read (j); 760 | c = jo_peek (j); 761 | } 762 | return c; 763 | } 764 | 765 | jo_type_t 766 | jo_here (jo_t j) 767 | { // Return what type of thing we are at - we are always at a value of some sort, which has a tag if we are in an object 768 | if (!j || j->err || !j->parse) 769 | return JO_END; 770 | int c = jo_ws (j); 771 | if (c < 0) 772 | return JO_END; 773 | if (c == '}' || c == ']') 774 | { 775 | if (j->tagok) 776 | { 777 | j->err = "Missing value"; 778 | return JO_END; 779 | } 780 | if (!j->level) 781 | { 782 | j->err = "Too many closed"; 783 | return JO_END; 784 | } 785 | if (c != ((j->o[(j->level - 1) / 8] & (1 << ((j->level - 1) & 7))) ? '}' : ']')) 786 | { 787 | j->err = "Mismatched close"; 788 | return JO_END; 789 | } 790 | return JO_CLOSE; 791 | } 792 | if (j->comma) 793 | { 794 | if (!j->level) 795 | { 796 | j->err = "Extra value at top level"; 797 | return JO_END; 798 | } 799 | if (c != ',') 800 | { 801 | j->err = "Missing comma"; 802 | return JO_END; 803 | } 804 | jo_read (j); 805 | c = jo_ws (j); 806 | j->comma = 0; // Comma consumed 807 | } 808 | // These are a guess of type - a robust check is done by jo_next 809 | if (!j->tagok && j->level && (j->o[(j->level - 1) / 8] & (1 << ((j->level - 1) & 7)))) 810 | { // We should be at a tag 811 | if (c != '"') 812 | { 813 | j->err = "Missing tag"; 814 | return JO_END; 815 | } 816 | return JO_TAG; 817 | } 818 | if (c == '"') 819 | return JO_STRING; 820 | if (c == '{') 821 | return JO_OBJECT; 822 | if (c == '[') 823 | return JO_ARRAY; 824 | if (c == 'n') 825 | return JO_NULL; 826 | if (c == 't') 827 | return JO_TRUE; 828 | if (c == 'f') 829 | return JO_FALSE; 830 | if (c == '-' || (c >= '0' && c <= '9')) 831 | return JO_NUMBER; 832 | j->err = "Bad JSON"; 833 | return JO_END; 834 | } 835 | 836 | jo_type_t 837 | jo_next (jo_t j) 838 | { // Move to next value, this validates what we are skipping. A tag and its value are separate 839 | int c; 840 | if (!j || !j->parse || j->err) 841 | return JO_END; 842 | switch (jo_here (j)) 843 | { 844 | case JO_END: // End or error 845 | break; 846 | case JO_TAG: // Tag 847 | jo_read (j); // " 848 | while (jo_read_str (j) >= 0); 849 | if (!j->err && jo_read (j) != '"') 850 | j->err = "Missing closing quote on tag"; 851 | jo_ws (j); 852 | if (!j->err && jo_read (j) != ':') 853 | j->err = "Missing colon after tag"; 854 | j->tagok = 1; // We have skipped tag 855 | break; 856 | case JO_OBJECT: 857 | jo_read (j); // { 858 | if (j->level >= JO_MAX) 859 | { 860 | j->err = "JSON too deep"; 861 | break; 862 | } 863 | j->o[j->level / 8] |= (1 << (j->level & 7)); 864 | j->level++; 865 | j->comma = 0; 866 | j->tagok = 0; 867 | break; 868 | case JO_ARRAY: 869 | jo_read (j); // ] 870 | if (j->level >= JO_MAX) 871 | { 872 | j->err = "JSON too deep"; 873 | break; 874 | } 875 | j->o[j->level / 8] &= ~(1 << (j->level & 7)); 876 | j->level++; 877 | j->comma = 0; 878 | j->tagok = 0; 879 | break; 880 | case JO_CLOSE: 881 | jo_read (j); // }/] 882 | j->level--; // Was checked by jo_here() 883 | j->comma = 1; 884 | j->tagok = 0; 885 | break; 886 | case JO_STRING: 887 | jo_read (j); // " 888 | while (jo_read_str (j) >= 0); 889 | if (!j->err && jo_read (j) != '"') 890 | j->err = "Missing closing quote on string"; 891 | j->comma = 1; 892 | j->tagok = 0; 893 | break; 894 | case JO_NUMBER: 895 | if (jo_peek (j) == '-') 896 | jo_read (j); // minus 897 | if ((c = jo_peek (j)) == '0') 898 | jo_read (j); // just zero 899 | else if (c >= '1' && c <= '9') 900 | while ((c = jo_peek (j)) >= '0' && c <= '9') 901 | jo_read (j); // int 902 | if (jo_peek (j) == '.') 903 | { // real 904 | jo_read (j); 905 | if ((c = jo_peek (j)) < '0' || c > '9') 906 | j->err = "Bad real, must be digits after decimal point"; 907 | else 908 | while ((c = jo_peek (j)) >= '0' && c <= '9') 909 | jo_read (j); // frac 910 | } 911 | if ((c = jo_peek (j)) == 'e' || c == 'E') 912 | { // exp 913 | jo_read (j); 914 | if ((c = jo_peek (j)) == '-' || c == '+') 915 | jo_read (j); 916 | if ((c = jo_peek (j)) < '0' || c > '9') 917 | j->err = "Bad exp"; 918 | else 919 | while ((c = jo_peek (j)) >= '0' && c <= '9') 920 | jo_read (j); // exp 921 | } 922 | j->comma = 1; 923 | j->tagok = 0; 924 | break; 925 | case JO_NULL: 926 | if (jo_read (j) != 'n' || // 927 | jo_read (j) != 'u' || // 928 | jo_read (j) != 'l' || // 929 | jo_read (j) != 'l') 930 | j->err = "Misspelled null"; 931 | j->comma = 1; 932 | j->tagok = 0; 933 | break; 934 | case JO_TRUE: 935 | if (jo_read (j) != 't' || // 936 | jo_read (j) != 'r' || // 937 | jo_read (j) != 'u' || // 938 | jo_read (j) != 'e') 939 | j->err = "Misspelled true"; 940 | j->comma = 1; 941 | j->tagok = 0; 942 | break; 943 | case JO_FALSE: 944 | if (jo_read (j) != 'f' || // 945 | jo_read (j) != 'a' || // 946 | jo_read (j) != 'l' || // 947 | jo_read (j) != 's' || // 948 | jo_read (j) != 'e') 949 | j->err = "Misspelled false"; 950 | j->comma = 1; 951 | j->tagok = 0; 952 | break; 953 | } 954 | return jo_here (j); 955 | } 956 | 957 | static ssize_t 958 | jo_cpycmp (jo_t j, void *strv, size_t max, uint8_t cmp) 959 | { // Copy or compare (-1 for jstr) 960 | char *str = strv; 961 | char *end = str + max; 962 | if (!j || !j->parse || j->err) 963 | { // No pointer 964 | if (!cmp) 965 | return -1; // Invalid length 966 | if (!str) 967 | return 0; // null==null? 968 | return 1; // str>null 969 | } 970 | jo_t p = jo_link (j); 971 | int c = jo_peek (p); 972 | ssize_t result = 0; 973 | void process (int c) 974 | { // Compare or copy or count, etc 975 | if (cmp) 976 | { // Comparing 977 | if (!str) 978 | return; // Uh 979 | if (str >= end) 980 | { 981 | result = 1; // str ended, so str= 0xF0) 987 | { 988 | c2 &= 0x07; 989 | q = 3; 990 | } else if (c >= 0xE0) 991 | { 992 | c2 &= 0x0F; 993 | q = 2; 994 | } else if (c >= 0xC0) 995 | { 996 | c2 &= 0x1F; 997 | q = 1; 998 | } 999 | while (q-- && str < end && *str >= 0x80 && *str < 0xC0) 1000 | c2 = (c2 << 6) + (*str++ & 0x3F); 1001 | if (c < c2) 1002 | { 1003 | result = -1; // str>j 1004 | return; 1005 | } 1006 | if (c > c2) 1007 | { 1008 | result = 1; // str= 0xF0) 1020 | { 1021 | add (0xF0 + (c >> 18)); 1022 | add (0xC0 + ((c >> 12) & 0x3F)); 1023 | add (0xC0 + ((c >> 6) & 0x3F)); 1024 | add (0xC0 + (c & 0x3F)); 1025 | } else if (c >= 0xE0) 1026 | { 1027 | add (0xF0 + (c >> 12)); 1028 | add (0xC0 + ((c >> 6) & 0x3F)); 1029 | add (0xC0 + (c & 0x3F)); 1030 | } else if (c >= 0xC0) 1031 | { 1032 | add (0xF0 + (c >> 6)); 1033 | add (0xC0 + (c & 0x3F)); 1034 | } else 1035 | add (c); 1036 | } 1037 | } 1038 | if (c == '"') 1039 | { // String 1040 | jo_read (p); 1041 | while ((c = jo_read_str (p)) >= 0 && (!cmp || !result)) 1042 | process (c); 1043 | } else 1044 | { // Literal or number 1045 | while ((c = jo_read (p)) >= 0 && c > ' ' && c != ',' && c != '[' && c != '{' && c != ']' && c != '}' && (!cmp || !result)) 1046 | process (c); 1047 | } 1048 | if (!cmp && str && str < end) 1049 | *str = 0; // Final null... 1050 | if (!result && cmp && str && str < end) 1051 | result = -1; // j ended, do str>j 1052 | jo_free (&p); 1053 | return result; 1054 | } 1055 | 1056 | ssize_t 1057 | jo_strlen (jo_t j) 1058 | { // Return byte length, if a string or tag this is the decoded byte length, else length of literal 1059 | return jo_cpycmp (j, NULL, 0, 0); 1060 | } 1061 | 1062 | ssize_t 1063 | jo_strncpy (jo_t j, void *target, size_t max) 1064 | { // Copy from current point to a string. If a string or a tag, remove quotes and decode/deescape 1065 | return jo_cpycmp (j, target, max, 0); 1066 | } 1067 | 1068 | ssize_t 1069 | jo_strncmp (jo_t j, void *source, size_t max) 1070 | { // Compare from current point to a string. If a string or a tag, remove quotes and decode/deescape 1071 | return jo_cpycmp (j, source, max, 1); 1072 | } 1073 | 1074 | jo_type_t 1075 | jo_skip (jo_t j) 1076 | { // Skip to next value at this level 1077 | jo_type_t t = jo_here (j); 1078 | if (t > JO_CLOSE) 1079 | { 1080 | int l = jo_level (j); 1081 | while ((t = jo_next (j)) != JO_END && jo_level (j) > l); 1082 | if (!j->err && t == JO_END && j->level) 1083 | j->err = "Unclosed"; 1084 | } 1085 | return t; 1086 | } 1087 | 1088 | jo_type_t 1089 | jo_find (jo_t j, const char *path) 1090 | { // Find a path, JSON path style. Does not do [n] or ['name'] yet 1091 | jo_rewind (j); 1092 | if (*path == '$') 1093 | { 1094 | if (!path[1]) 1095 | return jo_here (j); // root 1096 | if (path[1] == '.') 1097 | path += 2; // We always start from root anyway 1098 | } 1099 | while (*path) 1100 | { 1101 | jo_type_t t = jo_here (j); 1102 | if (t != JO_OBJECT) 1103 | break; // Not an object 1104 | const char *tag = path; 1105 | while (*path && *path != '.') 1106 | path++; 1107 | int len = path - tag; 1108 | if (*path) 1109 | path++; 1110 | t = jo_next (j); 1111 | while (t == JO_TAG) 1112 | { // Scan the object 1113 | if (len == 1 && *tag == '*') 1114 | break; // Found - wildcard - only finds first entry 1115 | if (!jo_strncmp (j, (char *) tag, len)) 1116 | break; // Found 1117 | jo_next (j); 1118 | t = jo_skip (j); 1119 | } 1120 | if (t != JO_TAG) 1121 | break; // not found 1122 | t = jo_next (j); 1123 | if (!*path) 1124 | return t; // Found 1125 | } 1126 | return JO_END; 1127 | } 1128 | 1129 | const char * 1130 | jo_debug (jo_t j) 1131 | { // Debug string 1132 | if (!j) 1133 | return "No j"; 1134 | if (!j->parse) 1135 | { // Where we are up to creating 1136 | jo_store (j, 0); // add null 1137 | if (j->null) 1138 | return j->buf; 1139 | return "Not terminated"; 1140 | } 1141 | return j->buf + j->ptr; // Where we are (note, may not be 0 terminated) 1142 | } 1143 | 1144 | int64_t 1145 | jo_read_int (jo_t j) 1146 | { 1147 | if (!j || !j->parse || jo_here (j) != JO_NUMBER) 1148 | return -1; 1149 | int64_t n = 0, 1150 | c, 1151 | s = 1; 1152 | jo_t p = jo_link (j); 1153 | c = jo_read (p); 1154 | if (c == '-') 1155 | { 1156 | s = -1; 1157 | c = jo_read (p); 1158 | } 1159 | while (c >= '0' && c <= '9') 1160 | { 1161 | n = n * 10 + c - '0'; 1162 | c = jo_read (p); 1163 | } 1164 | jo_free (&p); 1165 | return n * s; 1166 | } 1167 | 1168 | long double 1169 | jo_read_float (jo_t j) 1170 | { 1171 | if (!j || !j->parse || jo_here (j) != JO_NUMBER) 1172 | return NAN; 1173 | char temp[50]; 1174 | ssize_t l = jo_strncpy (j, temp, sizeof (temp)); 1175 | if (l <= 0) 1176 | return NAN; 1177 | char *end = NULL; 1178 | long double value = strtold (temp, &end); 1179 | if (!end || *end) 1180 | return NAN; 1181 | return value; 1182 | } 1183 | 1184 | time_t 1185 | jo_read_datetime (jo_t j) 1186 | { // Get a datetime 1187 | if (jo_here (j) != JO_STRING) 1188 | return -1; 1189 | char dt[21]; 1190 | ssize_t l = jo_strncpy (j, dt, sizeof (dt)); 1191 | if (l != 10 && l != 19 && l != 20) 1192 | return -1; 1193 | int y = 0, 1194 | m = 0, 1195 | d = 0, 1196 | H = 0, 1197 | M = 0, 1198 | S = 0; 1199 | int n = sscanf (dt, "%d-%d-%d%*c%d:%d:%d", &y, &m, &d, &H, &M, &S); 1200 | if (n != 3 && n != 6) 1201 | return 1; 1202 | struct tm tm = {.tm_year = y - 1900,.tm_mon = m - 1,.tm_mday = d,.tm_hour = H,.tm_min = M,.tm_sec = S,.tm_isdst = -1 }; 1203 | time_t t = 0; 1204 | #if 0 // ESP IDF has no timegm! 1205 | if (l == 20 && dt[l - 1] == 'Z') 1206 | t = timegm (&tm); 1207 | else 1208 | t = timelocal (&tm); 1209 | #else 1210 | if (l == 20 && dt[l - 1] == 'Z') 1211 | tm.tm_isdst = 0; 1212 | t = mktime (&tm); 1213 | #endif 1214 | return t; 1215 | } 1216 | 1217 | jo_t 1218 | jo_parse_query (const char *buf) 1219 | { // Parse a query string format into a JSON object string (allocated) 1220 | if (!buf) 1221 | return NULL; 1222 | jo_t j = jo_object_alloc (); 1223 | if (!j) 1224 | return j; 1225 | while (*buf) 1226 | { 1227 | jo_write (j, '"'); 1228 | while (*buf && *buf != '=') 1229 | jo_write_char (j, *buf++); 1230 | if (*buf) 1231 | buf++; 1232 | jo_write (j, '"'); 1233 | jo_write (j, ':'); 1234 | jo_write (j, '"'); // Do all as strings 1235 | while (*buf && *buf != '&') 1236 | { 1237 | int c = *buf++; 1238 | if (c == '+') 1239 | c = ' '; 1240 | else if (c == '%' && isxdigit ((int) *buf) && isxdigit ((int) buf[1])) 1241 | { 1242 | c = (*buf & 0xF) + (isalpha ((int) *buf) ? 9 : 0); 1243 | buf++; 1244 | c = (c << 4) + (*buf & 0xF) + (isalpha ((int) *buf) ? 9 : 0); 1245 | buf++; 1246 | } 1247 | jo_write_char (j, c); 1248 | } 1249 | jo_write (j, '"'); 1250 | if (*buf) 1251 | buf++; 1252 | if (*buf) 1253 | jo_write (j, ','); 1254 | } 1255 | jo_close (j); 1256 | return j; 1257 | } 1258 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # 2 | # Automatically generated file. DO NOT EDIT. 3 | # Espressif IoT Development Framework (ESP-IDF) Project Configuration 4 | # 5 | CONFIG_IDF_TARGET_ARCH_XTENSA=y 6 | CONFIG_IDF_TARGET="esp32" 7 | CONFIG_IDF_TARGET_ESP32=y 8 | CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 9 | 10 | # 11 | # SDK tool configuration 12 | # 13 | CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" 14 | CONFIG_SDK_PYTHON="python" 15 | CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES=y 16 | # CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set 17 | # end of SDK tool configuration 18 | 19 | # 20 | # Build type 21 | # 22 | CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y 23 | # CONFIG_APP_BUILD_TYPE_ELF_RAM is not set 24 | CONFIG_APP_BUILD_GENERATE_BINARIES=y 25 | CONFIG_APP_BUILD_BOOTLOADER=y 26 | CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y 27 | # end of Build type 28 | 29 | # 30 | # Application manager 31 | # 32 | CONFIG_APP_COMPILE_TIME_DATE=y 33 | # CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set 34 | # CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set 35 | # CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set 36 | CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 37 | # end of Application manager 38 | 39 | # 40 | # Bootloader config 41 | # 42 | CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x1000 43 | CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y 44 | # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set 45 | # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set 46 | # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set 47 | # CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set 48 | CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y 49 | # CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set 50 | # CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set 51 | # CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set 52 | # CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set 53 | CONFIG_BOOTLOADER_LOG_LEVEL=1 54 | # CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set 55 | CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y 56 | # CONFIG_BOOTLOADER_FACTORY_RESET is not set 57 | # CONFIG_BOOTLOADER_APP_TEST is not set 58 | CONFIG_BOOTLOADER_WDT_ENABLE=y 59 | # CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set 60 | CONFIG_BOOTLOADER_WDT_TIME_MS=9000 61 | # CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set 62 | # CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set 63 | CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 64 | # CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set 65 | # end of Bootloader config 66 | 67 | # 68 | # Security features 69 | # 70 | CONFIG_SECURE_SIGNED_ON_BOOT=y 71 | CONFIG_SECURE_SIGNED_ON_UPDATE=y 72 | CONFIG_SECURE_SIGNED_APPS=y 73 | CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT=y 74 | CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME=y 75 | CONFIG_SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT=y 76 | CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT=y 77 | # CONFIG_SECURE_BOOT is not set 78 | CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES=y 79 | CONFIG_SECURE_BOOT_SIGNING_KEY="secure_boot_signing_key.pem" 80 | # CONFIG_SECURE_FLASH_ENC_ENABLED is not set 81 | # end of Security features 82 | 83 | # 84 | # Serial flasher config 85 | # 86 | CONFIG_ESPTOOLPY_PORT="/dev/cu.usbserial-AM00LQDF" 87 | CONFIG_ESPTOOLPY_BAUD_115200B=y 88 | # CONFIG_ESPTOOLPY_BAUD_230400B is not set 89 | # CONFIG_ESPTOOLPY_BAUD_921600B is not set 90 | # CONFIG_ESPTOOLPY_BAUD_2MB is not set 91 | # CONFIG_ESPTOOLPY_BAUD_OTHER is not set 92 | CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 93 | CONFIG_ESPTOOLPY_BAUD=115200 94 | CONFIG_ESPTOOLPY_COMPRESSED=y 95 | # CONFIG_ESPTOOLPY_NO_STUB is not set 96 | # CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set 97 | # CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set 98 | CONFIG_ESPTOOLPY_FLASHMODE_DIO=y 99 | # CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set 100 | CONFIG_ESPTOOLPY_FLASHMODE="dio" 101 | # CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set 102 | CONFIG_ESPTOOLPY_FLASHFREQ_40M=y 103 | # CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set 104 | # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set 105 | CONFIG_ESPTOOLPY_FLASHFREQ="40m" 106 | # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set 107 | # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set 108 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 109 | # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set 110 | # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set 111 | CONFIG_ESPTOOLPY_FLASHSIZE="4MB" 112 | CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y 113 | CONFIG_ESPTOOLPY_BEFORE_RESET=y 114 | # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set 115 | CONFIG_ESPTOOLPY_BEFORE="default_reset" 116 | CONFIG_ESPTOOLPY_AFTER_RESET=y 117 | # CONFIG_ESPTOOLPY_AFTER_NORESET is not set 118 | CONFIG_ESPTOOLPY_AFTER="hard_reset" 119 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set 120 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set 121 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set 122 | CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y 123 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set 124 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set 125 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set 126 | # CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set 127 | CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 128 | CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 129 | # end of Serial flasher config 130 | 131 | # 132 | # Partition Table 133 | # 134 | # CONFIG_PARTITION_TABLE_SINGLE_APP is not set 135 | # CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set 136 | # CONFIG_PARTITION_TABLE_TWO_OTA is not set 137 | CONFIG_PARTITION_TABLE_CUSTOM=y 138 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="components/ESP32-RevK/partitions_4m.csv" 139 | CONFIG_PARTITION_TABLE_FILENAME="components/ESP32-RevK/partitions_4m.csv" 140 | CONFIG_PARTITION_TABLE_OFFSET=0x8000 141 | CONFIG_PARTITION_TABLE_MD5=y 142 | # end of Partition Table 143 | 144 | # 145 | # Compiler options 146 | # 147 | CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y 148 | # CONFIG_COMPILER_OPTIMIZATION_SIZE is not set 149 | # CONFIG_COMPILER_OPTIMIZATION_PERF is not set 150 | # CONFIG_COMPILER_OPTIMIZATION_NONE is not set 151 | CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y 152 | # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set 153 | # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set 154 | # CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set 155 | # CONFIG_COMPILER_CXX_EXCEPTIONS is not set 156 | # CONFIG_COMPILER_CXX_RTTI is not set 157 | CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y 158 | # CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set 159 | # CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set 160 | # CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set 161 | # CONFIG_COMPILER_WARN_WRITE_STRINGS is not set 162 | # CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set 163 | # CONFIG_COMPILER_DUMP_RTL_FILES is not set 164 | # end of Compiler options 165 | 166 | # 167 | # Component config 168 | # 169 | 170 | # 171 | # RevK 172 | # 173 | CONFIG_REVK_APPNAME="" 174 | CONFIG_REVK_WIFI=y 175 | CONFIG_REVK_WIFISSID="IoT" 176 | CONFIG_REVK_WIFIPASS="security" 177 | CONFIG_REVK_WIFIBSSID="" 178 | CONFIG_REVK_WIFICHAN=0 179 | CONFIG_REVK_WIFIIP="" 180 | CONFIG_REVK_WIFIGW="" 181 | CONFIG_REVK_WIFIDNS="" 182 | CONFIG_REVK_APSSID="" 183 | CONFIG_REVK_APPASS="" 184 | CONFIG_REVK_APIP="10.0.0.1/24" 185 | # CONFIG_REVK_APLR is not set 186 | # CONFIG_REVK_APHIDE is not set 187 | CONFIG_REVK_MQTT=y 188 | CONFIG_REVK_MQTTHOST="mqtt.iot" 189 | CONFIG_REVK_MQTTUSER="" 190 | CONFIG_REVK_MQTTPASS="" 191 | CONFIG_REVK_MQTTCERT="" 192 | CONFIG_REVK_MQTTPORT=1883 193 | CONFIG_REVK_MQTTSIZE=2048 194 | CONFIG_REVK_MQTTQUIET=y 195 | CONFIG_REVK_OTAHOST="ota.revk.uk" 196 | CONFIG_REVK_OTACERT="" 197 | CONFIG_REVK_NTPHOST="pool.ntp.org" 198 | CONFIG_REVK_TZ="GMT+0BST,M3.5.0,M10.5.0" 199 | CONFIG_REVK_APCONFIG=y 200 | CONFIG_REVK_APPORT=0 201 | CONFIG_REVK_APWAIT=60 202 | CONFIG_REVK_APTIME=300 203 | CONFIG_REVK_PARTITION_CHECK=y 204 | CONFIG_REVK_LOCK_CPU1=y 205 | # CONFIG_REVK_SHORT_ID is not set 206 | # end of RevK 207 | 208 | # 209 | # VL53L0X 210 | # 211 | # CONFIG_VL53L0X_DEBUG is not set 212 | # end of VL53L0X 213 | 214 | # 215 | # Application Level Tracing 216 | # 217 | # CONFIG_APPTRACE_DEST_TRAX is not set 218 | CONFIG_APPTRACE_DEST_NONE=y 219 | CONFIG_APPTRACE_LOCK_ENABLE=y 220 | # end of Application Level Tracing 221 | 222 | # 223 | # ESP-ASIO 224 | # 225 | # CONFIG_ASIO_SSL_SUPPORT is not set 226 | # end of ESP-ASIO 227 | 228 | # 229 | # Bluetooth 230 | # 231 | # CONFIG_BT_ENABLED is not set 232 | CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 233 | CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 234 | CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 235 | CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0 236 | CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 237 | CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 238 | CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 239 | CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 240 | CONFIG_BT_CTRL_MODE_EFF=1 241 | CONFIG_BT_CTRL_BLE_MAX_ACT=10 242 | CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=10 243 | CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 244 | CONFIG_BT_CTRL_PINNED_TO_CORE=0 245 | CONFIG_BT_CTRL_HCI_TL=1 246 | CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 247 | CONFIG_BT_CTRL_HW_CCA_EFF=0 248 | CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=0 249 | CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y 250 | CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 251 | CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 252 | CONFIG_BT_CTRL_BLE_SCAN_DUPL=y 253 | CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 254 | CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 255 | CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 256 | CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 257 | CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 258 | CONFIG_BT_CTRL_HCI_TL_EFF=1 259 | CONFIG_BT_RESERVE_DRAM=0 260 | # end of Bluetooth 261 | 262 | # 263 | # CoAP Configuration 264 | # 265 | CONFIG_COAP_MBEDTLS_PSK=y 266 | # CONFIG_COAP_MBEDTLS_PKI is not set 267 | # CONFIG_COAP_MBEDTLS_DEBUG is not set 268 | CONFIG_COAP_LOG_DEFAULT_LEVEL=0 269 | # end of CoAP Configuration 270 | 271 | # 272 | # Driver configurations 273 | # 274 | 275 | # 276 | # ADC configuration 277 | # 278 | # CONFIG_ADC_FORCE_XPD_FSM is not set 279 | CONFIG_ADC_DISABLE_DAC=y 280 | # end of ADC configuration 281 | 282 | # 283 | # SPI configuration 284 | # 285 | # CONFIG_SPI_MASTER_IN_IRAM is not set 286 | CONFIG_SPI_MASTER_ISR_IN_IRAM=y 287 | # CONFIG_SPI_SLAVE_IN_IRAM is not set 288 | CONFIG_SPI_SLAVE_ISR_IN_IRAM=y 289 | # end of SPI configuration 290 | 291 | # 292 | # TWAI configuration 293 | # 294 | # CONFIG_TWAI_ISR_IN_IRAM is not set 295 | # CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC is not set 296 | # CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST is not set 297 | # CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID is not set 298 | # CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT is not set 299 | # end of TWAI configuration 300 | 301 | # 302 | # UART configuration 303 | # 304 | # CONFIG_UART_ISR_IN_IRAM is not set 305 | # end of UART configuration 306 | 307 | # 308 | # RTCIO configuration 309 | # 310 | # CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set 311 | # end of RTCIO configuration 312 | 313 | # 314 | # GPIO Configuration 315 | # 316 | # CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL is not set 317 | # end of GPIO Configuration 318 | # end of Driver configurations 319 | 320 | # 321 | # eFuse Bit Manager 322 | # 323 | # CONFIG_EFUSE_CUSTOM_TABLE is not set 324 | # CONFIG_EFUSE_VIRTUAL is not set 325 | # CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set 326 | CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y 327 | # CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set 328 | CONFIG_EFUSE_MAX_BLK_LEN=192 329 | # end of eFuse Bit Manager 330 | 331 | # 332 | # ESP-TLS 333 | # 334 | CONFIG_ESP_TLS_USING_MBEDTLS=y 335 | # CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set 336 | # CONFIG_ESP_TLS_SERVER is not set 337 | # CONFIG_ESP_TLS_PSK_VERIFICATION is not set 338 | # CONFIG_ESP_TLS_INSECURE is not set 339 | # end of ESP-TLS 340 | 341 | # 342 | # ESP32-specific 343 | # 344 | CONFIG_ESP32_ECO3_CACHE_LOCK_FIX=y 345 | CONFIG_ESP32_REV_MIN_0=y 346 | # CONFIG_ESP32_REV_MIN_1 is not set 347 | # CONFIG_ESP32_REV_MIN_2 is not set 348 | # CONFIG_ESP32_REV_MIN_3 is not set 349 | CONFIG_ESP32_REV_MIN=0 350 | CONFIG_ESP32_DPORT_WORKAROUND=y 351 | # CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set 352 | CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y 353 | # CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set 354 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 355 | CONFIG_ESP32_SPIRAM_SUPPORT=y 356 | 357 | # 358 | # SPI RAM config 359 | # 360 | CONFIG_SPIRAM_TYPE_AUTO=y 361 | # CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set 362 | # CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set 363 | # CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set 364 | CONFIG_SPIRAM_SIZE=-1 365 | CONFIG_SPIRAM_SPEED_40M=y 366 | CONFIG_SPIRAM=y 367 | CONFIG_SPIRAM_BOOT_INIT=y 368 | CONFIG_SPIRAM_IGNORE_NOTFOUND=y 369 | # CONFIG_SPIRAM_USE_MEMMAP is not set 370 | # CONFIG_SPIRAM_USE_CAPS_ALLOC is not set 371 | CONFIG_SPIRAM_USE_MALLOC=y 372 | CONFIG_SPIRAM_MEMTEST=y 373 | CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 374 | # CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set 375 | CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 376 | # CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set 377 | CONFIG_SPIRAM_CACHE_WORKAROUND=y 378 | 379 | # 380 | # SPIRAM cache workaround debugging 381 | # 382 | CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW=y 383 | # CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST is not set 384 | # CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS is not set 385 | # end of SPIRAM cache workaround debugging 386 | 387 | CONFIG_SPIRAM_BANKSWITCH_ENABLE=y 388 | CONFIG_SPIRAM_BANKSWITCH_RESERVE=8 389 | # CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY is not set 390 | 391 | # 392 | # PSRAM clock and cs IO for ESP32-DOWD 393 | # 394 | CONFIG_D0WD_PSRAM_CLK_IO=17 395 | CONFIG_D0WD_PSRAM_CS_IO=16 396 | # end of PSRAM clock and cs IO for ESP32-DOWD 397 | 398 | # 399 | # PSRAM clock and cs IO for ESP32-D2WD 400 | # 401 | CONFIG_D2WD_PSRAM_CLK_IO=9 402 | CONFIG_D2WD_PSRAM_CS_IO=10 403 | # end of PSRAM clock and cs IO for ESP32-D2WD 404 | 405 | # 406 | # PSRAM clock and cs IO for ESP32-PICO 407 | # 408 | CONFIG_PICO_PSRAM_CS_IO=10 409 | # end of PSRAM clock and cs IO for ESP32-PICO 410 | 411 | # CONFIG_SPIRAM_CUSTOM_SPIWP_SD3_PIN is not set 412 | CONFIG_SPIRAM_SPIWP_SD3_PIN=7 413 | # CONFIG_SPIRAM_2T_MODE is not set 414 | # end of SPI RAM config 415 | 416 | # CONFIG_ESP32_TRAX is not set 417 | CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 418 | # CONFIG_ESP32_ULP_COPROC_ENABLED is not set 419 | CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 420 | CONFIG_ESP32_DEBUG_OCDAWARE=y 421 | CONFIG_ESP32_BROWNOUT_DET=y 422 | CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y 423 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set 424 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set 425 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set 426 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set 427 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set 428 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set 429 | # CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set 430 | CONFIG_ESP32_BROWNOUT_DET_LVL=0 431 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y 432 | # CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set 433 | # CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set 434 | # CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set 435 | CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y 436 | # CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set 437 | # CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set 438 | # CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set 439 | CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 440 | CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 441 | CONFIG_ESP32_XTAL_FREQ_40=y 442 | # CONFIG_ESP32_XTAL_FREQ_26 is not set 443 | # CONFIG_ESP32_XTAL_FREQ_AUTO is not set 444 | CONFIG_ESP32_XTAL_FREQ=40 445 | # CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set 446 | # CONFIG_ESP32_NO_BLOBS is not set 447 | # CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set 448 | # CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set 449 | CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 450 | # end of ESP32-specific 451 | 452 | CONFIG_ESP32C3_DEBUG_OCDAWARE=y 453 | CONFIG_ESP32C3_BROWNOUT_DET=y 454 | CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y 455 | 456 | # 457 | # Cache config 458 | # 459 | # end of Cache config 460 | 461 | CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM=0x0 462 | CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=0 463 | CONFIG_ESP32S2_DEBUG_OCDAWARE=y 464 | CONFIG_ESP32S2_BROWNOUT_DET=y 465 | 466 | # 467 | # Cache config 468 | # 469 | # end of Cache config 470 | 471 | CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 472 | CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=0 473 | CONFIG_ESP32S3_DEBUG_OCDAWARE=y 474 | CONFIG_ESP32S3_BROWNOUT_DET=y 475 | 476 | # 477 | # ADC-Calibration 478 | # 479 | CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y 480 | CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y 481 | CONFIG_ADC_CAL_LUT_ENABLE=y 482 | # end of ADC-Calibration 483 | 484 | # 485 | # Common ESP-related 486 | # 487 | CONFIG_ESP_ERR_TO_NAME_LOOKUP=y 488 | # end of Common ESP-related 489 | 490 | # 491 | # Ethernet 492 | # 493 | CONFIG_ETH_ENABLED=y 494 | CONFIG_ETH_USE_ESP32_EMAC=y 495 | CONFIG_ETH_PHY_INTERFACE_RMII=y 496 | # CONFIG_ETH_PHY_INTERFACE_MII is not set 497 | CONFIG_ETH_RMII_CLK_INPUT=y 498 | # CONFIG_ETH_RMII_CLK_OUTPUT is not set 499 | CONFIG_ETH_RMII_CLK_IN_GPIO=0 500 | CONFIG_ETH_DMA_BUFFER_SIZE=512 501 | CONFIG_ETH_DMA_RX_BUFFER_NUM=10 502 | CONFIG_ETH_DMA_TX_BUFFER_NUM=10 503 | CONFIG_ETH_USE_SPI_ETHERNET=y 504 | CONFIG_ETH_SPI_ETHERNET_DM9051=y 505 | # CONFIG_ETH_SPI_ETHERNET_W5500 is not set 506 | # CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set 507 | # CONFIG_ETH_USE_OPENETH is not set 508 | # end of Ethernet 509 | 510 | # 511 | # Event Loop Library 512 | # 513 | # CONFIG_ESP_EVENT_LOOP_PROFILING is not set 514 | CONFIG_ESP_EVENT_POST_FROM_ISR=y 515 | CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y 516 | # end of Event Loop Library 517 | 518 | # 519 | # GDB Stub 520 | # 521 | # end of GDB Stub 522 | 523 | # 524 | # ESP HTTP client 525 | # 526 | CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y 527 | # CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set 528 | CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y 529 | # end of ESP HTTP client 530 | 531 | # 532 | # HTTP Server 533 | # 534 | CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 535 | CONFIG_HTTPD_MAX_URI_LEN=512 536 | CONFIG_HTTPD_ERR_RESP_NO_DELAY=y 537 | CONFIG_HTTPD_PURGE_BUF_LEN=32 538 | # CONFIG_HTTPD_LOG_PURGE_DATA is not set 539 | # CONFIG_HTTPD_WS_SUPPORT is not set 540 | # end of HTTP Server 541 | 542 | # 543 | # ESP HTTPS OTA 544 | # 545 | # CONFIG_OTA_ALLOW_HTTP is not set 546 | # end of ESP HTTPS OTA 547 | 548 | # 549 | # ESP HTTPS server 550 | # 551 | # CONFIG_ESP_HTTPS_SERVER_ENABLE is not set 552 | # end of ESP HTTPS server 553 | 554 | # 555 | # Hardware Settings 556 | # 557 | 558 | # 559 | # MAC Config 560 | # 561 | CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y 562 | CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y 563 | CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y 564 | CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y 565 | # CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set 566 | CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y 567 | CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 568 | # end of MAC Config 569 | 570 | # 571 | # Sleep Config 572 | # 573 | # end of Sleep Config 574 | # end of Hardware Settings 575 | 576 | # 577 | # LCD and Touch Panel 578 | # 579 | # end of LCD and Touch Panel 580 | 581 | # 582 | # ESP NETIF Adapter 583 | # 584 | CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 585 | CONFIG_ESP_NETIF_TCPIP_LWIP=y 586 | # CONFIG_ESP_NETIF_LOOPBACK is not set 587 | CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y 588 | # end of ESP NETIF Adapter 589 | 590 | # 591 | # Power Management 592 | # 593 | # CONFIG_PM_ENABLE is not set 594 | # end of Power Management 595 | 596 | # 597 | # ESP System Settings 598 | # 599 | # CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set 600 | CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y 601 | # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set 602 | # CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set 603 | 604 | # 605 | # Memory protection 606 | # 607 | # end of Memory protection 608 | 609 | CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 610 | CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 611 | CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 612 | CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y 613 | # CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set 614 | # CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set 615 | CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 616 | CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 617 | CONFIG_ESP_CONSOLE_UART_DEFAULT=y 618 | # CONFIG_ESP_CONSOLE_UART_CUSTOM is not set 619 | # CONFIG_ESP_CONSOLE_NONE is not set 620 | CONFIG_ESP_CONSOLE_UART=y 621 | CONFIG_ESP_CONSOLE_MULTIPLE_UART=y 622 | CONFIG_ESP_CONSOLE_UART_NUM=0 623 | CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 624 | CONFIG_ESP_INT_WDT=y 625 | CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 626 | CONFIG_ESP_INT_WDT_CHECK_CPU1=y 627 | CONFIG_ESP_TASK_WDT=y 628 | CONFIG_ESP_TASK_WDT_PANIC=y 629 | CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 630 | CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y 631 | CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y 632 | CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 633 | CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y 634 | # CONFIG_ESP_PANIC_HANDLER_IRAM is not set 635 | # end of ESP System Settings 636 | 637 | # 638 | # High resolution timer (esp_timer) 639 | # 640 | # CONFIG_ESP_TIMER_PROFILING is not set 641 | CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y 642 | CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y 643 | CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 644 | CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 645 | # CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set 646 | # CONFIG_ESP_TIMER_IMPL_FRC2 is not set 647 | CONFIG_ESP_TIMER_IMPL_TG0_LAC=y 648 | # end of High resolution timer (esp_timer) 649 | 650 | # 651 | # Wi-Fi 652 | # 653 | CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 654 | CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 655 | CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y 656 | CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 657 | CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 658 | CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32 659 | # CONFIG_ESP32_WIFI_CSI_ENABLED is not set 660 | CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y 661 | CONFIG_ESP32_WIFI_TX_BA_WIN=6 662 | CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y 663 | CONFIG_ESP32_WIFI_RX_BA_WIN=6 664 | # CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set 665 | CONFIG_ESP32_WIFI_NVS_ENABLED=y 666 | CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y 667 | # CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set 668 | CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 669 | CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 670 | # CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set 671 | CONFIG_ESP32_WIFI_IRAM_OPT=y 672 | CONFIG_ESP32_WIFI_RX_IRAM_OPT=y 673 | CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y 674 | # CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set 675 | # CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set 676 | # end of Wi-Fi 677 | 678 | # 679 | # PHY 680 | # 681 | CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y 682 | # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set 683 | CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 684 | CONFIG_ESP32_PHY_MAX_TX_POWER=20 685 | CONFIG_ESP32_REDUCE_PHY_TX_POWER=y 686 | # end of PHY 687 | 688 | # 689 | # Core dump 690 | # 691 | # CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set 692 | # CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set 693 | CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y 694 | # end of Core dump 695 | 696 | # 697 | # FAT Filesystem support 698 | # 699 | # CONFIG_FATFS_CODEPAGE_DYNAMIC is not set 700 | CONFIG_FATFS_CODEPAGE_437=y 701 | # CONFIG_FATFS_CODEPAGE_720 is not set 702 | # CONFIG_FATFS_CODEPAGE_737 is not set 703 | # CONFIG_FATFS_CODEPAGE_771 is not set 704 | # CONFIG_FATFS_CODEPAGE_775 is not set 705 | # CONFIG_FATFS_CODEPAGE_850 is not set 706 | # CONFIG_FATFS_CODEPAGE_852 is not set 707 | # CONFIG_FATFS_CODEPAGE_855 is not set 708 | # CONFIG_FATFS_CODEPAGE_857 is not set 709 | # CONFIG_FATFS_CODEPAGE_860 is not set 710 | # CONFIG_FATFS_CODEPAGE_861 is not set 711 | # CONFIG_FATFS_CODEPAGE_862 is not set 712 | # CONFIG_FATFS_CODEPAGE_863 is not set 713 | # CONFIG_FATFS_CODEPAGE_864 is not set 714 | # CONFIG_FATFS_CODEPAGE_865 is not set 715 | # CONFIG_FATFS_CODEPAGE_866 is not set 716 | # CONFIG_FATFS_CODEPAGE_869 is not set 717 | # CONFIG_FATFS_CODEPAGE_932 is not set 718 | # CONFIG_FATFS_CODEPAGE_936 is not set 719 | # CONFIG_FATFS_CODEPAGE_949 is not set 720 | # CONFIG_FATFS_CODEPAGE_950 is not set 721 | CONFIG_FATFS_CODEPAGE=437 722 | CONFIG_FATFS_LFN_NONE=y 723 | # CONFIG_FATFS_LFN_HEAP is not set 724 | # CONFIG_FATFS_LFN_STACK is not set 725 | CONFIG_FATFS_FS_LOCK=0 726 | CONFIG_FATFS_TIMEOUT_MS=10000 727 | CONFIG_FATFS_PER_FILE_CACHE=y 728 | CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y 729 | # CONFIG_FATFS_USE_FASTSEEK is not set 730 | # end of FAT Filesystem support 731 | 732 | # 733 | # Modbus configuration 734 | # 735 | CONFIG_FMB_COMM_MODE_TCP_EN=y 736 | CONFIG_FMB_TCP_PORT_DEFAULT=502 737 | CONFIG_FMB_TCP_PORT_MAX_CONN=5 738 | CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 739 | CONFIG_FMB_COMM_MODE_RTU_EN=y 740 | CONFIG_FMB_COMM_MODE_ASCII_EN=y 741 | CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 742 | CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 743 | CONFIG_FMB_QUEUE_LENGTH=20 744 | CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 745 | CONFIG_FMB_SERIAL_BUF_SIZE=256 746 | CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 747 | CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 748 | CONFIG_FMB_PORT_TASK_PRIO=10 749 | # CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set 750 | CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 751 | CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 752 | CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 753 | CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 754 | CONFIG_FMB_TIMER_PORT_ENABLED=y 755 | CONFIG_FMB_TIMER_GROUP=0 756 | CONFIG_FMB_TIMER_INDEX=0 757 | # CONFIG_FMB_TIMER_ISR_IN_IRAM is not set 758 | # end of Modbus configuration 759 | 760 | # 761 | # FreeRTOS 762 | # 763 | # CONFIG_FREERTOS_UNICORE is not set 764 | CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF 765 | CONFIG_FREERTOS_CORETIMER_0=y 766 | # CONFIG_FREERTOS_CORETIMER_1 is not set 767 | CONFIG_FREERTOS_HZ=1000 768 | CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y 769 | # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set 770 | # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set 771 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y 772 | # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set 773 | CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y 774 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 775 | CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y 776 | # CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set 777 | # CONFIG_FREERTOS_ASSERT_DISABLE is not set 778 | CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 779 | CONFIG_FREERTOS_ISR_STACKSIZE=1536 780 | # CONFIG_FREERTOS_LEGACY_HOOKS is not set 781 | CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 782 | CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y 783 | # CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set 784 | CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 785 | CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 786 | CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 787 | CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 788 | # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set 789 | # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set 790 | CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y 791 | CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y 792 | # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set 793 | # CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set 794 | CONFIG_FREERTOS_DEBUG_OCDAWARE=y 795 | # CONFIG_FREERTOS_FPU_IN_ISR is not set 796 | # end of FreeRTOS 797 | 798 | # 799 | # Heap memory debugging 800 | # 801 | CONFIG_HEAP_POISONING_DISABLED=y 802 | # CONFIG_HEAP_POISONING_LIGHT is not set 803 | # CONFIG_HEAP_POISONING_COMPREHENSIVE is not set 804 | CONFIG_HEAP_TRACING_OFF=y 805 | # CONFIG_HEAP_TRACING_STANDALONE is not set 806 | # CONFIG_HEAP_TRACING_TOHOST is not set 807 | CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS=y 808 | # end of Heap memory debugging 809 | 810 | # 811 | # jsmn 812 | # 813 | # CONFIG_JSMN_PARENT_LINKS is not set 814 | # CONFIG_JSMN_STRICT is not set 815 | # end of jsmn 816 | 817 | # 818 | # libsodium 819 | # 820 | CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y 821 | # end of libsodium 822 | 823 | # 824 | # Log output 825 | # 826 | # CONFIG_LOG_DEFAULT_LEVEL_NONE is not set 827 | CONFIG_LOG_DEFAULT_LEVEL_ERROR=y 828 | # CONFIG_LOG_DEFAULT_LEVEL_WARN is not set 829 | # CONFIG_LOG_DEFAULT_LEVEL_INFO is not set 830 | # CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set 831 | # CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set 832 | CONFIG_LOG_DEFAULT_LEVEL=1 833 | CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y 834 | # CONFIG_LOG_MAXIMUM_LEVEL_WARN is not set 835 | # CONFIG_LOG_MAXIMUM_LEVEL_INFO is not set 836 | # CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set 837 | # CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set 838 | CONFIG_LOG_MAXIMUM_LEVEL=1 839 | CONFIG_LOG_COLORS=y 840 | CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y 841 | # CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set 842 | # end of Log output 843 | 844 | # 845 | # LWIP 846 | # 847 | CONFIG_LWIP_LOCAL_HOSTNAME="espressif" 848 | # CONFIG_LWIP_NETIF_API is not set 849 | CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y 850 | # CONFIG_LWIP_L2_TO_L3_COPY is not set 851 | # CONFIG_LWIP_IRAM_OPTIMIZATION is not set 852 | CONFIG_LWIP_TIMERS_ONDEMAND=y 853 | CONFIG_LWIP_MAX_SOCKETS=10 854 | # CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set 855 | # CONFIG_LWIP_SO_LINGER is not set 856 | CONFIG_LWIP_SO_REUSE=y 857 | CONFIG_LWIP_SO_REUSE_RXTOALL=y 858 | # CONFIG_LWIP_SO_RCVBUF is not set 859 | # CONFIG_LWIP_NETBUF_RECVINFO is not set 860 | CONFIG_LWIP_IP4_FRAG=y 861 | CONFIG_LWIP_IP6_FRAG=y 862 | # CONFIG_LWIP_IP4_REASSEMBLY is not set 863 | # CONFIG_LWIP_IP6_REASSEMBLY is not set 864 | # CONFIG_LWIP_IP_FORWARD is not set 865 | # CONFIG_LWIP_STATS is not set 866 | # CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set 867 | CONFIG_LWIP_ESP_GRATUITOUS_ARP=y 868 | CONFIG_LWIP_GARP_TMR_INTERVAL=60 869 | CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 870 | CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y 871 | # CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set 872 | # CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set 873 | 874 | # 875 | # DHCP server 876 | # 877 | CONFIG_LWIP_DHCPS_LEASE_UNIT=60 878 | CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 879 | # end of DHCP server 880 | 881 | # CONFIG_LWIP_AUTOIP is not set 882 | CONFIG_LWIP_IPV6=y 883 | CONFIG_LWIP_IPV6_AUTOCONFIG=y 884 | CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 885 | # CONFIG_LWIP_IPV6_FORWARD is not set 886 | # CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set 887 | CONFIG_LWIP_NETIF_LOOPBACK=y 888 | CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 889 | 890 | # 891 | # TCP 892 | # 893 | CONFIG_LWIP_MAX_ACTIVE_TCP=16 894 | CONFIG_LWIP_MAX_LISTENING_TCP=16 895 | CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y 896 | CONFIG_LWIP_TCP_MAXRTX=12 897 | CONFIG_LWIP_TCP_SYNMAXRTX=6 898 | CONFIG_LWIP_TCP_MSS=1440 899 | CONFIG_LWIP_TCP_TMR_INTERVAL=250 900 | CONFIG_LWIP_TCP_MSL=60000 901 | CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 902 | CONFIG_LWIP_TCP_WND_DEFAULT=5744 903 | CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 904 | CONFIG_LWIP_TCP_QUEUE_OOSEQ=y 905 | # CONFIG_LWIP_TCP_SACK_OUT is not set 906 | # CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set 907 | CONFIG_LWIP_TCP_OVERSIZE_MSS=y 908 | # CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set 909 | # CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set 910 | CONFIG_LWIP_TCP_RTO_TIME=1500 911 | # end of TCP 912 | 913 | # 914 | # UDP 915 | # 916 | CONFIG_LWIP_MAX_UDP_PCBS=16 917 | CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 918 | # end of UDP 919 | 920 | # 921 | # Checksums 922 | # 923 | # CONFIG_LWIP_CHECKSUM_CHECK_IP is not set 924 | # CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set 925 | CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y 926 | # end of Checksums 927 | 928 | CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 929 | CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y 930 | # CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set 931 | # CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set 932 | CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF 933 | # CONFIG_LWIP_PPP_SUPPORT is not set 934 | CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 935 | CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 936 | # CONFIG_LWIP_SLIP_SUPPORT is not set 937 | 938 | # 939 | # ICMP 940 | # 941 | # CONFIG_LWIP_MULTICAST_PING is not set 942 | # CONFIG_LWIP_BROADCAST_PING is not set 943 | # end of ICMP 944 | 945 | # 946 | # LWIP RAW API 947 | # 948 | CONFIG_LWIP_MAX_RAW_PCBS=16 949 | # end of LWIP RAW API 950 | 951 | # 952 | # SNTP 953 | # 954 | CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 955 | CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 956 | # end of SNTP 957 | 958 | CONFIG_LWIP_ESP_LWIP_ASSERT=y 959 | 960 | # 961 | # Hooks 962 | # 963 | # CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set 964 | CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y 965 | # CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set 966 | CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y 967 | # CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set 968 | # CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set 969 | CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y 970 | # CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set 971 | # CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set 972 | CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y 973 | # CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set 974 | # CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set 975 | # end of Hooks 976 | 977 | # CONFIG_LWIP_DEBUG is not set 978 | # end of LWIP 979 | 980 | # 981 | # mbedTLS 982 | # 983 | CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y 984 | # CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set 985 | # CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set 986 | # CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set 987 | CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y 988 | CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 989 | CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 990 | # CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set 991 | # CONFIG_MBEDTLS_DEBUG is not set 992 | 993 | # 994 | # Certificate Bundle 995 | # 996 | CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y 997 | CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y 998 | # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set 999 | # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set 1000 | # CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set 1001 | # end of Certificate Bundle 1002 | 1003 | # CONFIG_MBEDTLS_ECP_RESTARTABLE is not set 1004 | # CONFIG_MBEDTLS_CMAC_C is not set 1005 | CONFIG_MBEDTLS_HARDWARE_AES=y 1006 | # CONFIG_MBEDTLS_HARDWARE_MPI is not set 1007 | # CONFIG_MBEDTLS_HARDWARE_SHA is not set 1008 | CONFIG_MBEDTLS_ROM_MD5=y 1009 | # CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set 1010 | # CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set 1011 | CONFIG_MBEDTLS_HAVE_TIME=y 1012 | # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set 1013 | CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y 1014 | CONFIG_MBEDTLS_SHA512_C=y 1015 | CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y 1016 | # CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set 1017 | # CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set 1018 | # CONFIG_MBEDTLS_TLS_DISABLED is not set 1019 | CONFIG_MBEDTLS_TLS_SERVER=y 1020 | CONFIG_MBEDTLS_TLS_CLIENT=y 1021 | CONFIG_MBEDTLS_TLS_ENABLED=y 1022 | 1023 | # 1024 | # TLS Key Exchange Methods 1025 | # 1026 | CONFIG_MBEDTLS_PSK_MODES=y 1027 | CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y 1028 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y 1029 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y 1030 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y 1031 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y 1032 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y 1033 | CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y 1034 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y 1035 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y 1036 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y 1037 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y 1038 | # end of TLS Key Exchange Methods 1039 | 1040 | CONFIG_MBEDTLS_SSL_RENEGOTIATION=y 1041 | # CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set 1042 | CONFIG_MBEDTLS_SSL_PROTO_TLS1=y 1043 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y 1044 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y 1045 | CONFIG_MBEDTLS_SSL_PROTO_DTLS=y 1046 | CONFIG_MBEDTLS_SSL_ALPN=y 1047 | CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y 1048 | CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y 1049 | 1050 | # 1051 | # Symmetric Ciphers 1052 | # 1053 | CONFIG_MBEDTLS_AES_C=y 1054 | # CONFIG_MBEDTLS_CAMELLIA_C is not set 1055 | # CONFIG_MBEDTLS_DES_C is not set 1056 | CONFIG_MBEDTLS_RC4_DISABLED=y 1057 | # CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set 1058 | # CONFIG_MBEDTLS_RC4_ENABLED is not set 1059 | # CONFIG_MBEDTLS_BLOWFISH_C is not set 1060 | # CONFIG_MBEDTLS_XTEA_C is not set 1061 | CONFIG_MBEDTLS_CCM_C=y 1062 | CONFIG_MBEDTLS_GCM_C=y 1063 | # CONFIG_MBEDTLS_NIST_KW_C is not set 1064 | # end of Symmetric Ciphers 1065 | 1066 | # CONFIG_MBEDTLS_RIPEMD160_C is not set 1067 | 1068 | # 1069 | # Certificates 1070 | # 1071 | CONFIG_MBEDTLS_PEM_PARSE_C=y 1072 | CONFIG_MBEDTLS_PEM_WRITE_C=y 1073 | CONFIG_MBEDTLS_X509_CRL_PARSE_C=y 1074 | CONFIG_MBEDTLS_X509_CSR_PARSE_C=y 1075 | # end of Certificates 1076 | 1077 | CONFIG_MBEDTLS_ECP_C=y 1078 | CONFIG_MBEDTLS_ECDH_C=y 1079 | CONFIG_MBEDTLS_ECDSA_C=y 1080 | # CONFIG_MBEDTLS_ECJPAKE_C is not set 1081 | CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y 1082 | CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y 1083 | CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y 1084 | CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y 1085 | CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y 1086 | CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y 1087 | CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y 1088 | CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y 1089 | CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y 1090 | CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y 1091 | CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y 1092 | CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y 1093 | CONFIG_MBEDTLS_ECP_NIST_OPTIM=y 1094 | # CONFIG_MBEDTLS_POLY1305_C is not set 1095 | # CONFIG_MBEDTLS_CHACHA20_C is not set 1096 | # CONFIG_MBEDTLS_HKDF_C is not set 1097 | # CONFIG_MBEDTLS_THREADING_C is not set 1098 | # CONFIG_MBEDTLS_SECURITY_RISKS is not set 1099 | # end of mbedTLS 1100 | 1101 | # 1102 | # mDNS 1103 | # 1104 | CONFIG_MDNS_MAX_SERVICES=10 1105 | CONFIG_MDNS_TASK_PRIORITY=1 1106 | CONFIG_MDNS_TASK_STACK_SIZE=4096 1107 | # CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set 1108 | CONFIG_MDNS_TASK_AFFINITY_CPU0=y 1109 | # CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set 1110 | CONFIG_MDNS_TASK_AFFINITY=0x0 1111 | CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 1112 | # CONFIG_MDNS_STRICT_MODE is not set 1113 | CONFIG_MDNS_TIMER_PERIOD_MS=100 1114 | # end of mDNS 1115 | 1116 | # 1117 | # ESP-MQTT Configurations 1118 | # 1119 | CONFIG_MQTT_PROTOCOL_311=y 1120 | CONFIG_MQTT_TRANSPORT_SSL=y 1121 | CONFIG_MQTT_TRANSPORT_WEBSOCKET=y 1122 | CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y 1123 | # CONFIG_MQTT_MSG_ID_INCREMENTAL is not set 1124 | # CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set 1125 | # CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set 1126 | # CONFIG_MQTT_USE_CUSTOM_CONFIG is not set 1127 | # CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set 1128 | # CONFIG_MQTT_CUSTOM_OUTBOX is not set 1129 | # end of ESP-MQTT Configurations 1130 | 1131 | # 1132 | # Newlib 1133 | # 1134 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y 1135 | # CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set 1136 | # CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set 1137 | # CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set 1138 | # CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set 1139 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y 1140 | # CONFIG_NEWLIB_NANO_FORMAT is not set 1141 | # end of Newlib 1142 | 1143 | # 1144 | # NVS 1145 | # 1146 | # end of NVS 1147 | 1148 | # 1149 | # OpenSSL 1150 | # 1151 | # CONFIG_OPENSSL_DEBUG is not set 1152 | CONFIG_OPENSSL_ERROR_STACK=y 1153 | CONFIG_OPENSSL_ASSERT_DO_NOTHING=y 1154 | # CONFIG_OPENSSL_ASSERT_EXIT is not set 1155 | # end of OpenSSL 1156 | 1157 | # 1158 | # OpenThread 1159 | # 1160 | # CONFIG_OPENTHREAD_ENABLED is not set 1161 | # end of OpenThread 1162 | 1163 | # 1164 | # PThreads 1165 | # 1166 | CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 1167 | CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 1168 | CONFIG_PTHREAD_STACK_MIN=768 1169 | CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y 1170 | # CONFIG_PTHREAD_DEFAULT_CORE_0 is not set 1171 | # CONFIG_PTHREAD_DEFAULT_CORE_1 is not set 1172 | CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 1173 | CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" 1174 | # end of PThreads 1175 | 1176 | # 1177 | # SPI Flash driver 1178 | # 1179 | # CONFIG_SPI_FLASH_VERIFY_WRITE is not set 1180 | # CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set 1181 | CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y 1182 | # CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS is not set 1183 | # CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set 1184 | CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED=y 1185 | # CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set 1186 | # CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set 1187 | # CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set 1188 | CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y 1189 | CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 1190 | CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 1191 | CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 1192 | # CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set 1193 | # CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set 1194 | # CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set 1195 | 1196 | # 1197 | # Auto-detect flash chips 1198 | # 1199 | CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y 1200 | CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y 1201 | CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y 1202 | CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y 1203 | # end of Auto-detect flash chips 1204 | 1205 | CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y 1206 | # end of SPI Flash driver 1207 | 1208 | # 1209 | # SPIFFS Configuration 1210 | # 1211 | CONFIG_SPIFFS_MAX_PARTITIONS=3 1212 | 1213 | # 1214 | # SPIFFS Cache Configuration 1215 | # 1216 | CONFIG_SPIFFS_CACHE=y 1217 | CONFIG_SPIFFS_CACHE_WR=y 1218 | # CONFIG_SPIFFS_CACHE_STATS is not set 1219 | # end of SPIFFS Cache Configuration 1220 | 1221 | CONFIG_SPIFFS_PAGE_CHECK=y 1222 | CONFIG_SPIFFS_GC_MAX_RUNS=10 1223 | # CONFIG_SPIFFS_GC_STATS is not set 1224 | CONFIG_SPIFFS_PAGE_SIZE=256 1225 | CONFIG_SPIFFS_OBJ_NAME_LEN=32 1226 | # CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set 1227 | CONFIG_SPIFFS_USE_MAGIC=y 1228 | CONFIG_SPIFFS_USE_MAGIC_LENGTH=y 1229 | CONFIG_SPIFFS_META_LENGTH=4 1230 | CONFIG_SPIFFS_USE_MTIME=y 1231 | 1232 | # 1233 | # Debug Configuration 1234 | # 1235 | # CONFIG_SPIFFS_DBG is not set 1236 | # CONFIG_SPIFFS_API_DBG is not set 1237 | # CONFIG_SPIFFS_GC_DBG is not set 1238 | # CONFIG_SPIFFS_CACHE_DBG is not set 1239 | # CONFIG_SPIFFS_CHECK_DBG is not set 1240 | # CONFIG_SPIFFS_TEST_VISUALISATION is not set 1241 | # end of Debug Configuration 1242 | # end of SPIFFS Configuration 1243 | 1244 | # 1245 | # TCP Transport 1246 | # 1247 | CONFIG_WS_BUFFER_SIZE=1024 1248 | # end of TCP Transport 1249 | 1250 | # 1251 | # Unity unit testing library 1252 | # 1253 | CONFIG_UNITY_ENABLE_FLOAT=y 1254 | CONFIG_UNITY_ENABLE_DOUBLE=y 1255 | # CONFIG_UNITY_ENABLE_64BIT is not set 1256 | # CONFIG_UNITY_ENABLE_COLOR is not set 1257 | CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y 1258 | # CONFIG_UNITY_ENABLE_FIXTURE is not set 1259 | # CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set 1260 | # end of Unity unit testing library 1261 | 1262 | # 1263 | # Virtual file system 1264 | # 1265 | CONFIG_VFS_SUPPORT_IO=y 1266 | CONFIG_VFS_SUPPORT_DIR=y 1267 | CONFIG_VFS_SUPPORT_SELECT=y 1268 | CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y 1269 | CONFIG_VFS_SUPPORT_TERMIOS=y 1270 | 1271 | # 1272 | # Host File System I/O (Semihosting) 1273 | # 1274 | CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 1275 | CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 1276 | # end of Host File System I/O (Semihosting) 1277 | # end of Virtual file system 1278 | 1279 | # 1280 | # Wear Levelling 1281 | # 1282 | # CONFIG_WL_SECTOR_SIZE_512 is not set 1283 | CONFIG_WL_SECTOR_SIZE_4096=y 1284 | CONFIG_WL_SECTOR_SIZE=4096 1285 | # end of Wear Levelling 1286 | 1287 | # 1288 | # Wi-Fi Provisioning Manager 1289 | # 1290 | CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 1291 | CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 1292 | # end of Wi-Fi Provisioning Manager 1293 | 1294 | # 1295 | # Supplicant 1296 | # 1297 | CONFIG_WPA_MBEDTLS_CRYPTO=y 1298 | # CONFIG_WPA_WAPI_PSK is not set 1299 | # CONFIG_WPA_DEBUG_PRINT is not set 1300 | # CONFIG_WPA_TESTING_OPTIONS is not set 1301 | # CONFIG_WPA_WPS_WARS is not set 1302 | # CONFIG_WPA_11KV_SUPPORT is not set 1303 | # end of Supplicant 1304 | # end of Component config 1305 | 1306 | # 1307 | # Compatibility options 1308 | # 1309 | # CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set 1310 | # end of Compatibility options 1311 | 1312 | # Deprecated options for backward compatibility 1313 | CONFIG_TOOLPREFIX="xtensa-esp32-elf-" 1314 | CONFIG_PYTHON="python" 1315 | CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y 1316 | # CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set 1317 | CONFIG_LOG_BOOTLOADER_LEVEL_ERROR=y 1318 | # CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set 1319 | # CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set 1320 | # CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set 1321 | # CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set 1322 | CONFIG_LOG_BOOTLOADER_LEVEL=1 1323 | # CONFIG_APP_ROLLBACK_ENABLE is not set 1324 | # CONFIG_FLASH_ENCRYPTION_ENABLED is not set 1325 | # CONFIG_FLASHMODE_QIO is not set 1326 | # CONFIG_FLASHMODE_QOUT is not set 1327 | CONFIG_FLASHMODE_DIO=y 1328 | # CONFIG_FLASHMODE_DOUT is not set 1329 | # CONFIG_MONITOR_BAUD_9600B is not set 1330 | # CONFIG_MONITOR_BAUD_57600B is not set 1331 | CONFIG_MONITOR_BAUD_115200B=y 1332 | # CONFIG_MONITOR_BAUD_230400B is not set 1333 | # CONFIG_MONITOR_BAUD_921600B is not set 1334 | # CONFIG_MONITOR_BAUD_2MB is not set 1335 | # CONFIG_MONITOR_BAUD_OTHER is not set 1336 | CONFIG_MONITOR_BAUD_OTHER_VAL=115200 1337 | CONFIG_MONITOR_BAUD=115200 1338 | CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y 1339 | # CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set 1340 | CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y 1341 | # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set 1342 | # CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set 1343 | # CONFIG_CXX_EXCEPTIONS is not set 1344 | CONFIG_STACK_CHECK_NONE=y 1345 | # CONFIG_STACK_CHECK_NORM is not set 1346 | # CONFIG_STACK_CHECK_STRONG is not set 1347 | # CONFIG_STACK_CHECK_ALL is not set 1348 | # CONFIG_WARN_WRITE_STRINGS is not set 1349 | # CONFIG_DISABLE_GCC8_WARNINGS is not set 1350 | # CONFIG_ESP32_APPTRACE_DEST_TRAX is not set 1351 | CONFIG_ESP32_APPTRACE_DEST_NONE=y 1352 | CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y 1353 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 1354 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 1355 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 1356 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 1357 | CONFIG_ADC2_DISABLE_DAC=y 1358 | CONFIG_SPIRAM_SUPPORT=y 1359 | # CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is not set 1360 | CONFIG_TRACEMEM_RESERVE_DRAM=0x0 1361 | # CONFIG_ULP_COPROC_ENABLED is not set 1362 | CONFIG_ULP_COPROC_RESERVE_MEM=0 1363 | CONFIG_BROWNOUT_DET=y 1364 | CONFIG_BROWNOUT_DET_LVL_SEL_0=y 1365 | # CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set 1366 | # CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set 1367 | # CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set 1368 | # CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set 1369 | # CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set 1370 | # CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set 1371 | # CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set 1372 | CONFIG_BROWNOUT_DET_LVL=0 1373 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y 1374 | # CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set 1375 | # CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set 1376 | # CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set 1377 | # CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set 1378 | # CONFIG_NO_BLOBS is not set 1379 | # CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set 1380 | # CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is not set 1381 | # CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is not set 1382 | # CONFIG_EVENT_LOOP_PROFILING is not set 1383 | CONFIG_POST_EVENTS_FROM_ISR=y 1384 | CONFIG_POST_EVENTS_FROM_IRAM_ISR=y 1385 | # CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set 1386 | CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y 1387 | CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 1388 | # CONFIG_ESP32S2_PANIC_PRINT_HALT is not set 1389 | CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y 1390 | # CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set 1391 | # CONFIG_ESP32S2_PANIC_GDBSTUB is not set 1392 | CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 1393 | CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 1394 | CONFIG_MAIN_TASK_STACK_SIZE=3584 1395 | CONFIG_CONSOLE_UART_DEFAULT=y 1396 | # CONFIG_CONSOLE_UART_CUSTOM is not set 1397 | # CONFIG_ESP_CONSOLE_UART_NONE is not set 1398 | CONFIG_CONSOLE_UART=y 1399 | CONFIG_CONSOLE_UART_NUM=0 1400 | CONFIG_CONSOLE_UART_BAUDRATE=115200 1401 | CONFIG_INT_WDT=y 1402 | CONFIG_INT_WDT_TIMEOUT_MS=300 1403 | CONFIG_INT_WDT_CHECK_CPU1=y 1404 | CONFIG_TASK_WDT=y 1405 | CONFIG_TASK_WDT_PANIC=y 1406 | CONFIG_TASK_WDT_TIMEOUT_S=5 1407 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y 1408 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y 1409 | CONFIG_IPC_TASK_STACK_SIZE=1024 1410 | CONFIG_TIMER_TASK_STACK_SIZE=3584 1411 | CONFIG_REDUCE_PHY_TX_POWER=y 1412 | # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set 1413 | # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set 1414 | CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y 1415 | CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 1416 | CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 1417 | CONFIG_MB_QUEUE_LENGTH=20 1418 | CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 1419 | CONFIG_MB_SERIAL_BUF_SIZE=256 1420 | CONFIG_MB_SERIAL_TASK_PRIO=10 1421 | # CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set 1422 | CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 1423 | CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 1424 | CONFIG_MB_CONTROLLER_STACK_SIZE=4096 1425 | CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 1426 | CONFIG_MB_TIMER_PORT_ENABLED=y 1427 | CONFIG_MB_TIMER_GROUP=0 1428 | CONFIG_MB_TIMER_INDEX=0 1429 | # CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set 1430 | CONFIG_TIMER_TASK_PRIORITY=1 1431 | CONFIG_TIMER_TASK_STACK_DEPTH=2048 1432 | CONFIG_TIMER_QUEUE_LENGTH=10 1433 | # CONFIG_L2_TO_L3_COPY is not set 1434 | # CONFIG_USE_ONLY_LWIP_SELECT is not set 1435 | CONFIG_ESP_GRATUITOUS_ARP=y 1436 | CONFIG_GARP_TMR_INTERVAL=60 1437 | CONFIG_TCPIP_RECVMBOX_SIZE=32 1438 | CONFIG_TCP_MAXRTX=12 1439 | CONFIG_TCP_SYNMAXRTX=6 1440 | CONFIG_TCP_MSS=1440 1441 | CONFIG_TCP_MSL=60000 1442 | CONFIG_TCP_SND_BUF_DEFAULT=5744 1443 | CONFIG_TCP_WND_DEFAULT=5744 1444 | CONFIG_TCP_RECVMBOX_SIZE=6 1445 | CONFIG_TCP_QUEUE_OOSEQ=y 1446 | # CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set 1447 | CONFIG_TCP_OVERSIZE_MSS=y 1448 | # CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set 1449 | # CONFIG_TCP_OVERSIZE_DISABLE is not set 1450 | CONFIG_UDP_RECVMBOX_SIZE=6 1451 | CONFIG_TCPIP_TASK_STACK_SIZE=3072 1452 | CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y 1453 | # CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set 1454 | # CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set 1455 | CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF 1456 | # CONFIG_PPP_SUPPORT is not set 1457 | CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 1458 | CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 1459 | CONFIG_ESP32_PTHREAD_STACK_MIN=768 1460 | CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y 1461 | # CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set 1462 | # CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set 1463 | CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 1464 | CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" 1465 | # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS is not set 1466 | # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set 1467 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED=y 1468 | CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y 1469 | CONFIG_SUPPORT_TERMIOS=y 1470 | CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 1471 | CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 1472 | # End of deprecated options 1473 | --------------------------------------------------------------------------------