From dffc3ff9df0f704357fe43ca60535ac936481f49 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 18 Sep 2022 15:50:57 -0700 Subject: [PATCH 01/97] Missed in update doc change. --- address_info.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/address_info.txt b/address_info.txt index 29f7cf37..5cce8a38 100644 --- a/address_info.txt +++ b/address_info.txt @@ -2,4 +2,4 @@ bootloader.bin : 0x1000 partitions.bin : 0x8000 ota_data_initial.bin : 0xd000 spiffs.bin : 0x11000 -alarmdecoder_ad2iot_esp32.bin : 0x60000 \ No newline at end of file +alarmdecoder_ad2iot_esp32.bin : 0x80000 \ No newline at end of file From 9b336e610447e58ba45556cdc9a46d4e3b1fb10a Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Mon, 14 Nov 2022 23:32:40 -0800 Subject: [PATCH 02/97] Prep for release of 1.1.1 P1. Fixes problem in twilio reporting and improves logging and data validation. Some fixes to default ad2iot.ini --- CHANGELOG.md | 11 ++++++++ components/twilio/twilio.cpp | 54 ++++++++++++++++++++++++++---------- data/ad2iot.ini | 24 ++++++++++------ sdkconfig.defaults | 1 + 4 files changed, 68 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 017d07c3..d228a17e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). --- ## Releases +## [1.1.1 P1] - 2022-11-14 Sean Mathews - coder @f34rdotcom +Changes: + - Fix missing compile flag with new espidf that caused auth failure with twilio. + - Add new? lost switch ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH. + - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. + - TODO: Find more time to audit and cleanup code. + - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. +### Change log + - [X] SM CORE: Fix missing compile flag ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH + - [X] SM TWILIO: Improve error handling and response data validation. + - [X] SM CORE: Small changes to default ad2iot.ini to fix a few switch numbers and add testing for all default switches in components. ## [1.1.1] - 2022-09-18 Sean Mathews - coder @f34rdotcom Changes: - Partition change add new coredump partition. diff --git a/components/twilio/twilio.cpp b/components/twilio/twilio.cpp index 65019f5f..75f2abe5 100644 --- a/components/twilio/twilio.cpp +++ b/components/twilio/twilio.cpp @@ -333,38 +333,64 @@ static bool _sendQ_done_handler(esp_err_t res, esp_http_client_handle_t client, #endif // parse some data from json response if one exists. - std::string jsonStatus; - std::string jsonMessage; + std::string szStatus; + std::string szMessage; std::string notify_url; cJSON * root = cJSON_Parse(r->results.c_str()); if (root) { + // check for exceptions and report + // https://www.twilio.com/docs/usage/twilios-response#response-formats-exceptions + cJSON * code = cJSON_GetObjectItem(root, "code"); + if (code) { + ESP_LOGI(TAG,"parse exception code json"); + szStatus = "Exception"; + int ret_code = code->valueint; + + std::string ret_message; + cJSON * jso_message = cJSON_GetObjectItem(root, "message"); + if (jso_message && jso_message->valuestring) { + ret_message = jso_message->valuestring; + } + + std::string ret_more_info; + cJSON * jso_more_info = cJSON_GetObjectItem(root, "more_info"); + if (jso_more_info && jso_more_info->valuestring) { + ret_more_info = jso_more_info->valuestring; + } + + int ret_status = -1; + cJSON * jso_status = cJSON_GetObjectItem(root, "status"); + if (jso_status) { + ret_status = jso_status->valueint; + } + + szMessage = ad2_string_printf("code: %i, message: '%s', more_info: '%s', status: %i", + ret_code, ret_message.c_str(), ret_more_info.c_str(), ret_status); + } // If the request contains a subresource_uris and Notifications.json then request it next else we are done. cJSON * subr_uris = cJSON_GetObjectItem(root, "subresource_uris"); if (subr_uris) { + ESP_LOGI(TAG,"parse subresource_uris json"); + szStatus = "subresource_uris"; // { "subresource_uris" : { "notifications" : "FOO", ...}} cJSON * notifications_url = cJSON_GetObjectItem(subr_uris, "notifications"); - if (notifications_url) { - notify_url = cJSON_GetStringValue(notifications_url); + if (notifications_url && notifications_url->valuestring) { + notify_url = notifications_url->valuestring; } } - // json status - cJSON * status = cJSON_GetObjectItem(root, "status"); - if (status) { - jsonStatus = cJSON_GetStringValue(status); - } - // json error cJSON * errors = cJSON_GetObjectItem(root, "errors"); if (errors) { - jsonStatus = "error"; + ESP_LOGI(TAG,"parse error json"); + szStatus = "error"; cJSON * error = cJSON_GetArrayItem(errors, 0); if (error) { cJSON * message = cJSON_GetObjectItem(error, "message"); - if (message) { - jsonMessage = cJSON_GetStringValue(message); + if (message && message->valuestring) { + szMessage = message->valuestring; } } } @@ -372,7 +398,7 @@ static bool _sendQ_done_handler(esp_err_t res, esp_http_client_handle_t client, cJSON_Delete(root); } - ESP_LOGI(TAG,"Notify slot #%i response code: '%i' status: '%s' message: '%s'", r->notify_slot, esp_http_client_get_status_code(client), jsonStatus.c_str(), jsonMessage.c_str()); + ESP_LOGI(TAG,"Notify slot #%i response code: '%i' status: '%s' message: '%s'", r->notify_slot, esp_http_client_get_status_code(client), szStatus.c_str(), szMessage.c_str()); // If first request was OK and we are scheduled to make GET for details. if (res == ESP_OK && r->state == TWILIO_NEXT_STATE_GET) { diff --git a/data/ad2iot.ini b/data/ad2iot.ini index 9fbcdc21..4e551f94 100644 --- a/data/ad2iot.ini +++ b/data/ad2iot.ini @@ -420,6 +420,10 @@ switch 60 open = SWITCH 1 OPEN switch 60 close = SWITCH 1 CLOSE switch 60 trouble = SWITCH 1 TROUBLE +switch 91 notify = 1 +switch 91 open = ON MAIN AC POWER +switch 91 close = ON BATTERY BACKUP POWER + switch 95 notify = 1 switch 95 open = FIRE ON switch 95 close = FIRE OFF @@ -429,6 +433,10 @@ switch 99 notify = 1 switch 99 open = ALARM ACTIVE switch 99 close = ALARM CLEAR +switch 100 notify = 1 +switch 100 open = ARMED +switch 100 close = DISARMED + switch 103 notify = 1 switch 103 open = ARMED USER 3 switch 103 close = DISARMED USER 3 @@ -495,6 +503,11 @@ format 3 = <<{0}{0} END_OF_TEXT +# Notify POWER STATUS EMail+SMS +switch 91 notify = 1,2 +switch 91 open = ON MAIN AC POWER +switch 91 close = ON BATTERY BACKUP POWER + # Notify SOS Call, SMS, EMail EVERYONE! switch 95 notify = 1,2,3 switch 95 open = FIRE ALARM @@ -505,17 +518,12 @@ switch 99 notify = 1,2,3 switch 99 open = ALARM ACTIVE switch 99 close = ALARM CLEAR -# Notify POWER STATUS EMail+SMS -switch 2 notify = 1,2 -switch 2 open = ON MAIN AC POWER -switch 2 close = ON BATTERY BACKUP POWER - # Notify generic ARMED/DISARMED switch 100 notify = 1,2 switch 100 open = ALARM ARMED switch 100 close = ALARM DISARMED # Notify ARM/DISARM USER #3 on LRR/CID report but not both. -#switch 103 notify = 1,2 -#switch 103 open = ARMED USER 3 -#switch 103 close = DISARMED USER 3 +switch 103 notify = 1,2 +switch 103 open = ARMED USER 3 +switch 103 close = DISARMED USER 3 diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 00f7f015..a5bf1939 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -54,6 +54,7 @@ CONFIG_MQTT_MSG_ID_INCREMENTAL=y CONFIG_MQTT_CUSTOM_OUTBOX=y CONFIG_ESP_HTTPS_SERVER_ENABLE=y CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y CONFIG_HTTPD_WS_SUPPORT=y CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y From 23ac142be3b040c5b3175b49f002f8a567a20b6c Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 00:00:22 -0800 Subject: [PATCH 03/97] Fix version on last release was actually P1 this is P2 for 1.1.0. --- CHANGELOG.md | 2 +- main/ad2_settings.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d228a17e..473cdd51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). --- ## Releases -## [1.1.1 P1] - 2022-11-14 Sean Mathews - coder @f34rdotcom +## [1.1.2] - 2022-11-14 Sean Mathews - coder @f34rdotcom Changes: - Fix missing compile flag with new espidf that caused auth failure with twilio. - Add new? lost switch ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH. diff --git a/main/ad2_settings.h b/main/ad2_settings.h index 7bba53eb..b85d7cc1 100644 --- a/main/ad2_settings.h +++ b/main/ad2_settings.h @@ -24,7 +24,7 @@ //#define AD2_STACK_REPORT // @brief Firmware version string. -#define FIRMWARE_VERSION "AD2IOT-1101" +#define FIRMWARE_VERSION "AD2IOT-1102" #if defined(CONFIG_STDK_IOT_CORE) #define FIRMWARE_BUILDFLAGS "stsdk" From bb694f8c584b7e3ad722c8ae18ccd06779adab66 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 20:40:16 -0800 Subject: [PATCH 04/97] Some cleanup work as I work on final release testing. --- CHANGELOG.md | 18 ++--- components/twilio/twilio.cpp | 2 +- sdkconfig.defaults | 127 +++++++++++++++++++++++------------ 3 files changed, 93 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 473cdd51..a4353130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,24 +6,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] Open issues ### SM - Sean Mathews coder at f34r.com +- [ ] API: Add countdown tracking for DSC/Ademco exit mode - [ ] CORE: Needed feature ad2_fw_update() to update AD2* firmware. - [ ] CORE: TODO: Monitor limited sockets look for ways to reduce if possible. - [ ] CORE: Push includes down to lower level. main include has too many component specific includes. -- [ ] TWILIO & PUSHOVER: Add virtual partition qualifier to virtual switch command. Currently on the Twilio notification is hard coded to the default virtual partition in slot 0. The Pushover notification currently has no qualifier and sends messages regardless of the partition as long as it matches. Merge these into a single pattern allowing for the user to define it by its ```vpart``` id. - [ ] CORE: Audit Espressif v3.2 api usage look for more that are soon to be deprecated. -- [ ] STSDK: TODO. FIX Ability to build stsdk component inside of pio build environment. Currently only possible to build with STSDK build.py script. - [ ] CORE: FIXME: Setting HOST NAME when using static IP over ethernet not working. - [ ] CORE: FIXME: reboot of esp32 causes connected ser2sock clients to hang. So far various attempts to fix have been unsuccessful. Will need to do some network captures to determine the problem. - [ ] CORE: HUP/RESTART needs to be centralized so cleanup ex(_fifo_destroy) can happen first. How to connect with STSDK having its own restart calls. -- [ ] STSDK: TODO: Find way to set IOT_PUB_QUEUE_LENGTH & IOT_QUEUE_LENGTH from 10 to 20 during build. - [ ] CORE: Noted coredump when doing oil change check and a twilio message goes out. Both are mbedtls web requests. Will need to investigate and possibly serialize web requests. -- [ ] API: Add countdown tracking for DSC/Ademco exit mode - [ ] CORE: Improve: Finish wiring Virtual Switch A & B and Button A & B. -- [ ] STSDK: Improve: Connect Component OutputA & OutputB with switch capabilities tied to hal_ - [ ] CORE: Wishlist: Compile for bare metal BeagleBone Black and Raspberry Pi. https://forums.freertos.org/t/freertos-porting-to-raspberry-pi-3/6686/5. Alternatively run inside an ESP32 Virtual machine on a Pi? - [ ] CORE: TODO: better hardware abstraction. Need to remove _esp_ specific code to make it easier to port to other hardware. Trying to keep the code as POSIX as possible with the limited resources I have. - [ ] CORE: TODO: ```'ping'``` command could come in handy. Again today needed this with ST MQTT servers seeming to be down. +- [ ] STSDK: TODO. FIX Ability to build stsdk component inside of pio build environment. Currently only possible to build with STSDK build.py script. +- [ ] STSDK: Improve: Connect Component OutputA & OutputB with switch capabilities tied to hal_ - [ ] STSDK: TODO: Add SmartThings Zone devices. +- [ ] STSDK: TODO: Find way to set IOT_PUB_QUEUE_LENGTH & IOT_QUEUE_LENGTH from 10 to 20 during build. +- [ ] TWILIO & PUSHOVER: Add virtual partition qualifier to virtual switch command. Currently on the Twilio notification is hard coded to the default virtual partition in slot 0. The Pushover notification currently has no qualifier and sends messages regardless of the partition as long as it matches. Merge these into a single pattern allowing for the user to define it by its ```vpart``` id. - [ ] webUI: Add REST api compatible with the current webapp including a secret key. This is low priority as this method of connection is not very efficient. ### AJ @@ -33,18 +33,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/). --- ## Releases -## [1.1.2] - 2022-11-14 Sean Mathews - coder @f34rdotcom +## [1.1.0 P2] - 2022-11-14 Sean Mathews - coder @f34rdotcom Changes: - - Fix missing compile flag with new espidf that caused auth failure with twilio. - - Add new? lost switch ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH. + - Fix missing settings and organized sdkconfig.defaults. - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. - TODO: Find more time to audit and cleanup code. - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. ### Change log + - [X] SM CORE: Fix sdkconfig.defaults was missing critical bits. Better organized now and "should" build same exact same firmware as in release. - [X] SM CORE: Fix missing compile flag ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH - [X] SM TWILIO: Improve error handling and response data validation. - [X] SM CORE: Small changes to default ad2iot.ini to fix a few switch numbers and add testing for all default switches in components. -## [1.1.1] - 2022-09-18 Sean Mathews - coder @f34rdotcom +## [1.1.0 P1] - 2022-09-18 Sean Mathews - coder @f34rdotcom Changes: - Partition change add new coredump partition. - This change will require manual flash OTA will not work. Hopefully this is the last partition change. diff --git a/components/twilio/twilio.cpp b/components/twilio/twilio.cpp index 75f2abe5..b41649a4 100644 --- a/components/twilio/twilio.cpp +++ b/components/twilio/twilio.cpp @@ -366,7 +366,7 @@ static bool _sendQ_done_handler(esp_err_t res, esp_http_client_handle_t client, } szMessage = ad2_string_printf("code: %i, message: '%s', more_info: '%s', status: %i", - ret_code, ret_message.c_str(), ret_more_info.c_str(), ret_status); + ret_code, ret_message.c_str(), ret_more_info.c_str(), ret_status); } // If the request contains a subresource_uris and Notifications.json then request it next else we are done. diff --git a/sdkconfig.defaults b/sdkconfig.defaults index a5bf1939..47bcded4 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -1,18 +1,50 @@ -# GENERAL -CONFIG_FREERTOS_UNICORE=y +# Compiler settings +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 CONFIG_OPTIMIZATION_LEVEL_RELEASE=y + +# FreeRTOS settings +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_ISR_STACKSIZE=2048 +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y + +# General settings +CONFIG_LOG_COLORS=n CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y CONFIG_BOOTLOADER_LOG_LEVEL=0 + +# Hardware specific settings +CONFIG_ESP_INT_WDT_TIMEOUT_MS=3000 +## ESP32-WROOM-32E CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_BOOTLOADER_SPI_WP_PIN=7 CONFIG_ESPTOOLPY_FLASHSIZE="4MB" CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +## ESP32-POE-ISO ETHERNET config +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +CONFIG_ETH_RMII_CLK_OUT_GPIO=17 +CONFIG_ETH_RMII_CLK_OUTPUT=y +CONFIG_AD2IOT_ETH_PHY_LAN8720=y +CONFIG_AD2IOT_ETH_MDC_GPIO=23 +CONFIG_AD2IOT_ETH_MDIO_GPIO=18 +CONFIG_AD2IOT_ETH_PHY_RST_GPIO=-1 +CONFIG_AD2IOT_ETH_PHY_POWER_GPIO=12 +CONFIG_AD2IOT_ETH_PHY_ADDR=0 + +# Partition settings CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.4MB.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.4MB.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y -# CONFIG_FATFS_LFN_NONE is not set + +# FATFS settings CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_CODEPAGE_437=y CONFIG_FATFS_CODEPAGE=437 @@ -22,62 +54,69 @@ CONFIG_FATFS_API_ENCODING_ANSI_OEM=y CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE=y -CONFIG_FREERTOS_USE_TRACE_FACILITY=y -CONFIG_COMPILER_CXX_EXCEPTIONS=y -CONFIG_CXX_EXCEPTIONS=y -CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -# ESP32-POE-ISO ETHERNET -CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ETH_PHY_INTERFACE_RMII=y -CONFIG_ETH_RMII_CLK_OUT_GPIO=17 -CONFIG_ETH_RMII_CLK_OUTPUT=y -CONFIG_AD2IOT_ETH_PHY_LAN8720=y -CONFIG_AD2IOT_ETH_MDC_GPIO=23 -CONFIG_AD2IOT_ETH_MDIO_GPIO=18 -CONFIG_AD2IOT_ETH_PHY_RST_GPIO=-1 -CONFIG_AD2IOT_ETH_PHY_POWER_GPIO=12 -CONFIG_AD2IOT_ETH_PHY_ADDR=0 +# Coredump settings +CONFIG_ESP_COREDUMP_ENABLE=y +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y +CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP_COREDUMP_CHECKSUM_CRC32=y +CONFIG_ESP_COREDUMP_CHECK_BOOT=y +CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=20 -# DEFAULT COMPONENTS & SETTINGS +# LWIP settings CONFIG_LWIP_LOCAL_HOSTNAME="ad2iot" +CONFIG_LWIP_IPV6_AUTOCONFIG=y CONFIG_LWIP_MAX_SOCKETS=16 -CONFIG_AD2IOT_USE_WIFI=y -CONFIG_AD2IOT_USE_ETHERNET=y -CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y -CONFIG_MQTT_REPORT_DELETED_MESSAGES=y + +# MQTT client settings CONFIG_MQTT_PROTOCOL_311=y CONFIG_MQTT_TRANSPORT_SSL=y CONFIG_MQTT_TRANSPORT_WEBSOCKET=y CONFIG_MQTT_MSG_ID_INCREMENTAL=y -CONFIG_MQTT_CUSTOM_OUTBOX=y +CONFIG_MQTT_REPORT_DELETED_MESSAGES=y + +# HTTP(s) / WebSockets server CONFIG_ESP_HTTPS_SERVER_ENABLE=y CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y CONFIG_HTTPD_WS_SUPPORT=y +## TODO: Make better... +CONFIG_ESP_TLS_INSECURE=y +CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y + +# SSL/TLS certificate bundles CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" -CONFIG_STDK_IOT_CORE=y -CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y + +# STSDK build settings +#CONFIG_STDK_IOT_CORE=y +#CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +#CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y +#CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y +#CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set -CONFIG_STDK_IOT_CORE_LOG_FILE=y -CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y -CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 -CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y -CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y -CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y -CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y -CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y -CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y -CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y +#CONFIG_STDK_IOT_CORE_LOG_FILE=y +#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y +#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 +#CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y +#CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y +#CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y +#CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y +#CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y +#CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y +#CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y + +# AD2IoT network settings +CONFIG_AD2IOT_USE_WIFI=y +CONFIG_AD2IOT_USE_ETHERNET=y +CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y + +# AD2IoT default components enable/disable CONFIG_AD2IOT_TOP=y -CONFIG_AD2IOT_TWILIO_CLIENT=y -CONFIG_AD2IOT_PUSHOVER_CLIENT=y -CONFIG_AD2IOT_SER2SOCKD=y -CONFIG_AD2IOT_WEBSERVER_UI=y +CONFIG_AD2IOT_FTP_DAEMON=y CONFIG_AD2IOT_MQTT_CLIENT=y +CONFIG_AD2IOT_WEBSERVER_UI=y +CONFIG_AD2IOT_SER2SOCKD=y +CONFIG_AD2IOT_TWILIO_CLIENT=y +CONFIG_AD2IOT_PUSHOVER_CLIENT=y \ No newline at end of file From 237ff841acefe4e1460bb1e8226b9c9625dbea05 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 21:16:01 -0800 Subject: [PATCH 05/97] Testing having PIO build the project in travis. --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index afe8ed51..9ea3ce17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ dist: xenial -sudo: required +sudo: false language: python python: - - "nightly" + - "3.9" os: - linux @@ -14,6 +14,7 @@ cache: directories: - "~/.platformio" - $HOME/astyle + - $HOME/.cache/pip install: - pip install -U platformio @@ -35,7 +36,7 @@ script: echo "Please fix style issues as shown above" exit 1 fi - + - pio run -e esp32-poe-iso notifications: email: on_success: change From e9908260f9948b3b0ccbfd45a0b5d023b45a22ac Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 21:23:19 -0800 Subject: [PATCH 06/97] ... --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9ea3ce17..f64e4225 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: false language: python python: - - "3.9" + - "3.9.2" os: - linux From ca6374bacdd8764af9638f97e8138a7921319dfe Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 21:25:34 -0800 Subject: [PATCH 07/97] ... --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f64e4225..098f36a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: false language: python python: - - "3.9.2" + - "nightly" os: - linux From be75daa0b73249e50838bb075110dc8dfb23ebeb Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 22:07:54 -0800 Subject: [PATCH 08/97] ... --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 098f36a9..7af30a9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ -dist: xenial +dist: focal sudo: false language: python python: - - "nightly" + - "3.10.2" os: - linux From 16bdbf4651971207a6320ca5c84fd91e071513f9 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Tue, 15 Nov 2022 22:16:15 -0800 Subject: [PATCH 09/97] done. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4353130..3564ba69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,11 +35,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Releases ## [1.1.0 P2] - 2022-11-14 Sean Mathews - coder @f34rdotcom Changes: + - Add Travis platformio build test. - Fix missing settings and organized sdkconfig.defaults. - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. - TODO: Find more time to audit and cleanup code. - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. ### Change log + - [X] SM CORE: Travis build platform io project test. - [X] SM CORE: Fix sdkconfig.defaults was missing critical bits. Better organized now and "should" build same exact same firmware as in release. - [X] SM CORE: Fix missing compile flag ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH - [X] SM TWILIO: Improve error handling and response data validation. From 6fe2313d02d4fdb84080bd026dfc635a3546bc1b Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 29 Dec 2022 17:15:58 -0800 Subject: [PATCH 10/97] P3: Fixing STSDK. Building seems to work needs more testing and ftpd is broken :( --- CHANGELOG.md | 8 + components/stsdk/caps_battery.h | 8 +- components/stsdk/caps_button.h | 7 + .../stsdk/caps_carbonMonoxideDetector.h | 7 + components/stsdk/caps_contactSensor.h | 7 + components/stsdk/caps_momentary.h | 7 + components/stsdk/caps_powerSource.h | 7 + components/stsdk/caps_refresh.h | 7 + components/stsdk/caps_securitySystem.h | 7 + components/stsdk/caps_smokeDetector.h | 7 + components/stsdk/caps_switch.h | 7 + components/stsdk/caps_tamperAlert.h | 7 + components/stsdk/stsdk_main.cpp | 330 ++++++++++-------- components/stsdk/stsdk_main.h | 23 +- main/CMakeLists.txt | 7 + 15 files changed, 282 insertions(+), 164 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3564ba69..3b388c18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). --- ## Releases +## [1.1.0 P3] - 2022-12-__ Sean Mathews - coder @f34rdotcom +Changes: + - Get STSDK building again. +### Change log + - [X] SM CORE: Add fixes for stsdk code that I have been sitting on. Mostly just CDECL stuff. + - [X] SM CORE: Fix CMakeList.txt to fetch SimpleIni from github and include it for stsdk building. + - [ ] SM FTPD: Does not build with stsdk. + - [ ] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. ## [1.1.0 P2] - 2022-11-14 Sean Mathews - coder @f34rdotcom Changes: - Add Travis platformio build test. diff --git a/components/stsdk/caps_battery.h b/components/stsdk/caps_battery.h index 36f3fd2b..d252e6b7 100644 --- a/components/stsdk/caps_battery.h +++ b/components/stsdk/caps_battery.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_battery.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_battery_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -36,4 +40,6 @@ typedef struct caps_battery_data { } caps_battery_data_t; caps_battery_data_t *caps_battery_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); - +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_button.h b/components/stsdk/caps_button.h index bbae7062..6b345220 100644 --- a/components/stsdk/caps_button.h +++ b/components/stsdk/caps_button.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_button.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_button_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -43,3 +47,6 @@ typedef struct caps_button_data { } caps_button_data_t; caps_button_data_t *caps_button_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_carbonMonoxideDetector.h b/components/stsdk/caps_carbonMonoxideDetector.h index 03ef2b54..9914a107 100644 --- a/components/stsdk/caps_carbonMonoxideDetector.h +++ b/components/stsdk/caps_carbonMonoxideDetector.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_carbonMonoxideDetector.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_carbonMonoxideDetector_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -34,3 +38,6 @@ typedef struct caps_carbonMonoxideDetector_data { } caps_carbonMonoxideDetector_data_t; caps_carbonMonoxideDetector_data_t *caps_carbonMonoxideDetector_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_contactSensor.h b/components/stsdk/caps_contactSensor.h index 51dcd919..877bf8fb 100644 --- a/components/stsdk/caps_contactSensor.h +++ b/components/stsdk/caps_contactSensor.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_contactSensor.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_contactSensor_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -34,3 +38,6 @@ typedef struct caps_contactSensor_data { } caps_contactSensor_data_t; caps_contactSensor_data_t *caps_contactSensor_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_momentary.h b/components/stsdk/caps_momentary.h index bc553ea4..5606daa1 100644 --- a/components/stsdk/caps_momentary.h +++ b/components/stsdk/caps_momentary.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_momentary.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_momentary_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -31,3 +35,6 @@ typedef struct caps_momentary_data { } caps_momentary_data_t; caps_momentary_data_t *caps_momentary_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_powerSource.h b/components/stsdk/caps_powerSource.h index 4011aabe..8d283a5b 100644 --- a/components/stsdk/caps_powerSource.h +++ b/components/stsdk/caps_powerSource.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_powerSource.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_powerSource_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -34,3 +38,6 @@ typedef struct caps_powerSource_data { } caps_powerSource_data_t; caps_powerSource_data_t *caps_powerSource_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_refresh.h b/components/stsdk/caps_refresh.h index 08025cd3..0a3eca3c 100644 --- a/components/stsdk/caps_refresh.h +++ b/components/stsdk/caps_refresh.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_refresh.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_refresh_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -31,3 +35,6 @@ typedef struct caps_refresh_data { } caps_refresh_data_t; caps_refresh_data_t *caps_refresh_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_securitySystem.h b/components/stsdk/caps_securitySystem.h index b99c6784..a9d2697c 100644 --- a/components/stsdk/caps_securitySystem.h +++ b/components/stsdk/caps_securitySystem.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_securitySystem.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_securitySystem_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -42,3 +46,6 @@ typedef struct caps_securitySystem_data { } caps_securitySystem_data_t; caps_securitySystem_data_t *caps_securitySystem_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_smokeDetector.h b/components/stsdk/caps_smokeDetector.h index 83b130e6..5b141004 100644 --- a/components/stsdk/caps_smokeDetector.h +++ b/components/stsdk/caps_smokeDetector.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_smokeDetector.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_smokeDetector_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -34,3 +38,6 @@ typedef struct caps_smokeDetector_data { } caps_smokeDetector_data_t; caps_smokeDetector_data_t *caps_smokeDetector_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/caps_switch.h b/components/stsdk/caps_switch.h index 6454c5d2..19b71b19 100644 --- a/components/stsdk/caps_switch.h +++ b/components/stsdk/caps_switch.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_switch.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_switch_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -37,3 +41,6 @@ typedef struct caps_switch_data { } caps_switch_data_t; caps_switch_data_t *caps_switch_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/components/stsdk/caps_tamperAlert.h b/components/stsdk/caps_tamperAlert.h index 92341fa3..daddf00a 100644 --- a/components/stsdk/caps_tamperAlert.h +++ b/components/stsdk/caps_tamperAlert.h @@ -18,6 +18,10 @@ #include "caps/iot_caps_helper_tamperAlert.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct caps_tamperAlert_data { IOT_CAP_HANDLE* handle; void *usr_data; @@ -34,3 +38,6 @@ typedef struct caps_tamperAlert_data { } caps_tamperAlert_data_t; caps_tamperAlert_data_t *caps_tamperAlert_initialize(IOT_CTX *ctx, const char *component, void *init_usr_cb, void *usr_data); +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/components/stsdk/stsdk_main.cpp b/components/stsdk/stsdk_main.cpp index 616a5898..04e030a1 100644 --- a/components/stsdk/stsdk_main.cpp +++ b/components/stsdk/stsdk_main.cpp @@ -45,6 +45,10 @@ static const char *TAG = "STSDK"; #include "stsdk_main.h" #include "ota_util.h" +#ifdef __cplusplus +extern "C" { +#endif + // @brief global ST status tracking iot_status_t g_iot_status = IOT_STATUS_IDLE; @@ -82,6 +86,22 @@ caps_powerSource_data_t *cap_powerSource_data; // @brief Battery [% int 0 - 100] caps_battery_data_t *cap_battery_data; +char * STSDK_SUBCMD [] = { + (char*)STSDK_SUBCMD_ENABLE, + (char*)STSDK_SUBCMD_CLEANUP, + (char*)STSDK_SUBCMD_SERIAL, + (char*)STSDK_SUBCMD_PUBKEY, + (char*)STSDK_SUBCMD_PRIVKEY, + 0 // EOF +}; + +enum { + STSDK_SUBCMD_ENABLE_ID = 0, + STSDK_SUBCMD_CLEANUP_ID, + STSDK_SUBCMD_SERIAL_ID, + STSDK_SUBCMD_PUBKEY_ID, + STSDK_SUBCMD_PRIVKEY_ID +}; /** * @brief component: chime @@ -184,175 +204,174 @@ caps_momentary_data_t *cap_momentary_data_disarm; /** - * Enable/Disable STSDK component. - */ -static void _cli_cmd_enable_event(char *string) -{ - ESP_LOGI(TAG, "%s: enable/disable STSDK", __func__); - std::string arg; - if (ad2_copy_nth_arg(arg, string, 1) >= 0) { - ad2_set_config_key_bool(STSDK_ENABLE, nullptr, (arg[0] == 'Y' || arg[0] == 'y')); - ad2_printf_host(false, "Success setting value. Restart required to take effect.\r\n"); - } - - // show contents of this slot - bool en = false; - ad2_get_config_key_bool(STSDK_ENABLE, nullptr, &en); - ad2_printf_host(false, "SmartThings SDK driver is '%s'.\r\n", (en ? "Enabled" : "Disabled")); - -} - -/** - * Forget all STSDK state revert back to adoption mode. - */ -static void _cli_cmd_cleanup_event(char *string) -{ - ESP_LOGI(TAG, "%s: clean-up data with restart option", __func__); - ad2_printf_host(false, "Calling clean-up for STSDK settings.\r\n"); - st_conn_cleanup(ctx, true); -} - -/** - * Configure the AD2IoT SmartThings device_info.json - * field stored in NV - * - * command: stserial + * @brief SmartThings generic command event processing + * command: [COMMAND] * ex. - * stserial AaBbCcDdEeFf... + * [COMMAND] 0 arg... */ -static void _cli_cmd_stserial_event(char *string) +static void _cli_cmd_stsdk_event(const char *string) { - std::string arg; - if (ad2_copy_nth_arg(arg, string, 1) >= 0) { - nvs_handle my_handle; - esp_err_t err; - err = nvs_open_from_partition("stnv", "stdk", NVS_READWRITE, &my_handle); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_open_from_partition err %d", __func__, err); - } - err = nvs_set_str(my_handle, "SerialNum", arg.c_str()); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_set_str err %d", __func__, err); - ad2_printf_host(false, "Failed setting value.\r\n"); - } else { - ad2_printf_host(false, "Success setting value. Restart required to take effect.\r\n"); - } - err = nvs_commit(my_handle); - nvs_close(my_handle); - } else { - ad2_printf_host(false, "Missing \r\n"); - } -} -/** - * Configure the AD2IoT SmartThings device_info.json - * field stored in NV - * - * command: stpublickey - * ex. - * stpublickey AaBbCcDdEeFf... - */ -static void _cli_cmd_stpublickey_event(char *string) -{ - std::string arg; - if (ad2_copy_nth_arg(arg, string, 1) >= 0) { - nvs_handle my_handle; - esp_err_t err; - err = nvs_open_from_partition("stnv", "stdk", NVS_READWRITE, &my_handle); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_open_from_partition err %d", __func__, err); - } - err = nvs_set_str(my_handle, "PublicKey", arg.c_str()); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_set_str err %d", __func__, err); - ad2_printf_host(false, "Failed setting value.\r\n"); - } else { - ad2_printf_host(false, "Success setting value. Restart required to take effect.\r\n"); - } - err = nvs_commit(my_handle); - nvs_close(my_handle); - } else { - ad2_printf_host(false, "Missing \r\n"); + // key value validation + std::string cmd; + ad2_copy_nth_arg(cmd, string, 0); + ad2_lcase(cmd); + + if(cmd.compare(STSDK_COMMAND) != 0) { + ad2_printf_host(false, "What?\r\n"); + return;; } -} -/** - * Configure the AD2IoT SmartThings device_info.json - * field stored in NV - * - * command: stprivatekey - * ex. - * stprivatekey AaBbCcDdEeFf... - */ -static void _cli_cmd_stprivatekey_event(char *string) -{ - std::string arg; - if (ad2_copy_nth_arg(arg, string, 1) >= 0) { - nvs_handle my_handle; - esp_err_t err; - err = nvs_open_from_partition("stnv", "stdk", NVS_READWRITE, &my_handle); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_open_from_partition err %d", __func__, err); + // key value validation + std::string subcmd; + ad2_copy_nth_arg(subcmd, string, 1); + ad2_lcase(subcmd); + + int i; + bool en; + for(i = 0;; ++i) { + if (STSDK_SUBCMD[i] == 0) { + ad2_printf_host(false, "What?\r\n"); + break; } - err = nvs_set_str(my_handle, "PrivateKey", arg.c_str()); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_set_str err %d", __func__, err); - ad2_printf_host(false, "Failed setting value.\r\n"); - } else { - ad2_printf_host(false, "Success setting value. Restart required to take effect.\r\n"); + if(subcmd.compare(STSDK_SUBCMD[i]) == 0) { + std::string arg; + std::string key; + switch(i) { + /** + * Enable/Disable STSDK client. + */ + case STSDK_SUBCMD_ENABLE_ID: + if (ad2_copy_nth_arg(arg, string, 2) >= 0) { + ad2_set_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, (arg[0] == 'Y' || arg[0] == 'y')); + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); + } + + // show contents of this slot + en = false; + ad2_get_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, &en); + ad2_printf_host(true, "SmartThings Direct Connected Devices SDK client is '%s'.\r\n", (en ? "Enabled" : "Disabled")); + break; + /** + * Forget all STSDK state revert back to adoption mode. + */ + case STSDK_SUBCMD_CLEANUP_ID: + ESP_LOGI(TAG, "%s: clean-up data with restart option", __func__); + ad2_printf_host(true, "Calling clean-up for STSDK settings.\r\n"); + st_conn_cleanup(ctx, true); + break; + /** + * SmartThings Serial. + */ + case STSDK_SUBCMD_SERIAL_ID: + // arg found save to nvs + if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { + // save to the stnv nvs partition + nvs_handle my_handle; + esp_err_t err; + err = nvs_open_from_partition("nvs", "stdk", NVS_READWRITE, &my_handle); + if ( err != ESP_OK) { + ESP_LOGE(TAG, "%s: nvs_open_from_partition err: %s", __func__, esp_err_to_name(err)); + } + err = nvs_set_str(my_handle, "SerialNum", arg.c_str()); + if ( err != ESP_OK) { + ESP_LOGE(TAG, "%s: nvs_set_str err: %s", __func__, esp_err_to_name(err)); + ad2_printf_host(true, "Failed setting value.\r\n"); + } else { + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); + } + err = nvs_commit(my_handle); + nvs_close(my_handle); + break; + } + // If no arg then return current show contents of this slot + ad2_printf_host(true, "SmartThings 'serial' arg missing.\r\n"); + break; + /** + * SmartThings PrivateKey. + */ + case STSDK_SUBCMD_PRIVKEY_ID: + // arg found save to nvs + if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { + // save to the stnv nvs partition + nvs_handle my_handle; + esp_err_t err; + err = nvs_open_from_partition("nvs", "stdk", NVS_READWRITE, &my_handle); + if ( err != ESP_OK) { + ESP_LOGE(TAG, "%s: nvs_open_from_partition err: %s", __func__, esp_err_to_name(err)); + } + err = nvs_set_str(my_handle, "PrivateKey", arg.c_str()); + if ( err != ESP_OK) { + ESP_LOGE(TAG, "%s: nvs_set_str err: %s", __func__, esp_err_to_name(err)); + ad2_printf_host(true, "Failed setting value.\r\n"); + } else { + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); + } + err = nvs_commit(my_handle); + nvs_close(my_handle); + break; + } + // If no arg then return current show contents of this slot + ad2_printf_host(true, "SmartThings 'privatekey' arg missing.\r\n"); + break; + /** + * SmartThings PublicKey. + */ + case STSDK_SUBCMD_PUBKEY_ID: + // arg found save to nvs + if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { + // save to the stnv nvs partition + nvs_handle my_handle; + esp_err_t err; + err = nvs_open_from_partition("nvs", "stdk", NVS_READWRITE, &my_handle); + if ( err != ESP_OK) { + ESP_LOGE(TAG, "%s: nvs_open_from_partition err: %s", __func__, esp_err_to_name(err)); + } + err = nvs_set_str(my_handle, "PublicKey", arg.c_str()); + if ( err != ESP_OK) { + ESP_LOGE(TAG, "%s: nvs_set_str err: %s", __func__, esp_err_to_name(err)); + ad2_printf_host(true, "Failed setting value.\r\n"); + } else { + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); + } + err = nvs_commit(my_handle); + nvs_close(my_handle); + break; + } + // If no arg then return current show contents of this slot + ad2_printf_host(true, "SmartThings 'publickey' arg missing.\r\n"); + break; + default: + break; + } + break; } - err = nvs_commit(my_handle); - nvs_close(my_handle); - } else { - ad2_printf_host(false, "Missing \r\n"); } } -char * STSDK_SETTINGS [] = { - (char*)STSDK_ENABLE, - (char*)STSDK_CLEANUP, - (char*)STSDK_SERIAL, - (char*)STSDK_PUBKEY, - (char*)STSDK_PRIVKEY, - 0 // EOF -}; - /** * @brief command list for module */ static struct cli_command stsdk_cmd_list[] = { { - (char*)STSDK_ENABLE,(char*) - "Usage: stenable [arg]\r\n" + (char*)STSDK_COMMAND,(char*) + "Usage: smartthings [arg]\r\n" "\r\n" - " Configuration tool for STSDK client\r\n" - "Options:\r\n" - " arg [Y | N] Enable or Disable STSDK client\r\n" - , _cli_cmd_enable_event - }, - { - (char*)STSDK_CLEANUP,(char*) - "- Cleanup NV data with restart option\r\n" - " - ```" STSDK_CLEANUP "```\r\n\r\n", _cli_cmd_cleanup_event - }, - { - (char*)STSDK_SERIAL,(char*) - "- Sets the SmartThings device_info serialNumber.\r\n" - " - ```" STSDK_SERIAL " {serialNumber}```\r\n" - " - Example: ```" STSDK_SERIAL " AaBbCcDdEeFfGg...```\r\n\r\n", _cli_cmd_stserial_event - }, - { - (char*)STSDK_PUBKEY,(char*) - "- Sets the SmartThings device_info publicKey.\r\n" - " - ```" STSDK_PUBKEY " {publicKey}```\r\n" - " - Example: ```" STSDK_PUBKEY " AaBbCcDdEeFfGg...```\r\n\r\n", _cli_cmd_stpublickey_event - }, - { - (char*)STSDK_PRIVKEY,(char*) - "- Sets the SmartThings device_info privateKey.\r\n" - " - ```" STSDK_PRIVKEY " {privateKey}```\r\n" - " - Example: ```" STSDK_PRIVKEY " AaBbCcDdEeFfGg...```\r\n\r\n", _cli_cmd_stprivatekey_event - }, + " Configuration tool for SmartThings Direct Connected Devices SDK\r\n" + " NOTE: Only the enable setting is kept in the ad2iot.ini config.\r\n" + " The remaining settings are kept in the ```stnv``` partition and\r\n" + " managed by the SmartThings Direct Device SDK.\r\n" + "Commands:\r\n" + " enable [Y|N] Set or get enable flag\r\n" + " cleanup Reset the NVS partition\r\n" + " serial Set the device serial\r\n" + " publickey Set the device public key\r\n" + " privatekey Set the device private key\r\n" + "Examples:\r\n" + " ```smartthings enable Y```\r\n" + " ```smartthings publickey aabbccddeeffAABBCCDEEFF```\r\n" + , _cli_cmd_stsdk_event + } }; #if 0 // TODO/FIXME @@ -1001,7 +1020,7 @@ void stsdk_init(void) int iot_err; bool en = false; - ad2_get_config_key_bool(STSDK_ENABLE, 0, nullptr, &en); + ad2_get_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, &en); // nothing more needs to be done once commands are set if not enabled. if (!en) { @@ -1465,6 +1484,7 @@ void update_firmware_cmd_cb(IOT_CAP_HANDLE *handle, { hal_ota_do_update(nullptr); } - +#ifdef __cplusplus +} // extern "C" +#endif #endif /* CONFIG_STDK_IOT_CORE */ - diff --git a/components/stsdk/stsdk_main.h b/components/stsdk/stsdk_main.h index 8655ca02..e9721b09 100644 --- a/components/stsdk/stsdk_main.h +++ b/components/stsdk/stsdk_main.h @@ -41,14 +41,20 @@ #include "caps_powerSource.h" #include "caps_battery.h" -#define STSDK_ENABLE "stenable" -#define STSDK_CLEANUP "stcleanup" -#define STSDK_SERIAL "stserial" -#define STSDK_PUBKEY "stpublickey" -#define STSDK_PRIVKEY "stprivatekey" +#define STSDK_COMMAND "smartthings" +#define STSDK_SUBCMD_ENABLE "enable" +#define STSDK_SUBCMD_CLEANUP "cleanup" +#define STSDK_SUBCMD_SERIAL "serial" +#define STSDK_SUBCMD_PUBKEY "publickey" +#define STSDK_SUBCMD_PRIVKEY "privatekey" + +#define STSDK_CONFIG_SECTION "smartthings" -//#define SET_PIN_NUMBER_CONFRIM +//#define SET_PIN_NUMBER_CONFRIM +#ifdef __cplusplus +extern "C" { +#endif void stsdk_register_cmds(void); void stsdk_init(void); void button_event(IOT_CAP_HANDLE *handle, int type, int count); @@ -102,6 +108,7 @@ extern IOT_CAP_HANDLE *healthCheck_cap_handle; extern IOT_CAP_HANDLE *refresh_cap_handle; extern int noti_led_mode; - +#ifdef __cplusplus +} // extern "C" +#endif #endif /* _STSDK_MAIN_H */ - diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 58c3c91d..9426d34a 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -32,6 +32,13 @@ set(STDK_INCLUDE_PATH "$ENV{IDF_PATH}/components/bootloader_support/include" ) +# Fetch SimpleIni lib and as as include path. +# Todo: Only if not already downloaded. +include(FetchContent) # once in the project to include the module +FetchContent_Declare(simpleini GIT_REPOSITORY https://github.com/brofield/simpleini.git) +FetchContent_MakeAvailable(simpleini) +include_directories(${simpleini_SOURCE_DIR}) + if(CONFIG_STDK_IOT_CORE) add_subdirectory($ENV{STDK_CORE_PATH} iotcore) target_link_libraries(${COMPONENT_LIB} PUBLIC iotcore) From a206d6ee970c592c44be541f973a5dc2e5823aab Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 29 Dec 2022 17:21:07 -0800 Subject: [PATCH 11/97] Still on P2 so add to P2 not P3. --- CHANGELOG.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b388c18..e85283f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,22 +33,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). --- ## Releases -## [1.1.0 P3] - 2022-12-__ Sean Mathews - coder @f34rdotcom -Changes: - - Get STSDK building again. -### Change log - - [X] SM CORE: Add fixes for stsdk code that I have been sitting on. Mostly just CDECL stuff. - - [X] SM CORE: Fix CMakeList.txt to fetch SimpleIni from github and include it for stsdk building. - - [ ] SM FTPD: Does not build with stsdk. - - [ ] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. -## [1.1.0 P2] - 2022-11-14 Sean Mathews - coder @f34rdotcom +## [1.1.0 P2] - 2022-12-29 Sean Mathews - coder @f34rdotcom Changes: - Add Travis platformio build test. - Fix missing settings and organized sdkconfig.defaults. - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. - TODO: Find more time to audit and cleanup code. - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. + - Get STSDK building again. ### Change log + - [ ] SM FTPD: Does not build with stsdk. + - [ ] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. + - [X] SM CORE: Add fixes for stsdk code that I have been sitting on. Mostly just CDECL stuff. + - [X] SM CORE: Fix CMakeList.txt to fetch SimpleIni from github and include it for stsdk building. - [X] SM CORE: Travis build platform io project test. - [X] SM CORE: Fix sdkconfig.defaults was missing critical bits. Better organized now and "should" build same exact same firmware as in release. - [X] SM CORE: Fix missing compile flag ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH From 9ca78ede4cd9b4a7181c05c5917780d21346fe8c Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 29 Dec 2022 21:26:22 -0800 Subject: [PATCH 12/97] Update build docs. --- CHANGELOG.md | 3 ++- README.md | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e85283f5..a54d143d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,9 +44,10 @@ Changes: ### Change log - [ ] SM FTPD: Does not build with stsdk. - [ ] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. + - [X] SM CORE: Update README.md docs on building project including stsdk and platformio. - [X] SM CORE: Add fixes for stsdk code that I have been sitting on. Mostly just CDECL stuff. - [X] SM CORE: Fix CMakeList.txt to fetch SimpleIni from github and include it for stsdk building. - - [X] SM CORE: Travis build platform io project test. + - [X] SM CORE: Travis build platformio project test. - [X] SM CORE: Fix sdkconfig.defaults was missing critical bits. Better organized now and "should" build same exact same firmware as in release. - [X] SM CORE: Fix missing compile flag ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH - [X] SM TWILIO: Improve error handling and response data validation. diff --git a/README.md b/README.md index a0dc4551..425afa72 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ * 5.8.1. [Configuration for FTP server](#configuration-for-ftp-server) * 6. [Building firmware](#building-firmware) * 6.1. [PlatformIO](#platformio) - * 6.1.1. [TODO: Setup notes](#todo:-setup-notes) + * 6.1.1. [TODO: Setup notes](#platformio-setup-notes) * 6.2. [SmartThings device SDK build environment](#smartthings-device-sdk-build-environment) * 6.2.1. [Setup build environment](#setup-build-environment) * 6.2.2. [Configure the project](#configure-the-project) @@ -734,24 +734,44 @@ Examples: ## 6. Building firmware ### 6.1. PlatformIO -#### 6.1.1. TODO: Setup notes +#### 6.1.1. Open the project and use the platformio UI inside of vscode to build and flash. Select esp32dev or esp32-poe-iso tree and select Build to compile. ### 6.2. SmartThings device SDK build environment #### 6.2.1. Setup build environment -- Follow the instructions in the [SmartThings SDK for Direct connected devices for C](https://github.com/SmartThingsCommunity/st-device-sdk-c-ref) project for setting up a build environment. Confirm you can build the switch_example before continuing. -- Select the esp32 build environment. Branch v1.4 seems to be the current active branch and uses espidf v4.0.1-317-g50b3e2c81. +- Based on the instructions in the [SmartThings SDK for Direct connected devices for C](https://github.com/SmartThingsCommunity/st-device-sdk-c-ref) for setting up a build environment and [This community post](https://community.smartthings.com/t/how-to-build-direct-connected-devices/204055) to build the code inside of the stsdk c-ref build environment. ``` +# Make the root esp folder. +cd ~ +mkdir esp + +# Install the xtensa esp32 compiler cd ~/esp - git clone https://github.com/SmartThingsCommunity/st-device-sdk-c-ref.git -b release/v1.4 - cd st-device-sdk-c-ref -./setup.py esp32 -``` +wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz +tar -xvf xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz -- Place the contents of this his project in ```st-device-sdk-c-ref/apps/esp32/``` +# Get and install esp-idf toolchain v4.3.2 +cd ~/esp +git clone -b v4.3.2 --recursive https://github.com/espressif/esp-idf.git +cd ~/esp/esp-idf +./install.sh -#### 6.2.2. Configure the project +# Install st-device-sdk-c-ref master branch currently v1.7.5. +cd ~/esp +git clone https://github.com/SmartThingsCommunity/st-device-sdk-c-ref.git +cd st-device-sdk-c-ref +python setup.py esp32 +## At the end will be prompted to set the environment for building by sourcing the exports.sh file created during setup of stsdk c-ref. +. ./export.sh + +# Link our external AlarmDecoder-IoT project into the apps folder for st-device-sdk-c-ref. +ln -s ~/Code/AlarmDecoder-IoT ~/esp/st-device-sdk-c-ref/apps/esp32 +``` + +#### 6.2.2. Configure the project +Run menu config and enable/disable components. Each module will consume code space and memory so test with the ```top``` command to be sure resources are not being exausted. ``` -./build.sh esp32 AlarmDecoder-IoT menuconfig +cd ~/esp/st-device-sdk-c-ref +./build.py esp32 AlarmDecoder-IoT menuconfig ``` #### 6.2.3. Build, Flash, and Run @@ -759,6 +779,7 @@ cd ~/esp Build the project and flash it to the board, then run monitor tool to view serial output: ``` +cd ~/esp/st-device-sdk-c-ref ./build.sh esp32 AlarmDecoder-IoT build flash monitor -p /dev/ttyUSB0 ``` From 49208ea32342593bf561db20c4eb02657de6551f Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 30 Dec 2022 12:14:46 -0800 Subject: [PATCH 13/97] Compile steps seem solid on my system. Needs more testing. FTPD still broken and it seems MQTT still working. Maybe I can make a single build again. --- README.md | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 425afa72..feeb331e 100644 --- a/README.md +++ b/README.md @@ -743,16 +743,24 @@ Examples: cd ~ mkdir esp -# Install the xtensa esp32 compiler +# Get and install esp-idf toolchain v5.0 cd ~/esp -wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz -tar -xvf xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz +git clone -b v5.0 --recursive https://github.com/espressif/esp-idf.git -# Get and install esp-idf toolchain v4.3.2 -cd ~/esp -git clone -b v4.3.2 --recursive https://github.com/espressif/esp-idf.git cd ~/esp/esp-idf -./install.sh +## Added esp32 to the end. Need to test above again with this change. +./install.sh esp32 + +## At the end will be prompted to set the environment for building by sourcing the exports.sh file created during setup of stsdk c-ref. You can also follow the espressif docs and set the alias get_idf to '. $HOME/esp/esp-idf/export.sh' + +. ./export.sh + +# Install the xtensa esp32 toolchain +## Is this automagic now? During setup of esp-idf above. +### Downloading xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz to /home/mathewss/.espressif/dist/xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-amd64.tar.gz.tmp +cd ~/esp +wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-97-gc752ad5-5.2.0.tar.gz +tar -xvf xtensa-esp32-elf-linux64-1.22.0-97-gc752ad5-5.2.0.tar.gz # Install st-device-sdk-c-ref master branch currently v1.7.5. cd ~/esp @@ -760,18 +768,23 @@ git clone https://github.com/SmartThingsCommunity/st-device-sdk-c-ref.git cd st-device-sdk-c-ref python setup.py esp32 -## At the end will be prompted to set the environment for building by sourcing the exports.sh file created during setup of stsdk c-ref. -. ./export.sh +# Confirm the switch example can be built before continuing. +python build.py esp32 switch_example # Link our external AlarmDecoder-IoT project into the apps folder for st-device-sdk-c-ref. +# or fetch the AlarmDecoder-IoT project directly inside of the st-device-sdk-c-ref apps/esp32/ folder. ln -s ~/Code/AlarmDecoder-IoT ~/esp/st-device-sdk-c-ref/apps/esp32 ``` #### 6.2.2. Configure the project -Run menu config and enable/disable components. Each module will consume code space and memory so test with the ```top``` command to be sure resources are not being exausted. +Run menu config and enable/disable components. Each module will consume code space and memory so test with the ```top``` command to be sure resources are not being exausted. + - Component config: + - Enable ```SmartThings IoT Core``` + - Enable ESP32 support. ```BSP Support(ESP32)``` + - Disable ```AD2Iot * FTP demon``` ``` cd ~/esp/st-device-sdk-c-ref -./build.py esp32 AlarmDecoder-IoT menuconfig +python build.py esp32 AlarmDecoder-IoT menuconfig ``` #### 6.2.3. Build, Flash, and Run @@ -780,7 +793,7 @@ Build the project and flash it to the board, then run monitor tool to view seria ``` cd ~/esp/st-device-sdk-c-ref -./build.sh esp32 AlarmDecoder-IoT build flash monitor -p /dev/ttyUSB0 +python build.py esp32 AlarmDecoder-IoT build flash monitor -p /dev/ttyUSB0 ``` (To exit the serial monitor, type ``Ctrl-]``.) From dc8a0a7d49442cd7ff9a863e4f9a6a7af5e38244 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 9 Feb 2023 21:24:35 -0800 Subject: [PATCH 14/97] More changes and a release date push. --- CHANGELOG.md | 9 +- README.md | 151 +++++++++++++++--- .../flash-drive/{README.md => README-WWW.md} | 4 +- data/ad2iot.ini | 17 +- main/ad2_cli_cmd.cpp | 2 +- 5 files changed, 152 insertions(+), 31 deletions(-) rename contrib/webUI/flash-drive/{README.md => README-WWW.md} (87%) diff --git a/CHANGELOG.md b/CHANGELOG.md index a54d143d..2ea68084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,13 +27,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [ ] webUI: Add REST api compatible with the current webapp including a secret key. This is low priority as this method of connection is not very efficient. ### AJ -- [ ] Add a GitHub Action to run a `pio` build on every PR - [ ] Migrate `astyle` to GitHub Action -- [ ] Update README.md to reflect `pio` build changes --- ## Releases -## [1.1.0 P2] - 2022-12-29 Sean Mathews - coder @f34rdotcom +## [1.1.0 P2] - 2023-01-11 Sean Mathews - coder @f34rdotcom Changes: - Add Travis platformio build test. - Fix missing settings and organized sdkconfig.defaults. @@ -41,9 +39,12 @@ Changes: - TODO: Find more time to audit and cleanup code. - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. - Get STSDK building again. + - Improved documentation fixing errors and adding config file examples in each section. ### Change log - [ ] SM FTPD: Does not build with stsdk. - - [ ] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. + - [X] SM CORE: Docs improvements. + - [X] SM STSDK: Build and uploaded set keys but was not able to adopt. '''Error 81-001 Something went wrong''' + - [X] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. - [X] SM CORE: Update README.md docs on building project including stsdk and platformio. - [X] SM CORE: Add fixes for stsdk code that I have been sitting on. Mostly just CDECL stuff. - [X] SM CORE: Fix CMakeList.txt to fetch SimpleIni from github and include it for stsdk building. diff --git a/README.md b/README.md index feeb331e..7b077393 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Configuration of the AD2IoT is done directly over the USB serial port using a co - To save settings to the [ad2iot.ini](data/ad2iot.ini) use the ```restart``` command. This will save any settings changed in memory to the active configuration file before restarting to load the new settings. - Configuration using the configuration file. - The ad2iot will first attempt to load the [ad2iot.ini](data/ad2iot.ini) config file from the first fat32 partition on a uSD card if attached. If this fails it will attempt to load the same file from the internal spiffs partition. If this fails the system will use defaults and save any changes on ```restart``` command to the internal spiffs partition in the file [ad2iot.ini](data/ad2iot.ini). - - To access /sdcard/ad2iot.ini and /spiffs/ad2iot.ini files over the network enable the [FTPD component](#ftp-daemon-component). Use the custom FTP command ```REST``` to restart the ad2iot and force it to load the new configuration. + - To access /sdcard/ad2iot.ini and /spiffs/ad2iot.ini files over the network enable the [FTPD component](#ftp-daemon-component). With FileZilla edit the configuration upload and send a custom FTP command using the "Server" menu and the "Enter custom command.." sub menu. Enter ```REST``` to restart the ad2iot and force it to load the configuration. - Sample config file with internal documentation can be found here [data/ad2iot.ini](data/ad2iot.ini) - Be sure to set the ftpd acl to only allow trusted systems to manage the files on the uSD card. @@ -231,6 +231,10 @@ Usage: version Report the current and available version ``` +```console +AD2IOT # version +Installed version(AD2IOT-1102) build flag (webui) available version(AD2IOT-1102). +``` - netmode ```console Usage: netmode [(N | W | E)] [] @@ -253,6 +257,11 @@ Examples: Ethernet Static IPv4 address. ```netmode E mode=s&ip=192.168.1.111&mask=255.255.255.0&gw=192.168.1.1&dns1=4.2.2.2&dns2=8.8.8.8``` ``` +```console +# Example config file ini setting +# Enable ethernet driver and use DHCP for setting address +netmode = E mode=d +``` - switch ```console Usage: switch [command] [] @@ -274,23 +283,61 @@ Commands: close IDX REGEX CLOSE event REGEX filter for IDX 1-8 trouble IDX REGEX TROUBLE event REGEX filter for IDX 1-8 Options: - switchId ad2iot virtual switch ID 1-255 + swid ad2iot virtual switch ID 1-255 IDX REGEX index 1-8 for multiple tests REGEX Regular expression or exact match string. TYPE Message types [ALPHA,LRR,REL,EXP,RFX,AUI,KPM,KPE, CRC,VER,ERR,EVENT] -Common search verbs for type EVENT - arm {STAY|AWAY} - disarm - power {AC|BATTERY} - ready {ON|OFF} - alarm {ON/OFF} - fire {ON|OFF} - chime {ON|OFF} - exit {ON|OFF} - programming {ON|OFF} - zone {OPEN,CLOSE,TROUBLE} ZONE_NUMBER +Common message verbs and arguments received for type EVENT + ARM {STAY|AWAY} + DISARM + POWER {AC|BATTERY} + READY {ON|OFF} + ALARM {ON/OFF} + FIRE {ON|OFF} + CHIME {ON|OFF} + EXIT {ON|OFF} + PROGRAMMING {ON|OFF} + ZONE {OPEN,CLOSE,TROUBLE} {ZONE_NUMBER} +``` +```console +# Example config file ini section [switch N] +[switch 10] +# Test ZONE tracking event for zone 3 +default = 0 +reset = 0 +types = EVENT +filter = ZONE.* +open 1 = ZONE OPEN 3 +close 1 = ZONE CLOSE 3 +trouble 1 = ZONE TROUBLE 3 + +[switch 60] +# RFX serial 0123456 +default = -1 +reset = 0 +types = RFX +filter = !RFX:0123456,.* +open 1 = !RFX:0123456,1....... +close 1 = !RFX:0123456,0....... +trouble 1 = !RFX:0123456,......1. + +[switch 91] +# AC switch +default = -1 +reset = 0 +types = EVENT +open 1 = POWER BATTERY +close 1 = POWER AC + +[switch 95] +# Fire switch +default = -1 +reset = 0 +types = EVENT +open 1 = FIRE ON +close 1 = FIRE OFF ``` - code ```console @@ -302,6 +349,12 @@ Options: - Delete entry value Code string ``` +```console +# Example config file ini setting +[code] +1 = 4112 +2 = 1234 +``` - ad2term ```console Usage: ad2term [reset] @@ -326,6 +379,12 @@ Options: Example set mode Ademco with default address 18. ```ad2config mode=A&address=18``` ``` +```console +# Example config file ini setting +# This will push these settings to the AD2* board. +# Avoid multiple systems trying to enforce this setting. That would be bad. +ad2config = address=18&mode=A +``` - partition ```console Usage: partition [(
) [zoneList]] @@ -362,6 +421,13 @@ Examples: ```partition 2 -``` Note: address - will remove an entry. ``` +```console +# Example config file ini section [partition N] +# Note: Must add [zone N] sections for each zone for zone details. +[partition 1] +address = 18 +zones = 2,3,4,5,6,24,25,26 +``` - zone ```console Usage: zone [- | ] @@ -373,6 +439,23 @@ Options: value json string with type and alpha attributes {"type": "smoke", "alpha": "TESTING LAB SMOKE"} ``` +```console +# Example config file ini section [zone NN] +# Note: Must add each zone to the [partition N] zones list. +# For MQTT "type" is translated to "device_class" for the device discovery document. +# "alpha" is translated to "name" +# https://www.home-assistant.io/integrations/mqtt/#mqtt-discovery +# https://www.home-assistant.io/integrations/binary_sensor/#device-class +# +[zone 1] +description = {"type": "smoke", "alpha": "Smoke Alarm"} + +[zone 3] +description = {"type": "door", "alpha": "Back Door"} + +[zone 4] +description = {"type": "motion", "alpha": "Entry Motion"} +``` - ad2source ```console Usage: ad2source [( )] @@ -389,6 +472,11 @@ Examples: Set source to local attached uart with TX on GPIO 4 and RX on GPIO 36. ```ad2source COM 4:36``` ``` +```console +# Example config file ini setting +# Use caution changing this setting it can change GPIO pin states. +ad2source = C 4:36 +``` ### 5.2. Ser2sock server component Ser2sock allows sharing of a serial device over a TCP/IP network. It also supports encryption and authentication via OpenSSL. Typically configured for port 10000 several home automation systems are able to use this protocol to talk to the AlarmDecoder device for a raw stream of messages. Please be advised that network scanning of this port can lead to alarm faults. It is best to use the Access Control List feature to only allow specific hosts to communicate directly with the AD2* and the alarm panel. @@ -404,6 +492,12 @@ Examples: ```ser2sockd enable Y``` ```ser2sockd acl 192.168.0.0/28,192.168.1.0-192.168.1.10,192.168.3.4``` ``` +```console +# Example config file ini setting +[ser2sockd] +enable = true +acl = 192.168.0.0/16, 10.10.0.0/16 +``` ### 5.3. Web User Interface webUI component This component provides a simple HTML5+WebSocket user interface with realtime alarm status using push messages over WebSocket. Buttons for Arming, Disarming, Exiting, and sending panic events. Panic buttons require pressing the button three times in 5 seconds to help prevent false alarms.
@@ -422,7 +516,12 @@ Examples: ```webui enable Y``` ```webui acl 192.168.0.0/28,192.168.1.0-192.168.1.10,192.168.3.4``` ``` - +```console +# Example config file ini setting +[webui] +enable = true +acl = 192.168.0.0/16, 10.10.0.0/16 +``` ### 5.4. SmartThings Direct Connected device. ###### ```Only available in stsdk firmware build``` Direct-connected devices connect directly to the SmartThings cloud. The SDK for Direct Connected Devices is equipped to manage all MQTT topics and onboarding requirements, freeing you to focus on the actions and attributes of your device. To facilitate the development of device application in an original chipset SDK, the core device library and the examples were separated into two git repositories. That is, if you want to use the core device library in your original chipset SDK that installed before, you may simply link it to develop a device application in your existing development environment. For more info see https://github.com/SmartThingsCommunity/st-device-sdk-c-ref. @@ -526,7 +625,7 @@ Commands: token acid [hash] Twilio Auth Token from acid [address] Validated Email or Phone # to acid [address] Email or Phone # - type acid [M|C|E] Notification type Mail, Call, EMail + type acid [M|C|E] Notification type SMS, Call, EMail format acid [format] Output format string switch swid SCMD [ARG] Configure switches Sub-Commands: switch @@ -574,28 +673,28 @@ Options: # Twilio config section [twilio] - # Account ID #1 EMail using api.sendgrid.com + # Account storage ID(acid) #1 EMail using api.sendgrid.com sid 1 = NA token 1 = Abcdefg012345.... from 1 = foo@example.com to 1 = bar@example.com - type 1 = email + type 1 = E format 1 = {} - # Account ID #2 Text message using api.twilio.com + # Account storage ID(acid) #2 Text message using api.twilio.com sid 2 Abcdefg012345.... token 2 = Abcdefg012345.... from 2 = 15555551234 to 2 = 15555551234 - type 2 = text + type 2 = M format 2 = {} - # Account ID #3 Voice Twiml call using api.twilio.com + # Account storage ID(acid) #3 Voice Twiml call using api.twilio.com sid 3 = Abcdefg012345.... token 3 = Abcdefg012345.... from 3 = 15555551234 to 3 = 15555551234 - type 3 = call + type 3 = C format 3 = {0}{0}{0} ``` - Send notifications from profile in slot #0 for 5800 RF sensor with SN 0123456 and trigger on OPEN(ON), CLOSE(OFF) and TROUBLE REGEX patterns. In this example the Text or EMail sent would event contain the user defined message. @@ -731,7 +830,15 @@ Examples: ```ftpd enable Y``` ```ftpd acl 192.168.0.0/28,192.168.1.0-192.168.1.10,192.168.3.4``` ``` +```console +# Example config file ini section +[ftpd] +## Enable / Disable true or false +enable = true +## Access control list +acl = 192.168.0.0/16, 10.10.0.0/16 +``` ## 6. Building firmware ### 6.1. PlatformIO #### 6.1.1. Open the project and use the platformio UI inside of vscode to build and flash. Select esp32dev or esp32-poe-iso tree and select Build to compile. @@ -743,7 +850,7 @@ Examples: cd ~ mkdir esp -# Get and install esp-idf toolchain v5.0 +# Get and install esp-idf toolchain v5.0(AF), v4.3.2(AF), cd ~/esp git clone -b v5.0 --recursive https://github.com/espressif/esp-idf.git diff --git a/contrib/webUI/flash-drive/README.md b/contrib/webUI/flash-drive/README-WWW.md similarity index 87% rename from contrib/webUI/flash-drive/README.md rename to contrib/webUI/flash-drive/README-WWW.md index 55cf2c1c..1e0e0de4 100644 --- a/contrib/webUI/flash-drive/README.md +++ b/contrib/webUI/flash-drive/README-WWW.md @@ -1,6 +1,6 @@ -### Place this folder in the root directory of a fat32 formatted uSD disk. +### Place the contents of this folder in the root directory of a fat32 formatted uSD disk. ``` -├── README.md +├── README-WWW.md └── www ├── 404.html ├── 404.html.tpl diff --git a/data/ad2iot.ini b/data/ad2iot.ini index 4e551f94..7a233882 100644 --- a/data/ad2iot.ini +++ b/data/ad2iot.ini @@ -26,6 +26,7 @@ # Set source to local attached uart with TX on GPIO 4 and RX on GPIO 36. # ```ad2source COM 4:36``` ############################################################################### +# Use caution changing this setting it can change GPIO pin settings. ad2source = C 4:36 ############################################################################### @@ -38,6 +39,8 @@ ad2source = C 4:36 # Example set mode Ademco with default address 18. # ```ad2config mode=A&address=18``` ############################################################################### +# This will push these settings to the AD2* board. +# Avoid multiple systems trying to enforce this setting. That would be bad. ad2config = address=18&mode=A ############################################################################### @@ -198,12 +201,22 @@ description = {"type": "problem", "alpha": "Failed to call(FC)"} # close IDX REGEX CLOSE event REGEX filter for IDX 1-8 # trouble IDX REGEX TROUBLE event REGEX filter for IDX 1-8 # Options: -# switchId ad2iot virtual switch ID 1-255 +# swid ad2iot virtual switch ID 1-255 # IDX REGEX index 1-8 for multiple tests # REGEX Regular expression or exact match string. # TYPE Message types [ALPHA,LRR,REL,EXP,RFX,AUI,KPM,KPE, # CRC,VER,ERR,EVENT] ############################################################################### +[switch 10] +# Test ZONE tracking event for zone 3 +default = 0 +reset = 0 +types = EVENT +filter = ZONE.* +open 1 = ZONE OPEN 3 +close 1 = ZONE CLOSE 3 +trouble 1 = ZONE TROUBLE 3 + [switch 60] # RFX serial 0123456 default = -1 @@ -454,7 +467,7 @@ switch 103 close = DISARMED USER 3 # token acid [hash] Twilio Auth Token # from acid [address] Validated Email or Phone # # to acid [address] Email or Phone # -# type acid [M|C|E] Notification type Mail, Call, EMail +# type acid [M|C|E] Notification type SMS Text, Call, EMail # format acid [format] Output format string # switch swid SCMD [ARG] Configure switches # Sub-Commands: diff --git a/main/ad2_cli_cmd.cpp b/main/ad2_cli_cmd.cpp index 24159839..eb187203 100644 --- a/main/ad2_cli_cmd.cpp +++ b/main/ad2_cli_cmd.cpp @@ -704,7 +704,7 @@ static struct cli_command cmd_list[] = { " close IDX REGEX CLOSE event REGEX filter for IDX 1-8\r\n" " trouble IDX REGEX TROUBLE event REGEX filter for IDX 1-8\r\n" "Options:\r\n" - " switchId ad2iot virtual switch ID 1-255\r\n" + " swid ad2iot virtual switch ID 1-255\r\n" " IDX REGEX index 1-8 for multiple tests\r\n" " REGEX Regular expression or exact match string.\r\n" " TYPE Message types [ALPHA,LRR,REL,EXP,RFX,AUI,KPM,KPE,\r\n" From 0b9ee8727c3ad34f06c7d0dc7c874b9939c484f8 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 9 Feb 2023 22:11:44 -0800 Subject: [PATCH 15/97] testing.. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ea68084..bb015681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). --- ## Releases -## [1.1.0 P2] - 2023-01-11 Sean Mathews - coder @f34rdotcom +## [1.1.0 P2] - 2023-01-?? Sean Mathews - coder @f34rdotcom Changes: - Add Travis platformio build test. - Fix missing settings and organized sdkconfig.defaults. From eb86acaa4d10d4abb1d5950c026ade4359aecf50 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 21:57:10 -0800 Subject: [PATCH 16/97] More doc changes. Switcthing from travis-ci to github actions since I ran out of credits and can't build anymore. --- .github/workflows/build.yml | 26 ++++++++++++++++++++++ .travis.yml | 43 ------------------------------------- CHANGELOG.md | 1 + README.md | 14 ++++++------ data/ad2iot.ini | 9 +++++--- main/ad2_cli_cmd.cpp | 2 ++ 6 files changed, 43 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..099ed974 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,26 @@ +name: AlarmDecoder-IoT CI + +on: [push] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/cache@v3 + with: + path: | + ~/.cache/pip + ~/.platformio/.cache + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Install PlatformIO Core + run: pip install --upgrade platformio + + - name: Build AlarmDecoder-IoT PlatformIO Project + run: pio run \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7af30a9c..00000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -dist: focal -sudo: false - -language: python - -python: - - "3.10.2" - -os: - - linux - -cache: - pip: true - directories: - - "~/.platformio" - - $HOME/astyle - - $HOME/.cache/pip - -install: - - pip install -U platformio - - pio update - -before_script: - - sh test/install_astyle.sh - -script: - - cd $TRAVIS_BUILD_DIR - - export ARTISTIC_STYLE_OPTIONS=".astylerc" - - astyle *.cpp,*.h > astyle.out - - TEST=$(cat astyle.out | wc -l) - - ASTYLE_HEADER_LINES=4 - - | - if [[ $(($TEST - $ASTYLE_HEADER_LINES)) -ne 0 ]]; then - cat astyle.out - git --no-pager diff - echo "Please fix style issues as shown above" - exit 1 - fi - - pio run -e esp32-poe-iso -notifications: - email: - on_success: change - on_failure: change diff --git a/CHANGELOG.md b/CHANGELOG.md index bb015681..71a5cc65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Changes: - Get STSDK building again. - Improved documentation fixing errors and adding config file examples in each section. ### Change log + - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :( - [ ] SM FTPD: Does not build with stsdk. - [X] SM CORE: Docs improvements. - [X] SM STSDK: Build and uploaded set keys but was not able to adopt. '''Error 81-001 Something went wrong''' diff --git a/README.md b/README.md index 7b077393..77d310af 100644 --- a/README.md +++ b/README.md @@ -110,9 +110,9 @@ Configuration of the AD2IoT is done directly over the USB serial port using a co - ```ad2source COM 4:36``` - Network shared AD2* device over ser2sock - ```ad2source SOCK 192.168.0.121:10000``` - - Configure the AlarmDecoder firmware settings for the the attached alarm system. For Ademco mode a free keypad address needs to be assigned to each partition to control. DSC mode is ZeroConf and only requires the mode 'D' and the partition # from 1-8. + - Configure the AlarmDecoder firmware settings for the the attached alarm system. For Ademco mode a free keypad address needs to be assigned to each partition to control. DSC mode is ZeroConf and only requires the mode 'D' and the partition # from 1-8 followed by the Slot 1-8 So address=11 is Partition #1 Slot #1. - Typical Ademco Vista setting: ```ad2config mode=A&address=18``` - - Typical DSC Power Series setting: ```ad2config mode=D&address=1``` + - Typical DSC Power Series setting: ```ad2config mode=D&address=11``` - Configure the default partition address and optional zones in partition 1. - ```partition 1 18 2,3,4,5``` - Define any additional partitions and optional zones. @@ -299,7 +299,7 @@ Common message verbs and arguments received for type EVENT CHIME {ON|OFF} EXIT {ON|OFF} PROGRAMMING {ON|OFF} - ZONE {OPEN,CLOSE,TROUBLE} {ZONE_NUMBER} + ZONE {OPEN,CLOSE,TROUBLE} {zero padded 3 digit zone number} ``` ```console # Example config file ini section [switch N] @@ -309,9 +309,9 @@ default = 0 reset = 0 types = EVENT filter = ZONE.* -open 1 = ZONE OPEN 3 -close 1 = ZONE CLOSE 3 -trouble 1 = ZONE TROUBLE 3 +open 1 = ZONE OPEN 003 +close 1 = ZONE CLOSE 003 +trouble 1 = ZONE TROUBLE 003 [switch 60] # RFX serial 0123456 @@ -378,6 +378,8 @@ Options: device. Can be partial config. Example set mode Ademco with default address 18. ```ad2config mode=A&address=18``` + Example set mode DSC with default Partiion 1 Slot 2. + ```ad2config mode=D&address=12``` ``` ```console # Example config file ini setting diff --git a/data/ad2iot.ini b/data/ad2iot.ini index 7a233882..4244866d 100644 --- a/data/ad2iot.ini +++ b/data/ad2iot.ini @@ -38,6 +38,8 @@ ad2source = C 4:36 # device. Can be partial config. # Example set mode Ademco with default address 18. # ```ad2config mode=A&address=18``` +# Example set mode DSC with default Partiion 1 Slot 2. +# ```ad2config mode=D&address=12``` ############################################################################### # This will push these settings to the AD2* board. # Avoid multiple systems trying to enforce this setting. That would be bad. @@ -163,6 +165,7 @@ description = {"type": "carbon_monoxide", "alpha": "Test CO2 ZONE"} [zone 26] description = {"type": "door", "alpha": "test door"} +# Ademco Vista specific special zone numbers. [zone 191] description = {"type": "problem", "alpha": "Long Range Radio trouble(bF)"} @@ -213,9 +216,9 @@ default = 0 reset = 0 types = EVENT filter = ZONE.* -open 1 = ZONE OPEN 3 -close 1 = ZONE CLOSE 3 -trouble 1 = ZONE TROUBLE 3 +open 1 = ZONE OPEN 003 +close 1 = ZONE CLOSE 003 +trouble 1 = ZONE TROUBLE 003 [switch 60] # RFX serial 0123456 diff --git a/main/ad2_cli_cmd.cpp b/main/ad2_cli_cmd.cpp index eb187203..d6036335 100644 --- a/main/ad2_cli_cmd.cpp +++ b/main/ad2_cli_cmd.cpp @@ -803,6 +803,8 @@ static struct cli_command cmd_list[] = { " device. Can be partial config.\r\n" " Example set mode Ademco with default address 18.\r\n" " ```ad2config mode=A&address=18```\r\n" + " Example set mode DSC with default address 1 Slot 2.\r\n" + " ```ad2config mode=D&address=12```\r\n" , _cli_cmd_ad2config_event }, { From eb70f374f4342fb6767d5afe914bb148917c72a0 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 22:12:16 -0800 Subject: [PATCH 17/97] .. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77d310af..dedafc55 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ /vscode-markdown-toc-config --> # AlarmDecoder IoT Network Appliance - [Latest stable release ![Release Version](https://img.shields.io/github/release/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/releases/latest/) [![Travis (.org) branch](https://img.shields.io/travis/nutechsoftware/AlarmDecoder-IoT/master?style=plastic)](https://travis-ci.org/nutechsoftware/AlarmDecoder-IoT) + [Latest stable release ![Release Version](https://img.shields.io/github/release/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/releases/latest/) [![.github/workflows/build.yml](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=master&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) - [Latest development branch ![Development branch](https://img.shields.io/badge/dev-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/tree/dev) [![Travis (.org) branch](https://img.shields.io/travis/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://travis-ci.org/nutechsoftware/AlarmDecoder-IoT) + [Latest development branch ![Development branch](https://img.shields.io/badge/dev-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/tree/dev) [![.github/workflows/build.yml](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=dev&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) ## 1. Overview From 63b264a21a41fde7579e7a432dfb038ed69a358f Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 22:22:45 -0800 Subject: [PATCH 18/97] .. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dedafc55..ebe3fabc 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ # AlarmDecoder IoT Network Appliance [Latest stable release ![Release Version](https://img.shields.io/github/release/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/releases/latest/) [![.github/workflows/build.yml](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=master&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) - [Latest development branch ![Development branch](https://img.shields.io/badge/dev-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/tree/dev) [![.github/workflows/build.yml](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=dev&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) + [Latest development branch ![Development branch](https://img.shields.io/badge/dev-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/tree/dev) [![build](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=dev&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) ## 1. Overview From e4647f35fdead2757a876d258482b30a99160690 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 22:25:55 -0800 Subject: [PATCH 19/97] .. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebe3fabc..dedafc55 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ # AlarmDecoder IoT Network Appliance [Latest stable release ![Release Version](https://img.shields.io/github/release/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic) ![Release Date](https://img.shields.io/github/release-date/nutechsoftware/AlarmDecoder-IoT.svg?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/releases/latest/) [![.github/workflows/build.yml](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=master&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) - [Latest development branch ![Development branch](https://img.shields.io/badge/dev-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/tree/dev) [![build](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=dev&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) + [Latest development branch ![Development branch](https://img.shields.io/badge/dev-yellow?style=plastic) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/nutechsoftware/AlarmDecoder-IoT/dev?style=plastic)](https://github.com/nutechsoftware/AlarmDecoder-IoT/tree/dev) [![.github/workflows/build.yml](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml/badge.svg?branch=dev&event=push)](https://github.com/nutechsoftware/AlarmDecoder-IoT/actions/workflows/build.yml) ## 1. Overview From ef24fe4121a396b88fc548d47e0b34bac2e4defc Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 22:27:01 -0800 Subject: [PATCH 20/97] .. --- .github/workflows/build.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 099ed974..1cb3ef94 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,6 @@ name: AlarmDecoder-IoT CI -on: [push] - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: +on: [push, workflow_dispatch] jobs: build: From 1dcceae776eb9b0f3a4eb2808f239cec51240314 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 22:48:12 -0800 Subject: [PATCH 21/97] .. --- CHANGELOG.md | 4 ++-- sdkconfig.defaults | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a5cc65..1f25f82c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] Open issues ### SM - Sean Mathews coder at f34r.com +- [ ] FTPD: Does not build with stsdk. - [ ] API: Add countdown tracking for DSC/Ademco exit mode - [ ] CORE: Needed feature ad2_fw_update() to update AD2* firmware. - [ ] CORE: TODO: Monitor limited sockets look for ways to reduce if possible. @@ -33,7 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Releases ## [1.1.0 P2] - 2023-01-?? Sean Mathews - coder @f34rdotcom Changes: - - Add Travis platformio build test. + - Add Github action build test. - Fix missing settings and organized sdkconfig.defaults. - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. - TODO: Find more time to audit and cleanup code. @@ -42,7 +43,6 @@ Changes: - Improved documentation fixing errors and adding config file examples in each section. ### Change log - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :( - - [ ] SM FTPD: Does not build with stsdk. - [X] SM CORE: Docs improvements. - [X] SM STSDK: Build and uploaded set keys but was not able to adopt. '''Error 81-001 Something went wrong''' - [X] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 47bcded4..f6905b1f 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -3,7 +3,7 @@ CONFIG_COMPILER_CXX_EXCEPTIONS=y CONFIG_CXX_EXCEPTIONS=y CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_OPTIMIZATION_LEVEL_RELEASE=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y # FreeRTOS settings CONFIG_FREERTOS_UNICORE=y From 9f2d5fbc262c89ca68e7c8f4316db0956638cc20 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 22:50:34 -0800 Subject: [PATCH 22/97] .. --- sdkconfig.defaults | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index f6905b1f..8cdb3515 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -7,7 +7,7 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y # FreeRTOS settings CONFIG_FREERTOS_UNICORE=y -CONFIG_FREERTOS_ISR_STACKSIZE=2048 +CONFIG_FREERTOS_ISR_STACKSIZE=2096 CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y From 5d42cd6e1261f2e8265f0be0db213bd38d1059b0 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 23:02:22 -0800 Subject: [PATCH 23/97] .. --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1cb3ef94..c6d8fb25 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: recursive - uses: actions/cache@v3 with: path: | From 07e725a8903b3ed526652c528e34381434113c3c Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 23:14:24 -0800 Subject: [PATCH 24/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6d8fb25..5beb944d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: AlarmDecoder-IoT CI +name: CI build on: [push, workflow_dispatch] From 38c636452046217178736fef807938242d74a883 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Fri, 17 Feb 2023 23:45:51 -0800 Subject: [PATCH 25/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5beb944d..c205d963 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,4 +23,4 @@ jobs: run: pip install --upgrade platformio - name: Build AlarmDecoder-IoT PlatformIO Project - run: pio run \ No newline at end of file + run: pio run -e esp32-poe-iso \ No newline at end of file From 1620fb584b09648c5d8fa0db89c1ba7786fe81af Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 00:02:38 -0800 Subject: [PATCH 26/97] .. --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c205d963..5fd19a4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,5 +22,8 @@ jobs: - name: Install PlatformIO Core run: pip install --upgrade platformio - - name: Build AlarmDecoder-IoT PlatformIO Project - run: pio run -e esp32-poe-iso \ No newline at end of file + - name: Build esp32-poe-iso + run: pio run -e esp32-poe-iso + + - name: Build spiffs.bin + run: pio run -t buildfs -e esp32-poe-iso \ No newline at end of file From 381f097bc96ee9d24cd1b6cdae6715cb766ac6d6 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 09:21:10 -0800 Subject: [PATCH 27/97] ... --- .github/workflows/build.yml | 8 +++++++- .../ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png | Bin 0 -> 126746 bytes contrib/README-FLASH.md | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5fd19a4c..b98f2468 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,4 +26,10 @@ jobs: run: pio run -e esp32-poe-iso - name: Build spiffs.bin - run: pio run -t buildfs -e esp32-poe-iso \ No newline at end of file + run: pio run -t buildfs -e esp32-poe-iso + + - name: Build firmware package + run: cwd + + - name: Upload firmware package Artifact + run: ls \ No newline at end of file diff --git a/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png b/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png new file mode 100644 index 0000000000000000000000000000000000000000..5b3f37d275b314e572f98c66431e147b798e552b GIT binary patch literal 126746 zcmeFZWl&sgvo<=oy99UF!QI{6b%4R$-Q7L7y95aCnh*#CC%9Weu;3CnB+v8OKKnaW zyXt)Z_JU!}v|QbNb>BB@idn>{D$AfC5+DKq02Db{Np%1K%JKDK1rPfwkuyeW0020` zd^L65)j?il&aO_DHuhjLcOPdk8Q9y#5&-aCsn55`B$vYp{}lVY+NmGmO2QJe0pGs3TJWi^0;aKd>HgR8i8FBQ$4@t+V&L7%)RNOc5-RA zCX%0UJN3xuL}+{#=(D-^^I_mJ(^yDk`M`u{wP(ui_Mx+vWM|`RztdIVHh;rx5}I#N zuSj2?h%wLA^&w%eKKk0FMYpku_d4C3PTbDrrGG13yMCX$!{pbr-Q)U)-50#rDf({A zdk$X%dB>i28y|;Hw4O5X+G5s_!?L#V6FOSZLOD2Wx@VK_zrS|s0{eVg?z)?+3wZjKw(j5aFy{Eh zPJP4jlFg2*p9R6Ba^WDUKj^+s;f%0X1fF#2wy@Cf@Hpe;A&`jNp9JyJr)x^@dQEvQ zj)cQJ#U$U?>!NR`t5~gPbNq>go3O6!r+7bMf9;8jL5K4$zNt0RH|wtJ#O-IB zb4odQziuM>dka5CJz9cOa|*>iqF=8Pn*gIDZ0>+f#RJ{XrOcUX{eM5CC z4_imQTr;D(9qt&)KN^UL=_hUQ0{1!&pkEwGnj4zJ+QX6=RY-k!+#!O}%Pvx$3y2N` zLa|WyTbCt~ThPFrZ7us(cKB7RJo^x8!q^V3#>44!GNs{|4+YBCEvc%Ie@ItXre2s= zpCbQ!>B^#azNSFeRFBii;sO@*j4A`vRuB>lc^gS%j7x3y^?<~6A zmcer=OOe6%;N*B1@wd#gIncArcevTt(dE4xudVA^`M&C)XfvAcxdHyV?kSSBfz$Odkf zwQ)0c2b@+Tlsyza1lgQ?pKU&74R++Kj0Q}s+Z`a6-kD_cXnfD-c`5voH#7h1bM~XK zQ-4ltIUU18$w$4|ZbiDtZVPeT?^JhBa5{L$3zxdUF-+XRPj?+S=h zcJq7(_^SrxsA3`>SmF^WX_s8#19GIg6u&4z^Bv>L{dN55#RFo#OSGvTtY;Dz%R8=v zoX9Hz|BwD`OC1*EE$i*iX}LL5UO0A-s|GnHJXbG)3YRJYFYWD|FM+%-{tA~o99Ojl zIWP9JL2Ezztz}*Y(}ViT@6U8Glpi;nN(d%`Mq{4wm;^t*)d!%sUJMHuy}S{zH$xKj-hOu_;uA2J;ja`PEGoSVe3N*r*iOFBOaAlL~?CjOzDwMv9m2Dw@t zBBvYW^GQ_%^4gkKlR}*mFwf!38{^}fb6=YBPQt5)@kX=~(tl*38SV$1mb@zG1X~y} zd(S9KG_HG1e5&@E$IlOI8szWNUG0<3NvD?D?MA@Y?gwTauKPllm$^bilwVd(TQZ1# zjK(|98uv_c3Z&AvQt^ghW) zFvE2Q?LFFUT#7_rwyCn66Dh)YmOs5&jLlhI%Pd3}dXu~7JqBy@{k;+f!g8~7adZJ2 zPI9@hpB}xFq(VVf;wIr6>HU=$-z442dd2WGVb1Mz$O~Co7+;Ai5e%o1r=khD^ifM* zS)uh)(OY(8mk+2&;E@t(49VayWRC1iElNYs!Sv}1?IiIL5)D!avvpZWdwd6hW$N8K z=WzNKLjo);9de_J;^v}zg@SIwotO2nI@EobrZbd9uHaZzh%#8jZ+eL#k?h=W-t^G4 zZkM_wt9^v)43@^1U1c%i7E=70i36R|dv2&{B&sDbS`yXGkzlr()|V+@L}T>v6RD|b z-TC485>h73Wz_9(=wsqF)3=zzacsN-zL6@SQvGQN)Xz8P*FDa4>Lsw_xAn)H=nst0 z5tf6@yFYE%N6bs8!$781Aby&DuiY_D@7>WNoLx8n@E#%bLhe2Ub)ZB1Xq@@wSD5|? z{u&@`%~(tB889V%_rEPMtnpx#-MzGa7NYgRpNr<-%7| zFhmjWkU0WPSz{%T^o^f_Oap0M&5MTTNAe24E|7lxZWm=2QrR<5j&S2<-s{Z~w1X!x zs7Wz?5rRb7-|H<_faAZ&vE+X(?n*7$x_Te&Ajk00;=BZQg`;TLqeUlQ5ONInF)xd| z^z@=4gfL;rfJ`&8BlM(Yh^GWMHdWPgs8(utt~6)AxYvB=&GWT41=t_rL+Ulhu3ddK znbP4A{2&T%`+#zP4tRu~Pve~5ewgWenSW5EF`Lp{@4y_~O1bG-FlxWsaYsx4u zgmUaBSc;i0A&ib4%kz(pE>Nhlumj!zlvU2@Yl5X83HXKOEZ-X0lYiKln_mq`#}k6{ z5WaF3d-T{rkqN3lLz|H8XN~)NTYYw3nm&)_IKveSO`&-5CHRs@Ra@{iH(eBUM*+Wh zqX^}Qx(c(%JoIkpn>CBG`rT)+o53ItIs27(<@9biA20-O@aW4tfxNm6wD{)@UgSVtRwvg7cI(~6(Qq956HVU* znM0o~nvSZvt~0T7D02uBZ=|J)7q=WuS941mCA!)LqAq|X4214kNYpj5BkJB^TQk}U z?GH3TD%&<8Dz`17NbirmW^_9|$;3%Wm}c<14xq*(~R+^*#Z`RUGY%$j`uA z&#t$Q@6X`(RcS=eG>}%unxbv84UprZ-nf}YO;E`clStyxhDh%9#lYfc48Y*9AO$pd zQ5mM1f7PwD<4RD==xfs@BUfXy35?-6@EedrmoAaRJdSEC$XEBRc;ICF;cQT7**8Z8 z3U+eW0Ew&G8sr$#T0A7CeZHSP^1P>hK&{V}BvyokNEz%xfSs^KdWo@^!=Kxx*+3FH zNOxPNGTeZUP3JED9P^cb{>?{HENn*@kse$G|Mc9Q-C|BBlwbj>5vj1ndZ$a!UH@)=tTC*u(IV3(FFOch`Jr|lZO?8JIE_4APdYCgck(eK%&c)j$cMFJIpukD`ZX@ z&b@DkC2DN-5sjkB_?u+)=sS>_WOi@Jv!1CU^BUpsS$KSw)Jm}IDUWE*8@Xg}}xG%Hy5u7~NKUZZTm%Am;TnX=yH1~=Kcj_kXg2Uniz`VB- z1Vp)ADlh4<13v0r`2#cHy~U3$=rB@zqDR z2ku+vmIt#h!FvO?AhZ+VFlB$ih}Yk#rWQAyvPNfKs>ymMb&r^}lEvZA7Ni5sl;&Z@ zc}a&og_uECL{I9QQN_pGt7*|FYby8_j|8N2Lwb6|l4PI0U(inQ%iWh;-S(*(WJq`N zl{Bbqlk-X5Raq^u1EB;Y_4oJdm#RNpt@y=H);`(|`?#jMO7O=HnW{U(Jk;BisX%)$ zr+ZW|S=yMU6K4)gvRh^;!o6S)PZ82%QQ}}HKi?tNX)ifJy-Q4zAb}Vz%aW~~k=4^f z5uc+!znx4VT45j1^rs^;q%hkSI%a^#aeb@A;K;xeX?FmdUIB4uKl4c-5+uGfgGE>f zzU$(hNFF$D5>LW_JeSjlaRwGtlD|hk0qA%l6i1jT1=42uG4040snsgvbJFiXG+U$E zysK)+QwirmQ7F>)`;5?N9$B}piC*N)ujy}t^4_Vdmsp2Rg3F{iDrz{y*$>`r@*8Ig zsx>%VG7)qpiTe~m&WGQ~qHmf~<~ku4Y04?eG?;*}a<4{ZZFRIBsW$Q*G!Z=Lc!$t{ z_Pv9oUV!!!-3XDilyjufd67r@7g5467Evh;Q2LgB=b zSqt>%t&vmQXUwk0W~yJR^-kc&z8PAu02NX4z3>*?I8%6{xZt=?!TnM%w#xzq?{nGA zFn(cKgKlg_TSf!Qc?yy#G2zP=BUq%v`THdEvW(wz$7L^T*sr;IuJg0UFHAIq2o%T~ zAXWH#xpj5wIPo{h?v!6ql4r^Klao(p8j`~2^EWBfJ5?(f&~-5YHruFLQv8zc+b{zt zg#!Zw(Z=Lr#_y?&u|%;s-$H0lQAIztQos%L8c6VEAXi6P@yyr_L>g>wHp0juogtWQ z&kBO5R2$9vQjo@WWhAP{q%antZp9k2#dJr9Ffy&lm=YpG=v7NWjQX*7S=->Xw`Ac> z+w7<%QD~$s%ouCc1EERVGWscDN&8=Di{pGyGwyh$$!77q16X3e{`yJgt9~PfFu3cC zL7_+Deaepa1^-+JhRkAujy^2$X!wvA?@NfWxyL5~R_bqRoxI2(EgK@WrpPyN7Vv7r3D2iM9>pR<`V&C*jjLYIkP0pRE;FtktMMm#GDGW4 zrlALfc@7q^i&SdMQVFCOyJT#L3Jdo{mVEB;*3s}2W&|fltsMK8mY|ii+?G$6B?>{$7S#Ncx0Do zqJMPG(^||RZMtlnwO4&!66N3IOj1OcsGN})cx#GH1A!F@hZH|vVxHWRV=yN$0Vr6; ze&3Y50k~NZVuzN)6e_FTcEs{kwHX$~dtqSv^r^mv6EXHPCS$8=9648HiZ%*GQWkRF zCVgjw`6R`2(ytj2Uunbe^io<5%9hG8y}KeZn3H}Eyl-ooo2gRY&|v)#v?0yqC+sUR z^%6~>Sq<=@>ahTF2YP1m5{t?&NBAIo-{$DEX>(cU{8>w>pkkc$!5=1{Vo+V*S_M(bgh4tlJ@{sdj_Lp?lUNy-A zZ+XM9psB$?1Wmw3FkY}Kn_an>EBihXJ{A-s(=e7}zAtL2b!?K<;6m}s%tsk9bJvJZ zViI`o2&j7!0i4S2xIfd_hA<-FQqNR*^N3$07linH;CU!2?UJKCl*;fw$>R+^;>%Mq zM!r_}yJlP4!8IPz1-(qg zj!h15h&q98)WPhA-`=N_I9T$S+T-jg3Tx~UPRHrotz?xPOwWf zIk@?>_K8~WeYmOG>~!rSLR+PYKA5>c7fA}o>9MN@zv&reR7etebM^=%VObIIzc?rS z5M>2y3joOQ!eJ{@gJY&kigcn&MDy)}Q7uy5jrl8t-ANjfF@B|Ti&AhURxswp*RdF+-8Jd@=z6y=e|cLsfh7EP5O=?)b=_P_%<() z@B%Y}{2eAx^7e5?+B#9XCNVmjXDx>gmC}ue&G3))+OMO09FJ1wtYE4?hth$iF`zUx zfs(`dmz2z#7k0x11+Dm7rB4-?yhc{+x6PJn6P{>a&tfoC=`%7B>o^=Zm^N;hSD(v55(kNCngb`J1X@DF>0ME?p)<11Z%}dDp5w)H!Nt9)__G zQKX*hmEaZOuz%mZG6d0YHD;RVWXM$qB~&@M*cN8Q$1_CRDcgA?xir*)Q=syAsVn$7 zS>+gtC5A00W&%kZV^nC!McXB_rdzn1>Oe~xo+IAw?_|<50yUD?yv-fO+1+vJa7I{x zs#3_V*!-Sjd;TC*24R4Da-N{<`P@O<_7RImVR6dCgisSnXBoxA+4dI zKq(v=)8%n=pw(<-W4)?Ni~$Nd94FkV2CnnEeHu2@Q=WO=eY!y?oO9Y`INzKLEvzE` z3L$bpc#B+Vd3Hg^zSiQ5Gk+BgEYRuUKE_`iqW!cCCao*1QL5Zs3xh7a3O;0V%drrO zDsSdux8&|RsJ<|r3c}ruL9ICUf=j@5`8dOL`Fd!cbwdM2aB4{a%&UsoC;c`9CNdow zG6D1s`jIEV&GBbht#b*DWRwmwwc@&&Fd0@e4?g-T_E)WjkZetVq*%=~HOwY!u*H(J zs^sFpl~p~Lg%hE5-IyB~vr+RgI>p=+kqDK+aLc&QmC(Z>K`+DlJ0Gthg=viF!4%~T zTTLHU0Zb=6G-J95tO}VoE?3X}O8rA`X-(5z$J4D&?pFit`cC?yv)I`kx1$_2#|xy2 zF4)+#e2F}4XHsfyy{+ihx zcY7oVSV?ao1}DSr;#p1wTbQIdM=Ob+?8E}nHRGDDxY9z9LtOyh@{G71;!F|YK5WN) zF#`+k4>r-<7~ahPyn$-(u%7;e1;^Z+nS!dTKc|1lKPH4UP5=Ci73bpL*KLt_?>%t1 z`tqG*T=(hW^cL&#z+Sq40?dz4a!TriWD{r^xER4FdK+> zI85aUcYSsza?yP@5}M)+eRL!+iyKS1g)=4x;YO~Rt~hAE2u70ZOe|DlO_d}? zZw?ZT&DutHzVn%iEQWLyRy-VCked2}YX@+PJd%f)Ke9DMY_*@fC3C9$84Uh*Pa+u4 z`=&Ki>dZOpmxb%x{#ZW(4{<$l;jQK`C(1b>Q>`f2CbO6L~?s-JD`5J1Tunno+YFarua!rk?+xaDqUICy7H>2ZW zzDr-pUyCVUi&e`R-sygD%}v`F3$HiRR2#iU)6mFs>?GT3w6a**g)HdjMC7`09&8z|SNllL_mJu(dv&$EclfJNW#o0y z2pMZ8P}YOXrO>Xybr{Y5w3)>&tzc*excKA7r@c5}HK4!EZPL&mGIz@tBUY zL`ECs)k8`eSH*&cUth46aX_X}XHk|3K>~Kki~{LRg-f*3Gnx#Q5B>Z~7VNp@C=wZ{ zHZ{zE(I3@8U2{p_?v~M;B#_OR=F$fd9O+W{Dlk_j&AMR>M6SyWmcM-yxhfLF@k)Qa z{LI&0bXL0}E^1U#g-f|qp;OOa!)eyT&x-DcVg$mr^gboIe8kjBKwPSR3bYo<3ZE~Q z;?^SB=Y;Y23P73rsV+Q4AhyQY76;Y9$Fn##(uMfFzFHo`F*A=L3!SU)Qq+EB0+_L*jAmUn>BS>|}w~P}y8SGUIYT!x(CZdweIrudq!<%J2$zJ)wA_)kUl3yHb@IK3rZX67#RHA&_ z<>MM_)hb_1a_yTJb3je;Veg4kEa`fei|NhLT@&p}3NXz?ndc7=2F8=0;d-=2iSa+` zO1NM!^rY3WHOA69MRzGFFMp#$K#imBB8kR*??EREQ@>f{nV6H&#qRBZUYRva1Qb}o zJ0P34Nzs#X*Rb&;04P72TPFYLKx=E}yQ>z~ zR?I+ZkudlE>(Bbble{$u<36O=_Y4pTjlS4C1_2CDnr(9yxfZ@*(Ickf~J<^J^R18zMVX<-b zYfonPgCklD=f*70Y7Q0LxFXnE<^@DI1yKIL81Zsn9aynOiX^TvM_g#aEOaary985p_F$Ub( zCm_Rhhitj}DI{{uM4%rt$y_{aQv_x3!cG$|teW_Dd2E3qR0C>3l?}5-1RbC*Rc~x5 zV{$G&z5m-pYcyg?l%yr8Zk3hwd%=+Aa-)*)ww&lwhNkL`tpUz{ZA&byPih&;HI~)m z$i{HpWYR<-ebJNBfu>~=Bu1+w6(5M(5gAj06j7ISbV^2RazQNv-jK96p*Wi1Zc>v# zUCg8shJ1yix`(Q)Yz=mL8}p)R9X=pHZ<%yQ$^w%=A^h3Kwq&!#Qx1MIgs_%V+A{9@ zkQ`B0a;bAxCeX$GKsPw5V3U z|0M0!u`s*7JH@mXITpmD&utP)S%Qv;^_@~$tAh@+vh}EHM+CeJ>ixMFt|*au6`Kzi zOpICoO9u8hG||c4VW`kN$hJ9*0T%*0J`wM2=y+lV8G$Y;2f~^JPNibjJGv9Sc+==b zch*#PNH^;Y@KVZ{_~-F{!45pT63s&kfpH6P467Y8%}oFkb^3WPiE99A83as^z!fHrVheD)=J`Qib|Z z7stdSpK70oW8ukr6~#&UrHzM}RFWe=>e(d0uXd>t-L+@v!nxyB4D__=7bW}m& zwvn495onp9cz!tgLg5Bv5QuiAkun2jFIu~x$_@-+74Wy>ZNv6vFB`K|q!Z?gT>*#( zlD?iIVDG8g=uc)Yd3jA|B;nM2h0M?vOpP5*-C^j0jPCY$K1ZW_=b56!d1CyFp7EPw zRqVSL-Hr!i)g{etVlye0i)_qXIxHqKZw->80m>GF8iuFYoVKF8{E?<_?h_QCFURUX z!k0>@R}E0ATZ?k5nP5$ATEx1y@#M>n3xK2b?|FNw8JiZ*d$U^mN&Jpi3?bu2%x96h zD;uY>ta>6x-<;=b}DncY#^Uv2h^YNDu%s^jkhvy_@DHb(};y4-TZXD=+ zj8Lze&Tp?gMq)xazes#yh;Gc0(pS=Mz*eFZUW{+mvH#IEe4|voecCq#T3oI*7OdBp z+j^y;Y2MS!eNg?SbsBjtEK`k@pX;P~3pbFyNtThxu^tMc#jVir;4rNrkZ^EVEvNIXWW3@$E_W;T zRB}c=|BS;$znt}EJ*(uABZJsu%UT~|GvD4crQv1vQH|oY>-Hwb zLEv5kdX=1i*MoT6V3e43RaJ4pG&5f)LwSWArj#=P3 zEarBhU67&Av0Y#vxk{kO1CI)~3CXX0&)XR_>lEKx14$FoUDY{fCtfEwFCXdi1>4DU#svP zQTA`n8FY8`SH5$s|#)Ig~XfOgV zv+@ubI!3h;R6x96U(J`8jt}kjem^`JjuG1-x}rAqQ>V8n6B_Z;M*3XmuiAVIgtt>i{I%nL#GET=rBVL*$@rtiB>?a$G2MS6B`w*SS+-_VsV9~O7fTQ zojQFNDJl8fKY-M1akxTzi4|+T`H;X9Bio)NqVQQf%1bHgU29-pRCDb`)fvWuv-p8{G39AjhH_?cOd0lZLpApMg$FN{ue`2{BqY!nEnJ(pHm?<>KX6 zrK$H~=|*E}u=?|qJnTi>+Nzk}oTFu#ec;E4e*E%e`}7_w9tnzl+5L-Zk)D?qlB!?J zEZq!tjLhA87|K8Dj4!PvS4~ z&5-*>3-h0#mhvN}fnhiAXx+8A?F?w>_Cd(gxcTUClHb}}bQf(G%D3d*!1q=sF1ESq z-W!ebU=IQh(@3|kNmCP-#Y1sG{4dT!#|pOu1eG2;X{}=}g1LzZcC#t@q~svwN9F+F z_Pgv50xzrVp8;N2!|QmJ%(yG0FSS$CrRpNn2sqkPX2y@X%<&~w3)R*q5Z*toG-24tW&NbI7Jp&yaW3%NlBY-OB{mz?;v++O-_AopM)fmqbEt@Q zv9t1gL#7e@?5cRsxxh&_+l+(O+t*UQHAZ=F#oD3_9h_(-J5mFHQd8(=3atTYc?Q;o z{+t~sax;lIB)J@@)Iqbwbk$riyX81B6@wto*w|%h=&nYkU$VOYxk_C4NWSM@77VS8 zcI!Co%mMjG!@o(L(esdYoO|h5zew{K-!hY#=6P%H^uzN)|JX83pJ(Osd@JZuHzmbfV<~4@O7myD(aks6 zCh)b6N;GsCEX>^udPk$XWcL)jQfzP*SVuCq9BB?p%1I;ar73Jv`Nc z;S*MF^Ko5sXOzyXdVhuh<(x|LlV*f%zm+^NS)0NsR^v)FM>)Y@Jfb%z_Q;M8@jwrR z5YvCUNnr3)fp3Q;=_+*PEf@n}aB2Qp`aYo9xjC)axtb%;BpwR`_LjCG78Q-mCujB&6Pl0h{jxh6;l=~zjz1~Pi zwDp$~DH=7(c9S!8J?r9ck2SfqKy+hB+g}-~HT7q|CD78{K~sClp!;c`D#jJk?ROo$ z>2n+@cO-64g9@1*6A)U6*9|&Ri_^GYLA@V zoAB*l?JrcH!l!z>n1{YSrinWu0wGRa@h+!Maj2)dQ@7-ZoEKW$8VA#sFW|=1K)l2* z#QcXJV*;H(lwKvT}Q8G$yAAG@=Bt3iv{Fh1_ph9OPu)9csF(vnJQ> z@~bo`%HS3ZSM+#3pH|unw%t`0nFhYW!NzV8uOm)iV2jYO{=i{m0`nIJC@(p%OH|FlkU1+sYG;B*2gp*DNNBYOZzK6 z2Yc6eGKo7u1-{@!x!s%KlEX#VAHH?mhXR{N-CyJt$A4Ue_$NeB^6Jc;QcE6*YFX{X zubNGUz{@+2en#(Kp{aG_9cj|%=QX#1!U6tdt2tYsdG3mye?E!QH}N5j{z^E9i0qA zZ&m1^%B@okCcU<%hDc(+RfCcED|vd`#D-jw*2%ffFAZ90%^r)q?CrNZ^5C`6ED=E~ zTLsj2{sNVCVe>UVNtAJ5yJc}AT+qHFZ}3)EbLB^B)~V>(9IFPLfMUEiyK`^|w8Cvy zWJ?KDX<=#^n$=^u4iRy6Ris}(T+$WVqo8K9*+|>fR`qL!+fK)LhTceDMfGBznRRfy z04_&F7$a!5t(W6;8$$`C8{=}aJM(OH@usr=dzCB{9rYXcF5Sg~m8x=@MieBvU6w2^ zY=FpOB~0s6#peS%BzS`0w%5P7^$QKOy6PGr!0EK^nr(y`MHTG!u&AYz)X-F2}SD`P?}FzKJ_6Z#*_VVmv4n zm0`@c-h(m_C{≺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 z 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∋FCtbF%KF@>|4ZBX=H?dg)!cDle6nWf;h*8I!| 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 literal 0 HcmV?d00001 diff --git a/contrib/README-FLASH.md b/contrib/README-FLASH.md index f950eb2f..2d839a3a 100644 --- a/contrib/README-FLASH.md +++ b/contrib/README-FLASH.md @@ -1,6 +1,6 @@ Use the ESP32 flashing tool. https://www.espressif.com/en/support/download/other-tools -https://www.espressif.com/sites/default/files/tools/flash_download_tool_v3.8.5.zip +https://www.espressif.com/sites/default/files/tools/flash_download_tool_3.9.0_0.zip Select "Developer mode" From 89bba4f63b6a7cd329b3ba9a25a58f9c3d1c4e3d Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 09:24:38 -0800 Subject: [PATCH 28/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b98f2468..57b862a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: run: pio run -t buildfs -e esp32-poe-iso - name: Build firmware package - run: cwd + run: pwd - name: Upload firmware package Artifact run: ls \ No newline at end of file From d9621252dd7b836bc4761e625421a6e59a2511b5 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 09:28:31 -0800 Subject: [PATCH 29/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57b862a7..46a5ce36 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,4 +32,4 @@ jobs: run: pwd - name: Upload firmware package Artifact - run: ls \ No newline at end of file + run: ls .pio/build/esp32-poe-iso/ \ No newline at end of file From cafd4fa9f93c9407f42bac87369267b32a0ae968 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 10:26:49 -0800 Subject: [PATCH 30/97] ... --- .github/workflows/build.yml | 30 +++++++++++++++++-- README.md | 2 +- ...{README-FLASH.md => README-FLASH-ESP32.md} | 0 3 files changed, 28 insertions(+), 4 deletions(-) rename contrib/{README-FLASH.md => README-FLASH-ESP32.md} (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 46a5ce36..95e6ce4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,9 @@ name: CI build on: [push, workflow_dispatch] +env: + PP: AD2IoTRelease + jobs: build: runs-on: ubuntu-latest @@ -16,20 +19,41 @@ jobs: ~/.cache/pip ~/.platformio/.cache key: ${{ runner.os }}-pio + - uses: actions/setup-python@v4 with: python-version: '3.9' + - name: Install PlatformIO Core run: pip install --upgrade platformio + - name: Install zip + uses: montudor/action-zip@v1 + - name: Build esp32-poe-iso run: pio run -e esp32-poe-iso - name: Build spiffs.bin run: pio run -t buildfs -e esp32-poe-iso - - name: Build firmware package - run: pwd + - name: Create base Artifact release package structure + run: | + mkdir $PP + cp README.md CHANGELOG.md LICENSE $PP/ + mkdir $PP/esp32 + cp contrib/README-FLASH-ESP32.md contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png $PP/esp32/ + mkdir $PP/esp32/esp32-poe-iso-webui + cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/firmware.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/bootloader.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/partitions.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/ota_data_initial.bin $PP/esp32/esp32-poe-iso-webui/ + + - name: Zip Release files + run: zip -qq -r $PP.zip $PP - name: Upload firmware package Artifact - run: ls .pio/build/esp32-poe-iso/ \ No newline at end of file + uses: actions/upload-artifact@v3 + with: + name: AD2IoT-Release-Package + path: $PP \ No newline at end of file diff --git a/README.md b/README.md index dedafc55..3d1bfc5b 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ To switch to a specific build over the internet using OTA include the buildflag If the upgrade fails it may be the result of low memory on the device. Try disabling features restart the device and try again. Example. ```webui disable Y```. If all else fails install the latest release of the AD2IoT firmware over USB. -See the README-FLASH.MD inside the release file for instructions on flashing the firmware over the ESP32-POE-ISO USB port. +See the README-FLASH-ESP32.md inside the release file for instructions on flashing the firmware over the ESP32-POE-ISO USB port. ### 3.1. webUI build (webui) - alarmdecoder_webui_esp32.bin - Enabled components: Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd. diff --git a/contrib/README-FLASH.md b/contrib/README-FLASH-ESP32.md similarity index 100% rename from contrib/README-FLASH.md rename to contrib/README-FLASH-ESP32.md From daac10316eb2dfa525f3a267c7f5b7fbef08e39c Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 10:34:30 -0800 Subject: [PATCH 31/97] ... --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95e6ce4d..03b7f8c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,7 @@ name: CI build on: [push, workflow_dispatch] env: - PP: AD2IoTRelease + PP: AD2IoT-Release jobs: build: @@ -56,4 +56,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: AD2IoT-Release-Package - path: $PP \ No newline at end of file + path: AD2IoT-Release.zip \ No newline at end of file From ff0946b2a1871a2579d6f1d3f780a13114be6f3a Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 10:43:10 -0800 Subject: [PATCH 32/97] ... --- .github/workflows/build.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 03b7f8c2..097a89a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,9 +27,6 @@ jobs: - name: Install PlatformIO Core run: pip install --upgrade platformio - - name: Install zip - uses: montudor/action-zip@v1 - - name: Build esp32-poe-iso run: pio run -e esp32-poe-iso @@ -49,11 +46,8 @@ jobs: cp .pio/build/esp32-poe-iso/partitions.bin $PP/esp32/esp32-poe-iso-webui/ cp .pio/build/esp32-poe-iso/ota_data_initial.bin $PP/esp32/esp32-poe-iso-webui/ - - name: Zip Release files - run: zip -qq -r $PP.zip $PP - - name: Upload firmware package Artifact uses: actions/upload-artifact@v3 with: name: AD2IoT-Release-Package - path: AD2IoT-Release.zip \ No newline at end of file + path: AD2IoT-Release \ No newline at end of file From 6eca9c7ba5b69edcefdafc7c43ecaaa3304dfc21 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 11:04:32 -0800 Subject: [PATCH 33/97] .. --- ...ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png | Bin 126746 -> 125778 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png b/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png index 5b3f37d275b314e572f98c66431e147b798e552b..eae14081eaab9f12401760e47475d5d5fe663c53 100644 GIT binary patch delta 104761 zcmV)sK$yRp-Urgw2aqHITahIoe|8)>(ro`@6}<$^!*Vd5^X=d*|6N05Ql!LEsj6G5 zlE`3W1O|6=Glv5*`~UslG5`6`e_Tl3nwUz>EoaNG*kbdYFRFchjr*sw@&0*#X+*#m)8$Gm-N;1oo)X0u+4S8cCYW->m}}e|NBAjFI?xV^y3G;zpjt3f7i$BfxiCy zpjQimd){o<>jSR`1^;SMe7>Kr7UfpUm#(e(dUJeTsz3gZq4=D#E0I5=x25F9*VWrt z7|*4Kp6T0tPt%u`Dr!W==iNm`a!z4(iNtX zCeYIMdeN(^8qCjQ^J9$uf8y7lbj$LRvvu>QS^N0=C%gIh>L-Dfg_&gNm^K_rH>bae!7d>XiBELHI?&AH5 z`-VpGek$|3*le)c$`|_G_+4$c6PsFg;%S4goAb>5anUW;-EsT=e?8r#iP3Lg_}lww ze7F}YlhphSGKQ$%?)VZK9jI8!#D)S_{YP8eeQmq1o37er>~h@d9S?JSpr$*(@83WF(!2&{Fx_FUbgXPI@j*_U5o;ovK;vg&H9Z?`d}9e3J!mtA+;{a|V*oOsg7rfWd8Hl3B1+pBt7+Xc_;ZBj9dkPOp686P+uALR1H89h$2g&6 zd|;Q`1V)c=laF2DzMt7JBcIjEJd06(YRBag#>kL{!HE7m4!;Zo^Rlsx5YIHgU1qE^ z9D@GU=`fVz#-M|^$S7{p$2??#HS+9`XG}cnw7fe5+Szj>(n{8X{FfBQ)DeMA5GBhBCS{ZAih{(Lxp|48$1X6U}0c(zY{#x8Ah zc4=+ovbnLf)Bnr71M8G-5*i647fG=uR9ix2`xw zbl5PAmON(g>-&@^%R2nfpdHn%c?<>Bcn%@R!TFI(Iz;|5SUE$ptI|d0>)6C&)BzX#AWq#=3=;V<(m2VVvq2Mv$i{JB?tR)qCaq? zLeHQf&2CJ|5MEj1XM5DIy_z7A_RgGo}Kv)Mqa% z<&9{`6Vvf~$H`LaMFh+oKhej>7+n!i2f(yjhG*lIf?Sv3LCeyNNge%M(+Wr5exdVN{WFfExjWqC<5m&=Z5}y^0Fol*| zV`Abeq{}pP7Bqj!bC*l}zk86?p}ZjWy}`N$P!TGC)IcG<%Q4VU#^&OJ*Q7RlG!8P# z_#hY1CDsb_AhH+Ui>eE#YUo(>e{grEQEYqC*K()Jq{|rj0}PB6{#+S* z!O~>@@P1fu-?5%0J@MR`0>d+h7`10q3p&7I*&e>07mig*)Ij;Zb^jYeze7-H7Thu} zpC&^*CR#EW26h&vWAb}9-b{lxehgYMKF3GM+XL}w@LQ;(dZPr$ ze<@7E`b38B9rlSQ>)ygQx@8PM+fES%n_-54p)ik;glNeqW+HT8KA3(}>O&t?z)|SR zFyjaIqByjm<;DL8=650w20Bbl%=vlU{c*28cDNUK$_reYU_TGm7jNcI9AhY$N<=w6 zaAD*xZ(fjR1)uc{HXpr^TnSO_c0OWTf0BwZ8N8^0_6+E79qm;ouRyZJJ}0KlsC&F= z;6@|%76_Fgu3$T@@QtX2q9l}^@M_WU^r&WeXz!T#g@3)CNEu&1v1I+s_*!c!NYgnw zLU02PY%%cv4B!zC5i-S>UKn>~WiiqLYwC=KbQPKzm5Urrjj6p}Fn!}DjHS0de~jyW zE|=BfL6aIn5uRT_q`sv7Dq#;}A|mb@aL}eOjnjOHQ7WJeJZKHM^$xaNu53UkPyzyJ`YaBbu^26kYJ<;zn+FOC&{Yk^(G~dgZNTLs5fW> zdI_oo=$IhBa5|a`oD}|Y+uT<0O^6J=&?)pdVGc|nMliZFwT6;Znt(X(e_al?I0G8P z%BHyAf^ID4GkGi|WiPZwxC6QXfz^AIz+${1GnH5cooI@qh);;t&Hx|t5Q$j_Aj7B% zVBQaA3_2zvFN0;78Gj0P-)o-u2#Cb6mz8^{Tpq&^m=iO%rdS4T-1;$L1zS6nUiHy= zAGirFDy!~$5d6ScfCnxCf7|qbPLoP*%*><-Wwn|^7r?9_0P8*QvYx@sf&AQd_CfoE z{ehQ6&9;YR4xGaf&v;f0Mf?V`<8eVk3}L)23>MvMTei~;-p=5_l|%#%Lxq0l+NcM= zI@|2?=3!5`*6 zPS4Uq_8p-d$^__rYGFG$7BMaJh=Fn7Vh-$(ndB(cg9zg!kciwj(IBG|xS_&jq3`vM zgiCVl8tZherZKA0f7ccZBqS;(%`frB{2Fi)gpp{H#QGtuXQz~&sXk2%JKWZ%neQ}7 z7~mV-RG1Ky+Lk8Q37Nj*$SSmYbDBFQg2#BljuE0YiwjEc^8 zkOg{nh=|34h*tO#9U;mxBtY$C6cVjQ<^(KLG!KARr(iYcsnHt2Wm^QG;L4->fO-6t zDN&$P3$gHGeJd2f%zia(1E-2BgQ!qFiN+eDdZ}^9}J3xKuYM@aViW~ zrCUD&@y~HM%@EMZj2);^iN26kT&P`NTLWK!o&?6Ff8aUbE&v7CF^>LfuM$wEAl-(Z zfyRV}JpEiWDyFp%76>xq8>AINT!0E>?IHxzpTv+8_8`OMCJ#GGbb@UJ-2@&MF9>Xm zJdTZTCa>U?K;g zK=zCW;BaoPgncCgV2nl22UCfF7X&RG?~QN-w;=k%tCf9hPmH-NAr;+;YP@p?)pgsW zjbcHOVrMS8ivA*?(Bff$Z*Zy(Dz3gLs7E#)=u|IHThit$ zl-@W-pXM2kR$t5+kQ`Vo?4jLv(20+?(DC~KjLbeasq6g?3Novmb-%g=i@!^x5OVk2fx(!Vd#4JN=GFbR;XFA>xgi}zVK6DU0{zxB z(kFtt7RowP7PB-k$_`85VHq<_rh|Wp;pali#7G4Nq(8m_s}=U!fUD!Mj$xP( zcJ#!?XBoaO4l^Y1daTf6gaCY!RskH0=V^#6L_5HhT|#J~Sd-rg<{pdqQCHOJQYTG{ zc)%>0Lz*kY2CRz~SR|<&bCMw#4G>FkV}f>m6bafHdbeQ|v3eLY zV6Yp0!q*3NT#weB6J!)(4x=JC!!CHyI!b4tjX|%-%XgIHR=O|cz(=nm@g4vSG=XfR zdc*2ZW^^%Hf@N@GcME?B-ThvYe}1Uex3Yad=##P?5)R0GAMgWZ7D7iM9_2jGeC%F| zxM~p`f70mTj8D>6EX7LO%GUd0e3X^~d!-EAzWzjK6TFs;B z9cBQ}Yzo;}NN)i9>K++_B#9o<)o`~7J*c!{9*lpL7-ZyDRT>4wWr>wqsKt;P!$_+J zkw;7h&hM1m!m(x%|HuC5A3c8~E<(!DlbI3P)8s6CP>_Q5-x-W_ZmMs|qVxxYy#y

bSgx(m$~ku^}c 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 delta 105952 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%0AS*tgEItS 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

kE6;PcIxc*-y_-uNmgqPtP4T-%rmImefMe lw)fv3{Qv!L5bxLmouBCE`;jvnTj=n0?68`0%0VNq{{zm3&~X3& From 24f7757b816521c20867d281ee26aa64858efeb9 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 11:47:24 -0800 Subject: [PATCH 34/97] ... --- .github/workflows/build.yml | 11 +++++++---- contrib/README-FLASH-ESP32.md | 28 +++++++++++++++++++--------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 097a89a4..fd6a45e7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,16 +27,19 @@ jobs: - name: Install PlatformIO Core run: pip install --upgrade platformio + - name: Create base Artifact release package structure + run: | + mkdir $PP + cp README.md CHANGELOG.md LICENSE $PP/ + - name: Build esp32-poe-iso run: pio run -e esp32-poe-iso - - name: Build spiffs.bin + - name: Build spiffs.bin for esp32-poe-iso run: pio run -t buildfs -e esp32-poe-iso - - name: Create base Artifact release package structure + - name: Add esp32-poe-iso build to release package run: | - mkdir $PP - cp README.md CHANGELOG.md LICENSE $PP/ mkdir $PP/esp32 cp contrib/README-FLASH-ESP32.md contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png $PP/esp32/ mkdir $PP/esp32/esp32-poe-iso-webui diff --git a/contrib/README-FLASH-ESP32.md b/contrib/README-FLASH-ESP32.md index 2d839a3a..294e2394 100644 --- a/contrib/README-FLASH-ESP32.md +++ b/contrib/README-FLASH-ESP32.md @@ -1,13 +1,23 @@ -Use the ESP32 flashing tool. -https://www.espressif.com/en/support/download/other-tools -https://www.espressif.com/sites/default/files/tools/flash_download_tool_3.9.0_0.zip +### Flashing ESP32 with AD2IoT firmware +#### Requirements +- ESP32 Flashing tool + - https://www.espressif.com/en/support/download/other-tools + - https://www.espressif.com/sites/default/files/tools/flash_download_tool_3.9.3.zip -Select "Developer mode" -Select "ESP32 DownloadTool" +- USB Drivers + - Board specific drivers may be required programming. + - ESP32-POE-ISO USB drivers + - https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware -Match settings to provided example screen capture ESP32-DOWNLOAD-TOOL-UPLOADING-FIREMWARE.png -Connect the ESP32 board via USB and be sure it registers as a com port in device manager. Drivers may be required. -Press start. -Use Putty to connect to the COM port and configure the device. +#### Using the ESP32 DOWNLOAD TOOL + - Select "Developer mode" + - Select "ESP32 DownloadTool" + - Match settings to provided example screen capture ESP32-DOWNLOAD-TOOL-UPLOADING-FIREMWARE.png + - Connect the ESP32 board via USB and be sure it registers as a com port in device manager. + - Press start. + +#### Configure the firmware operation +- Use Putty or other serial terminal program to connect to the COM port of the ESP32 board. +- Using the command line interface(CLI) to configure the device and confirm communication are correct to the AlarmDecoder hardware AD2pHat board or remote SER2SOCK connected AD2* device. \ No newline at end of file From 91cbef172b5d4e836ffe6e319ad39cf5f24f6ca1 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 12:12:33 -0800 Subject: [PATCH 35/97] ... --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f25f82c..1232c795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Releases ## [1.1.0 P2] - 2023-01-?? Sean Mathews - coder @f34rdotcom Changes: - - Add Github action build test. + - Add CI using github Actions to test building and create an Artifact with the compiled firmware package and instructions. For more info on Artifacts see https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts + - Removed travis-ci support. - Fix missing settings and organized sdkconfig.defaults. - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. - TODO: Find more time to audit and cleanup code. @@ -42,7 +43,7 @@ Changes: - Get STSDK building again. - Improved documentation fixing errors and adding config file examples in each section. ### Change log - - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :( + - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :(. No loss now we can generate a release file something that seemed much more difficult with travis-ci. Add a workflow file named ```CI build``` to test and build a release file with compiled firmware and instructions. See the ```CI build``` build Summary page for the Artifacts file ```AD2IoT-Release-Package``` - [X] SM CORE: Docs improvements. - [X] SM STSDK: Build and uploaded set keys but was not able to adopt. '''Error 81-001 Something went wrong''' - [X] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. From 674d68596a134183fa280dc3bc7ec3e1df37f306 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 12:31:01 -0800 Subject: [PATCH 36/97] ... --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd6a45e7..3783463a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,12 @@ jobs: with: python-version: '3.9' + - name: Install required packages + run: sudo apt-get install -y git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 + + - name: goto done + run: exit 1 + - name: Install PlatformIO Core run: pip install --upgrade platformio From 62dd3a543887e01eed82fd4634417dfcf914931e Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 12:55:35 -0800 Subject: [PATCH 37/97] ... --- .github/workflows/build.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3783463a..35f5c420 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,10 +24,20 @@ jobs: with: python-version: '3.9' - - name: Install required packages - run: sudo apt-get install -y git wget flex bison gperf python3 python3-pip python3-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 + - name: Install required packages for st-device-c-ref build + run: sudo apt-get install -y gperf cmake ninja-build ccache dfu-util - - name: goto done + - name: Checkout st-device-sdk-c-ref + uses: actions/checkout@v2 + with: + submodules: true + repository: SmartThingsCommunity/st-device-sdk-c-ref + path: ./.st-device-sdk-c-ref + + - name: setup build environment for stsdk-c-ref + run: ls -l .st-device-sdk-c-ref + + - name: goto done early abort for testing. run: exit 1 - name: Install PlatformIO Core From e458ca6100c40f24106ce36788a793de4a30ce70 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 12:59:18 -0800 Subject: [PATCH 38/97] ... --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35f5c420..18eb0c24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,12 +30,12 @@ jobs: - name: Checkout st-device-sdk-c-ref uses: actions/checkout@v2 with: - submodules: true repository: SmartThingsCommunity/st-device-sdk-c-ref path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref - run: ls -l .st-device-sdk-c-ref + run: cd .st-device-sdk-c-ref + run: python setup.py - name: goto done early abort for testing. run: exit 1 From a0d18d7f8b4ad33d947d6401dded461d6728589e Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:00:34 -0800 Subject: [PATCH 39/97] ... --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18eb0c24..84ca570b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,8 +34,9 @@ jobs: path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref - run: cd .st-device-sdk-c-ref - run: python setup.py + run: | + cd .st-device-sdk-c-ref + python setup.py - name: goto done early abort for testing. run: exit 1 From 93d6232ff7cd55f188effa7699e9c06d6f66a31b Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:01:43 -0800 Subject: [PATCH 40/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 84ca570b..a40e98a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: - name: setup build environment for stsdk-c-ref run: | cd .st-device-sdk-c-ref - python setup.py + python setup.py esp32 - name: goto done early abort for testing. run: exit 1 From 3c41b91f60871efe4f6e9aae66290b858d93dca4 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:08:17 -0800 Subject: [PATCH 41/97] ... --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a40e98a8..33640d2a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,6 +36,8 @@ jobs: - name: setup build environment for stsdk-c-ref run: | cd .st-device-sdk-c-ref + git config user.name "GitHub Actions Bot" + git config user.email "<>" python setup.py esp32 - name: goto done early abort for testing. From 82dc07ca46c46734cf6be93beaab6cf335141297 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:14:33 -0800 Subject: [PATCH 42/97] ... --- .github/workflows/build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 33640d2a..8dbb6af1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,9 +36,11 @@ jobs: - name: setup build environment for stsdk-c-ref run: | cd .st-device-sdk-c-ref - git config user.name "GitHub Actions Bot" - git config user.email "<>" + git config --global user.name "GitHub Actions Bot" + git config --global user.email "<>" python setup.py esp32 + ln -s ../ apps/esp32/AlarmDecoder-IoT + python build.py esp32 AlarmDecoder-IoT - name: goto done early abort for testing. run: exit 1 From 06af21c772fad53f33b23ff3e5b1cfac0c9f88f2 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:21:57 -0800 Subject: [PATCH 43/97] ... --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8dbb6af1..1ef0715b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,7 @@ jobs: git config --global user.email "<>" python setup.py esp32 ln -s ../ apps/esp32/AlarmDecoder-IoT + ls -l apps/esp32/ python build.py esp32 AlarmDecoder-IoT - name: goto done early abort for testing. From af36798f350ba042ae177b0b4e59431502d490b6 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:27:53 -0800 Subject: [PATCH 44/97] ... --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ef0715b..40cb3d80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,6 +41,7 @@ jobs: python setup.py esp32 ln -s ../ apps/esp32/AlarmDecoder-IoT ls -l apps/esp32/ + ls -l apps/esp32/AlarmDecoder-IoT python build.py esp32 AlarmDecoder-IoT - name: goto done early abort for testing. From 8249f90fb4bc14fbddd0edc4423a4c9b08337870 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:33:30 -0800 Subject: [PATCH 45/97] ... --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 40cb3d80..ff8cdcaf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,7 @@ jobs: git config --global user.email "<>" python setup.py esp32 ln -s ../ apps/esp32/AlarmDecoder-IoT + pwd ls -l apps/esp32/ ls -l apps/esp32/AlarmDecoder-IoT python build.py esp32 AlarmDecoder-IoT From 0fe9ba0a50f23da5635631d768337888ce0793aa Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:37:20 -0800 Subject: [PATCH 46/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff8cdcaf..a402f5ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 - ln -s ../ apps/esp32/AlarmDecoder-IoT + ln -s /home/runner/work/AlarmDecoder-IoT/AlarmDecoder-IoT apps/esp32/ pwd ls -l apps/esp32/ ls -l apps/esp32/AlarmDecoder-IoT From 5de75877d4c1ed4307fd57425fc3b3cf1a1ce8f3 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:52:00 -0800 Subject: [PATCH 47/97] .. --- .github/workflows/build.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a402f5ff..a542cf44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,11 @@ jobs: with: python-version: '3.9' + - name: goto done early abort for testing. + run: | + python -c "import os; print(os.environ)" + exit 1 + - name: Install required packages for st-device-c-ref build run: sudo apt-get install -y gperf cmake ninja-build ccache dfu-util @@ -39,15 +44,13 @@ jobs: git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 - ln -s /home/runner/work/AlarmDecoder-IoT/AlarmDecoder-IoT apps/esp32/ + ln -s ../../AlarmDecoder-IoT apps/esp32/ pwd + echo os.environ ls -l apps/esp32/ ls -l apps/esp32/AlarmDecoder-IoT python build.py esp32 AlarmDecoder-IoT - - name: goto done early abort for testing. - run: exit 1 - - name: Install PlatformIO Core run: pip install --upgrade platformio From b016cc8a4dfe0701c41ed5d9a4c215758c456db3 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:53:51 -0800 Subject: [PATCH 48/97] .. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a542cf44..22508234 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ on: [push, workflow_dispatch] env: PP: AD2IoT-Release + SHELL: /bin/bash jobs: build: From aa340c1ad6f4e7840e6786b2514e6ed2af9c298d Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 13:55:06 -0800 Subject: [PATCH 49/97] .. --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 22508234..fed8d627 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,11 +25,6 @@ jobs: with: python-version: '3.9' - - name: goto done early abort for testing. - run: | - python -c "import os; print(os.environ)" - exit 1 - - name: Install required packages for st-device-c-ref build run: sudo apt-get install -y gperf cmake ninja-build ccache dfu-util @@ -52,6 +47,11 @@ jobs: ls -l apps/esp32/AlarmDecoder-IoT python build.py esp32 AlarmDecoder-IoT + - name: goto done early abort for testing. + run: | + python -c "import os; print(os.environ)" + exit 1 + - name: Install PlatformIO Core run: pip install --upgrade platformio From 0dfb6d2c19b38be9470da38b302a05f05f0c5666 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:05:31 -0800 Subject: [PATCH 50/97] .. --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fed8d627..74654760 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,6 +5,7 @@ on: [push, workflow_dispatch] env: PP: AD2IoT-Release SHELL: /bin/bash + TERM: 'xterm-256color' jobs: build: @@ -40,9 +41,9 @@ jobs: git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 - ln -s ../../AlarmDecoder-IoT apps/esp32/ + ln -s ../../../AlarmDecoder-IoT apps/esp32/ pwd - echo os.environ + python -c "import os; print(os.environ)" ls -l apps/esp32/ ls -l apps/esp32/AlarmDecoder-IoT python build.py esp32 AlarmDecoder-IoT From 0c4c081fb77853d8cec8efb34281caba885946c6 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:06:38 -0800 Subject: [PATCH 51/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 74654760..0c80724d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: [push, workflow_dispatch] env: PP: AD2IoT-Release SHELL: /bin/bash - TERM: 'xterm-256color' + TERM: 'xterm-256color' jobs: build: From dd16da3ce93db8d4621072a2c8a3830adf48e4d1 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:14:14 -0800 Subject: [PATCH 52/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c80724d..a5d8f94c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,7 @@ jobs: pwd python -c "import os; print(os.environ)" ls -l apps/esp32/ - ls -l apps/esp32/AlarmDecoder-IoT + ls -l apps/esp32/AlarmDecoder-IoT/ python build.py esp32 AlarmDecoder-IoT - name: goto done early abort for testing. From 10f363188d4e4ba3ef1dd3ba84a266430aede497 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:21:49 -0800 Subject: [PATCH 53/97] .. --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a5d8f94c..ad76ea97 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,8 @@ jobs: git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 - ln -s ../../../AlarmDecoder-IoT apps/esp32/ + . ./export.sh + ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ pwd python -c "import os; print(os.environ)" ls -l apps/esp32/ From 3df2d427017fafa184261f537b475ed8319d8852 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:28:36 -0800 Subject: [PATCH 54/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ad76ea97..ec215c35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 - . ./export.sh + #. ./export.sh ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ pwd python -c "import os; print(os.environ)" From b210fc6c4323be6d344b60795217e03b9c5ac006 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:36:37 -0800 Subject: [PATCH 55/97] .. --- .github/workflows/build.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ec215c35..3e37a933 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,12 +41,7 @@ jobs: git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 - #. ./export.sh ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ - pwd - python -c "import os; print(os.environ)" - ls -l apps/esp32/ - ls -l apps/esp32/AlarmDecoder-IoT/ python build.py esp32 AlarmDecoder-IoT - name: goto done early abort for testing. From df059a6b3813563b254b55a982f333c06dd987cc Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 14:37:19 -0800 Subject: [PATCH 56/97] .. --- sdkconfig.defaults | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 8cdb3515..3b433104 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -114,7 +114,7 @@ CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable CONFIG_AD2IOT_TOP=y -CONFIG_AD2IOT_FTP_DAEMON=y +CONFIG_AD2IOT_FTP_DAEMON=n CONFIG_AD2IOT_MQTT_CLIENT=y CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y From 8b875095c05e57d7327f0fa6bd094c360ef7db4d Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 16:01:31 -0800 Subject: [PATCH 57/97] .. --- .github/workflows/build.yml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3e37a933..2387a027 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,13 @@ jobs: with: python-version: '3.9' + - name: Create base Artifact release package structure + run: | + mkdir $PP + cp README.md CHANGELOG.md LICENSE $PP/ + mkdir $PP/esp32 + cp contrib/README-FLASH-ESP32.md contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png $PP/esp32/ + - name: Install required packages for st-device-c-ref build run: sudo apt-get install -y gperf cmake ninja-build ccache dfu-util @@ -35,7 +42,7 @@ jobs: repository: SmartThingsCommunity/st-device-sdk-c-ref path: ./.st-device-sdk-c-ref - - name: setup build environment for stsdk-c-ref + - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings run: | cd .st-device-sdk-c-ref git config --global user.name "GitHub Actions Bot" @@ -44,29 +51,25 @@ jobs: ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT - - name: goto done early abort for testing. + - name: Add esp32-poe-iso stsdk build to release package run: | - python -c "import os; print(os.environ)" - exit 1 + mkdir $PP/esp32/esp32-poe-iso-webui + cp build/partition_table/partition-table.bin $PP/esp32/esp32-poe-iso-stsdk/partitions.bin + cp build/alarmdecoder_ad2iot_esp32.bin $PP/esp32/esp32-poe-iso-stsdk/firmware.bin + cp build/bootloader/bootloader.bin $PP/esp32/esp32-poe-iso-stsdk/ + cp build/ota_data_initial.bin $PP/esp32/esp32-poe-iso-stsdk/ - name: Install PlatformIO Core run: pip install --upgrade platformio - - name: Create base Artifact release package structure - run: | - mkdir $PP - cp README.md CHANGELOG.md LICENSE $PP/ - - name: Build esp32-poe-iso run: pio run -e esp32-poe-iso - name: Build spiffs.bin for esp32-poe-iso run: pio run -t buildfs -e esp32-poe-iso - - name: Add esp32-poe-iso build to release package + - name: Add esp32-poe-iso webui build to release package run: | - mkdir $PP/esp32 - cp contrib/README-FLASH-ESP32.md contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png $PP/esp32/ mkdir $PP/esp32/esp32-poe-iso-webui cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-webui/ cp .pio/build/esp32-poe-iso/firmware.bin $PP/esp32/esp32-poe-iso-webui/ From d8bd4d1615d350b19fceffb1f8f985a1519cd4f7 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 16:17:27 -0800 Subject: [PATCH 58/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2387a027..1e597224 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,7 +53,7 @@ jobs: - name: Add esp32-poe-iso stsdk build to release package run: | - mkdir $PP/esp32/esp32-poe-iso-webui + mkdir $PP/esp32/esp32-poe-iso-stsdk cp build/partition_table/partition-table.bin $PP/esp32/esp32-poe-iso-stsdk/partitions.bin cp build/alarmdecoder_ad2iot_esp32.bin $PP/esp32/esp32-poe-iso-stsdk/firmware.bin cp build/bootloader/bootloader.bin $PP/esp32/esp32-poe-iso-stsdk/ From aa71b61574d550215fac3c66bb554a9e95916a96 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 16:31:47 -0800 Subject: [PATCH 59/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e597224..32c18d0b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: cd .st-device-sdk-c-ref git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" - python setup.py esp32 + python setup.py esp32 > /dev/null 2>&1 ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT From 7e677b71822aebd00366e103accb3c73b1f84397 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 16:33:23 -0800 Subject: [PATCH 60/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 32c18d0b..b0c1b1f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: run: sudo apt-get install -y gperf cmake ninja-build ccache dfu-util - name: Checkout st-device-sdk-c-ref - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: SmartThingsCommunity/st-device-sdk-c-ref path: ./.st-device-sdk-c-ref From 84bb9028a953b5ef0ce8d2f753a517f2cdc75070 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 17:28:05 -0800 Subject: [PATCH 61/97] .. --- .github/workflows/build.yml | 3 ++- components/ftpd/ftpd.cpp | 7 +++++++ sdkconfig.defaults | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b0c1b1f3..a80afb98 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,9 +47,10 @@ jobs: cd .st-device-sdk-c-ref git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" - python setup.py esp32 > /dev/null 2>&1 + python setup.py ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT + cd .. - name: Add esp32-poe-iso stsdk build to release package run: | diff --git a/components/ftpd/ftpd.cpp b/components/ftpd/ftpd.cpp index b306cc20..5b978d88 100644 --- a/components/ftpd/ftpd.cpp +++ b/components/ftpd/ftpd.cpp @@ -33,7 +33,14 @@ static const char *TAG = "FTPD"; // module specific includes +/// Problem with dirent included as "C" already by STSDK build. +#ifdef __cplusplus +extern "C" { +#endif #include +#ifdef __cplusplus +} +#endif #include #define FTPD_COMMAND "ftpd" diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 3b433104..8cdb3515 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -114,7 +114,7 @@ CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable CONFIG_AD2IOT_TOP=y -CONFIG_AD2IOT_FTP_DAEMON=n +CONFIG_AD2IOT_FTP_DAEMON=y CONFIG_AD2IOT_MQTT_CLIENT=y CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y From e983ca8741ea0ce6c8264116c3e1d9d8cc3ad5d8 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 17:30:08 -0800 Subject: [PATCH 62/97] .. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a80afb98..b64e8339 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: cd .st-device-sdk-c-ref git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" - python setup.py + python setup.py esp32 ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT cd .. From dc0b782128101cb0c6a3f8cbb41c0104af7fdd91 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 17:42:20 -0800 Subject: [PATCH 63/97] ... --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b64e8339..8d67424d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,9 @@ jobs: cp contrib/README-FLASH-ESP32.md contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png $PP/esp32/ - name: Install required packages for st-device-c-ref build - run: sudo apt-get install -y gperf cmake ninja-build ccache dfu-util + run: | + sudo apt-get install -y gperf cmake ninja-build ccache dfu-util + pip install qrcode - name: Checkout st-device-sdk-c-ref uses: actions/checkout@v3 From a7c0ac4a431271ddb3f6731039d9c299797d5c19 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 22:20:04 -0800 Subject: [PATCH 64/97] STSDK firmware builds but I still can't adopt. --- .github/workflows/build.yml | 1 - CHANGELOG.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8d67424d..cfdca6e2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,6 @@ jobs: - name: Install required packages for st-device-c-ref build run: | sudo apt-get install -y gperf cmake ninja-build ccache dfu-util - pip install qrcode - name: Checkout st-device-sdk-c-ref uses: actions/checkout@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1232c795..bc18c1b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] Open issues ### SM - Sean Mathews coder at f34r.com -- [ ] FTPD: Does not build with stsdk. - [ ] API: Add countdown tracking for DSC/Ademco exit mode - [ ] CORE: Needed feature ad2_fw_update() to update AD2* firmware. - [ ] CORE: TODO: Monitor limited sockets look for ways to reduce if possible. @@ -45,6 +44,7 @@ Changes: ### Change log - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :(. No loss now we can generate a release file something that seemed much more difficult with travis-ci. Add a workflow file named ```CI build``` to test and build a release file with compiled firmware and instructions. See the ```CI build``` build Summary page for the Artifacts file ```AD2IoT-Release-Package``` - [X] SM CORE: Docs improvements. + - [X] SM FTPD: Does not build with stsdk. Had to wrap in extern 'C' because stsdk already imports as extern. Testing did not show any issues and none were expected. - [X] SM STSDK: Build and uploaded set keys but was not able to adopt. '''Error 81-001 Something went wrong''' - [X] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. - [X] SM CORE: Update README.md docs on building project including stsdk and platformio. From c9ae3fd30f82b98bcb7c77a3b22f0df8a4fdd6d5 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 22:31:01 -0800 Subject: [PATCH 65/97] Finishing touches? Maybe. --- CHANGELOG.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc18c1b4..f6f0eaa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] Open issues +- [ ] CORE: TODO: Add astyle testing in new github action worflow. +- [ ] STSDK: TODO: Successful adopting test. ### SM - Sean Mathews coder at f34r.com - [ ] API: Add countdown tracking for DSC/Ademco exit mode @@ -26,20 +28,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [ ] TWILIO & PUSHOVER: Add virtual partition qualifier to virtual switch command. Currently on the Twilio notification is hard coded to the default virtual partition in slot 0. The Pushover notification currently has no qualifier and sends messages regardless of the partition as long as it matches. Merge these into a single pattern allowing for the user to define it by its ```vpart``` id. - [ ] webUI: Add REST api compatible with the current webapp including a secret key. This is low priority as this method of connection is not very efficient. -### AJ -- [ ] Migrate `astyle` to GitHub Action - --- ## Releases ## [1.1.0 P2] - 2023-01-?? Sean Mathews - coder @f34rdotcom Changes: - - Add CI using github Actions to test building and create an Artifact with the compiled firmware package and instructions. For more info on Artifacts see https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts + - Add CI using github Actions to test building and create an Artifact with a release package with compiled firmware and instructions. + - More info on Artifacts: https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts - Removed travis-ci support. - - Fix missing settings and organized sdkconfig.defaults. + - Fix missing settings and organized sdkconfig.defaults file. - Improve error handling to fix null pointer crashes when processing unexpected response from Twilio rest API. - TODO: Find more time to audit and cleanup code. - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. - Get STSDK building again. + - TODO: Confirm adopting works. So far I have not been successful. - Improved documentation fixing errors and adding config file examples in each section. ### Change log - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :(. No loss now we can generate a release file something that seemed much more difficult with travis-ci. Add a workflow file named ```CI build``` to test and build a release file with compiled firmware and instructions. See the ```CI build``` build Summary page for the Artifacts file ```AD2IoT-Release-Package``` From cad8a54cb012b750c0cd5803b37f78b1449beca2 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Feb 2023 23:01:49 -0800 Subject: [PATCH 66/97] ... --- README.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3d1bfc5b..8addf014 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ * 1. [Overview](#overview) * 2. [Tested and recommended hardware](#tested-and-recommended-hardware) * 3. [Firmware](#firmware) - * 3.1. [webUI build (webui) - alarmdecoder_webui_esp32.bin](#webui-build-(webui)---alarmdecoder_webui_esp32.bin) - * 3.2. [SmartThings build (stsdk) - alarmdecoder_stsdk_esp32.bin](#smartthings-build-(stsdk)---alarmdecoder_stsdk_esp32.bin) + * 3.1. [webUI build (webui) - esp32/esp32-poe-iso-webui](#webui-build-(webui)---esp32/esp32-poe-iso-webui) + * 3.2. [SmartThings build (stsdk) - esp32/esp32-poe-iso-stsdk](#smartthings-build-(stsdk)---esp32/esp32-poe-iso-stsdk) * 4. [Configuring the AD2IoT device](#configuring-the-ad2iot-device) * 5. [AD2Iot CLI - command line interface](#ad2iot-cli---command-line-interface) * 5.1. [Basic commands](#basic-commands) @@ -54,27 +54,25 @@ The device firmware is stored in the onboard non-volatile flash making the devic * ESP32-DevKitC-32E. WiFi only applications. ## 3. Firmware -The firmware is already compiled for the ESP32-POE-ISO board and is available in the release page or via OTA(over-the-air) update. Currently the firmware is built with the following build flags 'stsdk' and 'webui'. +Pre compiled firmware for the ESP32-POE-ISO board is available in the release package to flash to a new device or via OTA(over-the-air) update for devices that are already programmed with a current AD2IoT firmware. -To switch to a specific build over the internet using OTA include the buildflag in the upgrade command. +Currently two builds are available ```stsdk``` and ```webui```. To switch to a specific build over the internet using OTA include the buildflag in the upgrade command. - ```upgrade webui``` If the upgrade fails it may be the result of low memory on the device. Try disabling features restart the device and try again. Example. ```webui disable Y```. If all else fails install the latest release of the AD2IoT firmware over USB. -See the README-FLASH-ESP32.md inside the release file for instructions on flashing the firmware over the ESP32-POE-ISO USB port. +See the README-FLASH-ESP32.md inside the release file for instructions on flashing the firmware to a ESP32-POE-ISO board over USB. -### 3.1. webUI build (webui) - alarmdecoder_webui_esp32.bin +### 3.1. webUI build (webui) - esp32/esp32-poe-iso-webui - Enabled components: Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd. -This build uses the latest ESP-IDF v4.3 with the SmartThings driver is disabled. - - Optional uSD card with a FAT32 root partition is required for webUI. - Copy the contents of contrib/webUI/flash-drive folder into the root directory of the card. - Optionally place the sample configuration file [data/ad2iot.ini](data/ad2iot.ini) on the root directory to override the default config storage on the internal /spiffs partition. - Reboot the device after inserting the card for changes to take effect. -### 3.2. SmartThings build (stsdk) - alarmdecoder_stsdk_esp32.bin -- Enabled components: Pushover, Twilio, Sendgrid, ser2sock, SmartThings. +### 3.2. SmartThings build (stsdk) - esp32/esp32-poe-iso-stsdk +- Enabled components: SmartThings, Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd. This build is compiled using the [st-device-sdk-c-ref](https://github.com/SmartThingsCommunity/st-device-sdk-c-ref) from the SmartThings github repo and has the webUI component disabled. From bd93aec30d278628341790fdc59322ffdc5e7bbc Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 13:59:11 -0700 Subject: [PATCH 67/97] stsdk build issue testing. --- sdkconfig.defaults.stsdk | 122 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 sdkconfig.defaults.stsdk diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk new file mode 100644 index 00000000..87394e65 --- /dev/null +++ b/sdkconfig.defaults.stsdk @@ -0,0 +1,122 @@ +# Compiler settings +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_COMPILER_OPTIMIZATION_SIZE=y + +# FreeRTOS settings +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_ISR_STACKSIZE=2096 +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y + +# General settings +CONFIG_LOG_COLORS=n +CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y +CONFIG_BOOTLOADER_LOG_LEVEL=0 + +# Hardware specific settings +CONFIG_ESP_INT_WDT_TIMEOUT_MS=3000 +## ESP32-WROOM-32E +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_BOOTLOADER_SPI_WP_PIN=7 +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +## ESP32-POE-ISO ETHERNET config +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +CONFIG_ETH_RMII_CLK_OUT_GPIO=17 +CONFIG_ETH_RMII_CLK_OUTPUT=y +CONFIG_AD2IOT_ETH_PHY_LAN8720=y +CONFIG_AD2IOT_ETH_MDC_GPIO=23 +CONFIG_AD2IOT_ETH_MDIO_GPIO=18 +CONFIG_AD2IOT_ETH_PHY_RST_GPIO=-1 +CONFIG_AD2IOT_ETH_PHY_POWER_GPIO=12 +CONFIG_AD2IOT_ETH_PHY_ADDR=0 + +# Partition settings +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.4MB.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.4MB.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y + +# FATFS settings +CONFIG_FATFS_LFN_HEAP=y +CONFIG_FATFS_CODEPAGE_437=y +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_CODEPAGE_437=y +CONFIG_FATFS_MAX_LFN=255 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y + +# Coredump settings +CONFIG_ESP_COREDUMP_ENABLE=y +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y +CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP_COREDUMP_CHECKSUM_CRC32=y +CONFIG_ESP_COREDUMP_CHECK_BOOT=y +CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=20 + +# LWIP settings +CONFIG_LWIP_LOCAL_HOSTNAME="ad2iot" +CONFIG_LWIP_IPV6_AUTOCONFIG=y +CONFIG_LWIP_MAX_SOCKETS=16 + +# MQTT client settings +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_MSG_ID_INCREMENTAL=y +CONFIG_MQTT_REPORT_DELETED_MESSAGES=y + +# HTTP(s) / WebSockets server +CONFIG_ESP_HTTPS_SERVER_ENABLE=y +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y +CONFIG_HTTPD_WS_SUPPORT=y +## TODO: Make better... +CONFIG_ESP_TLS_INSECURE=y +CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y + +# SSL/TLS certificate bundles +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y +CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" + +# STSDK build settings +CONFIG_STDK_IOT_CORE=y +CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +# CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set +CONFIG_STDK_IOT_CORE_LOG_FILE=y +CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y +CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 +CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y +CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y +CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y +CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y +CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y +CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y +CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y + +# AD2IoT network settings +CONFIG_AD2IOT_USE_WIFI=y +CONFIG_AD2IOT_USE_ETHERNET=y +CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y + +# AD2IoT default components enable/disable +CONFIG_AD2IOT_TOP=y +CONFIG_AD2IOT_FTP_DAEMON=y +CONFIG_AD2IOT_MQTT_CLIENT=y +CONFIG_AD2IOT_WEBSERVER_UI=y +CONFIG_AD2IOT_SER2SOCKD=y +CONFIG_AD2IOT_TWILIO_CLIENT=y +CONFIG_AD2IOT_PUSHOVER_CLIENT=y From 34db6f2809d57ae5148dd3eea57047937f26d681 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 14:01:16 -0700 Subject: [PATCH 68/97] ... --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cfdca6e2..50919d0c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,6 +50,7 @@ jobs: git config --global user.email "<>" python setup.py esp32 ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ + cp $RUNNER_WORKSPACE/AlarmDecoder-IoT/sdkconfig.defaults.stsdk $RUNNER_WORKSPACE/AlarmDecoder-IoT/sdkconfig.defaults python build.py esp32 AlarmDecoder-IoT cd .. From 6e25063c9cab4c814b5a504e0ae7c081f349c95d Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 14:08:27 -0700 Subject: [PATCH 69/97] ... --- sdkconfig.defaults.stsdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 87394e65..0f429745 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -91,7 +91,7 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings CONFIG_STDK_IOT_CORE=y -CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +# CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP is not set CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y From aecab8b31eedd2704b8dd91bed9446f613209ebe Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 14:28:11 -0700 Subject: [PATCH 70/97] ... --- sdkconfig.defaults.stsdk | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 0f429745..1d1cfc26 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -92,20 +92,20 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings CONFIG_STDK_IOT_CORE=y # CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP is not set -CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +#CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y +#CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y +#CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set -CONFIG_STDK_IOT_CORE_LOG_FILE=y -CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y -CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 -CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y -CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y -CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y -CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y -CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y -CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y -CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y +#CONFIG_STDK_IOT_CORE_LOG_FILE=y +#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y +#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 +#CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y +#CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y +#CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y +#CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y +#CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y +#CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y +#CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y # AD2IoT network settings CONFIG_AD2IOT_USE_WIFI=y From 4bd32628b10c39e958bce26b9f94ee3c05656548 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 14:33:30 -0700 Subject: [PATCH 71/97] ... --- sdkconfig.defaults.stsdk | 1 + 1 file changed, 1 insertion(+) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 1d1cfc26..fb8c21e1 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -91,6 +91,7 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings CONFIG_STDK_IOT_CORE=y +CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y # CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP is not set #CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y #CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y From 92971003b94337effe88624a626016b4666c084b Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 20:15:33 -0700 Subject: [PATCH 72/97] ... --- .github/workflows/build.yml | 1 + main/alarmdecoder_main.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 50919d0c..3d0e8fc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,6 +41,7 @@ jobs: uses: actions/checkout@v3 with: repository: SmartThingsCommunity/st-device-sdk-c-ref + ref: release/v1.4 path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings diff --git a/main/alarmdecoder_main.cpp b/main/alarmdecoder_main.cpp index f5b8489e..a05365c0 100644 --- a/main/alarmdecoder_main.cpp +++ b/main/alarmdecoder_main.cpp @@ -503,6 +503,7 @@ void _update_top_task_stats() */ bool _show_pretty_process_list() { +#if CONFIG_AD2IOT_TOP // Format string for data columns. // "Name", "ID", "State", "Priority", "Stack", "CPU#", "TIME", "%BUSY, %CUR" #define TABBED_HEADER_FMT "%-15s %-3s %-5s %-8s %-5s %-4s %-20s %-6s %-6s\r\n" @@ -621,6 +622,7 @@ bool _show_pretty_process_list() " Stack: Minimum stack free bytes, CPU#: CPU affinity\r\n" " TBusy: %% busy total, Busy: %% busy now\r\n" ); +#endif return true; } @@ -632,6 +634,7 @@ bool _show_pretty_process_list() */ static void _cli_cmd_top_event(const char *string) { +#if CONFIG_AD2IOT_TOP uint8_t rx_buffer[AD2_UART_RX_BUFF_SIZE]; while(1) { if (ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS(100)) != 0) { @@ -650,6 +653,7 @@ static void _cli_cmd_top_event(const char *string) break; } } +#endif } #endif @@ -966,11 +970,13 @@ void init_ad2_uart_client(const char *args) */ void dump_mem_stats() { +#if CONFIG_AD2IOT_TOP float Total = heap_caps_get_total_size(MALLOC_CAP_32BIT); float Free_Size = heap_caps_get_free_size(MALLOC_CAP_32BIT); float DRam = heap_caps_get_free_size(MALLOC_CAP_8BIT); float IRam = heap_caps_get_free_size(MALLOC_CAP_32BIT) - heap_caps_get_free_size(MALLOC_CAP_8BIT); ad2_printf_host(true, "Total Heap Size %.2f Kb\nFree Space %.2f Kb\nDRAM %.2f Kb\nIRAM %.2f Kb\n",Total/1024,Free_Size/1024,DRam/1024,IRam/1024); +#endif } // external call from FreeRTOS is CDECL From 75f96d9d65a8b4e659baaf9db80241aee874ec32 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 20:25:08 -0700 Subject: [PATCH 73/97] ... --- sdkconfig.defaults.stsdk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index fb8c21e1..ea9c9704 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -114,9 +114,9 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=y +CONFIG_AD2IOT_TOP=n CONFIG_AD2IOT_FTP_DAEMON=y -CONFIG_AD2IOT_MQTT_CLIENT=y +CONFIG_AD2IOT_MQTT_CLIENT=n CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y CONFIG_AD2IOT_TWILIO_CLIENT=y From a64c4338409a033b7b77ccb29bacd1487614f1bd Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 20:38:12 -0700 Subject: [PATCH 74/97] ... --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3d0e8fc6..8e2b3926 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,6 +53,9 @@ jobs: ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ cp $RUNNER_WORKSPACE/AlarmDecoder-IoT/sdkconfig.defaults.stsdk $RUNNER_WORKSPACE/AlarmDecoder-IoT/sdkconfig.defaults python build.py esp32 AlarmDecoder-IoT + # FIXME: make better. After build restore sdkconfig.defaults and remove sdkconfig to force rebuild on later builds. + git checkout sdkconfig.defaults + rm sdkconfig cd .. - name: Add esp32-poe-iso stsdk build to release package From 3c3c5aa3e027339c5f46e00aa79ecbc83f378536 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 20:52:18 -0700 Subject: [PATCH 75/97] ... --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e2b3926..2afc71af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,17 +46,18 @@ jobs: - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings run: | + # Overwrite defaults and restore when done with build. + cp sdkconfig.defaults.stsdk sdkconfig.defaults cd .st-device-sdk-c-ref git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" python setup.py esp32 ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ - cp $RUNNER_WORKSPACE/AlarmDecoder-IoT/sdkconfig.defaults.stsdk $RUNNER_WORKSPACE/AlarmDecoder-IoT/sdkconfig.defaults python build.py esp32 AlarmDecoder-IoT - # FIXME: make better. After build restore sdkconfig.defaults and remove sdkconfig to force rebuild on later builds. + cd .. + # Restore defaults and remove any sdkconfig created git checkout sdkconfig.defaults rm sdkconfig - cd .. - name: Add esp32-poe-iso stsdk build to release package run: | From cf546b83d5d811a8cf8ed536655b2251778c89ff Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 21:31:49 -0700 Subject: [PATCH 76/97] ... --- sdkconfig.defaults.stsdk | 1 + 1 file changed, 1 insertion(+) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index ea9c9704..c0a48ba5 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -96,6 +96,7 @@ CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y #CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y #CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y #CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG=y # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set #CONFIG_STDK_IOT_CORE_LOG_FILE=y #CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y From 0fb0ac85bb95012441e89e7ca20ba32b7b7fc9e7 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 12 Mar 2023 23:08:48 -0700 Subject: [PATCH 77/97] ... --- .github/workflows/build.yml | 3 ++- sdkconfig.defaults.stsdk | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2afc71af..72e3db2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,9 +55,10 @@ jobs: ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT cd .. - # Restore defaults and remove any sdkconfig created + # Restore defaults and remove any sdkconfig created in build. git checkout sdkconfig.defaults rm sdkconfig + # No need to make clean later build with pio will use a different work folder. - name: Add esp32-poe-iso stsdk build to release package run: | diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index c0a48ba5..bede77ce 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -14,6 +14,8 @@ CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y CONFIG_FREERTOS_USE_TRACE_FACILITY=y # General settings +CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y +CONFIG_LOG_DEFAULT_LEVEL=5 CONFIG_LOG_COLORS=n CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y CONFIG_BOOTLOADER_LOG_LEVEL=0 @@ -92,16 +94,15 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings CONFIG_STDK_IOT_CORE=y CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y -# CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP is not set -#CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y -#CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -#CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG=y +CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +# CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG is not set # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set #CONFIG_STDK_IOT_CORE_LOG_FILE=y #CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y #CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 -#CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y #CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y #CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y #CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y From b1d0cb10db229a5aa217f03c775b08836cec96e9 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 13:09:05 -0700 Subject: [PATCH 78/97] ... --- components/stsdk/CMakeLists.txt | 3 +- components/stsdk/device_info.json | 8 --- components/stsdk/stsdk_main.cpp | 94 +++++++++++-------------------- sdkconfig.defaults.stsdk | 13 +---- 4 files changed, 35 insertions(+), 83 deletions(-) delete mode 100644 components/stsdk/device_info.json diff --git a/components/stsdk/CMakeLists.txt b/components/stsdk/CMakeLists.txt index cc2d5730..b17ff000 100644 --- a/components/stsdk/CMakeLists.txt +++ b/components/stsdk/CMakeLists.txt @@ -12,8 +12,7 @@ idf_component_register(SRCS "stsdk_main.cpp" "caps_smokeDetector.c" "caps_switch.c" "caps_tamperAlert.c" - EMBED_FILES "device_info.json" - "onboarding_config.json" + EMBED_FILES "onboarding_config.json" REQUIRES idf::otaupdate INCLUDE_DIRS . ../../main/ $ENV{STDK_CORE_PATH}/src/include/) project(stsdk) diff --git a/components/stsdk/device_info.json b/components/stsdk/device_info.json deleted file mode 100644 index 5d9b000c..00000000 --- a/components/stsdk/device_info.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "deviceInfo": { - "firmwareVersion": "firmwareVersion_here", - "privateKey": "privateKey_here", - "publicKey": "publicKey_here", - "serialNumber": "serialNumber_here" - } -} diff --git a/components/stsdk/stsdk_main.cpp b/components/stsdk/stsdk_main.cpp index 04e030a1..f27d8895 100644 --- a/components/stsdk/stsdk_main.cpp +++ b/components/stsdk/stsdk_main.cpp @@ -62,10 +62,6 @@ IOT_CTX* ctx = NULL; extern const uint8_t onboarding_config_start[] asm("_binary_onboarding_config_json_start"); extern const uint8_t onboarding_config_end[] asm("_binary_onboarding_config_json_end"); -// device_info_start is null-terminated string -extern const uint8_t device_info_start[] asm("_binary_device_info_json_start"); -extern const uint8_t device_info_end[] asm("_binary_device_info_json_end"); - /** * @brief component: main */ @@ -264,24 +260,9 @@ static void _cli_cmd_stsdk_event(const char *string) * SmartThings Serial. */ case STSDK_SUBCMD_SERIAL_ID: - // arg found save to nvs + // arg found save if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { - // save to the stnv nvs partition - nvs_handle my_handle; - esp_err_t err; - err = nvs_open_from_partition("nvs", "stdk", NVS_READWRITE, &my_handle); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_open_from_partition err: %s", __func__, esp_err_to_name(err)); - } - err = nvs_set_str(my_handle, "SerialNum", arg.c_str()); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_set_str err: %s", __func__, esp_err_to_name(err)); - ad2_printf_host(true, "Failed setting value.\r\n"); - } else { - ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); - } - err = nvs_commit(my_handle); - nvs_close(my_handle); + ad2_set_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_SERIAL, arg.c_str()); break; } // If no arg then return current show contents of this slot @@ -291,56 +272,27 @@ static void _cli_cmd_stsdk_event(const char *string) * SmartThings PrivateKey. */ case STSDK_SUBCMD_PRIVKEY_ID: - // arg found save to nvs + // arg found save if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { - // save to the stnv nvs partition - nvs_handle my_handle; - esp_err_t err; - err = nvs_open_from_partition("nvs", "stdk", NVS_READWRITE, &my_handle); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_open_from_partition err: %s", __func__, esp_err_to_name(err)); - } - err = nvs_set_str(my_handle, "PrivateKey", arg.c_str()); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_set_str err: %s", __func__, esp_err_to_name(err)); - ad2_printf_host(true, "Failed setting value.\r\n"); - } else { - ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); - } - err = nvs_commit(my_handle); - nvs_close(my_handle); + ad2_set_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_PRIVKEY, arg.c_str()); break; } // If no arg then return current show contents of this slot - ad2_printf_host(true, "SmartThings 'privatekey' arg missing.\r\n"); + ad2_printf_host(true, "SmartThings 'serial' arg missing.\r\n"); break; /** * SmartThings PublicKey. */ case STSDK_SUBCMD_PUBKEY_ID: - // arg found save to nvs + // arg found save if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { - // save to the stnv nvs partition - nvs_handle my_handle; - esp_err_t err; - err = nvs_open_from_partition("nvs", "stdk", NVS_READWRITE, &my_handle); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_open_from_partition err: %s", __func__, esp_err_to_name(err)); - } - err = nvs_set_str(my_handle, "PublicKey", arg.c_str()); - if ( err != ESP_OK) { - ESP_LOGE(TAG, "%s: nvs_set_str err: %s", __func__, esp_err_to_name(err)); - ad2_printf_host(true, "Failed setting value.\r\n"); - } else { - ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); - } - err = nvs_commit(my_handle); - nvs_close(my_handle); + ad2_set_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_PUBKEY, arg.c_str()); break; } // If no arg then return current show contents of this slot - ad2_printf_host(true, "SmartThings 'publickey' arg missing.\r\n"); + ad2_printf_host(true, "SmartThings 'serial' arg missing.\r\n"); break; + default: break; } @@ -1015,8 +967,6 @@ void stsdk_init(void) { unsigned char *onboarding_config = (unsigned char *) onboarding_config_start; unsigned int onboarding_config_len = onboarding_config_end - onboarding_config_start; - unsigned char *device_info = (unsigned char *) device_info_start; - unsigned int device_info_len = device_info_end - device_info_start; int iot_err; bool en = false; @@ -1030,8 +980,30 @@ void stsdk_init(void) ESP_LOGI(TAG, "Starting STSDK"); - // create a iot context - ctx = st_conn_init(onboarding_config, onboarding_config_len, device_info, device_info_len); + // Create a device info json string for the st_conn_init from internal NV keys + cJSON *root = cJSON_CreateObject(); + cJSON *deviceInfo = cJSON_CreateObject(); + + std::string privateKey; + std::string publicKey; + std::string serialNumber; + ad2_get_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_PRIVKEY, privateKey); + ad2_get_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_PUBKEY, publicKey); + ad2_get_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_SERIAL, serialNumber); + + cJSON_AddStringToObject(deviceInfo, "firmwareVersion", FIRMWARE_VERSION); + cJSON_AddStringToObject(deviceInfo, "privateKey", privateKey.c_str()); + cJSON_AddStringToObject(deviceInfo, "publicKey", publicKey.c_str()); + cJSON_AddStringToObject(deviceInfo, "serialNumber", serialNumber.c_str()); + cJSON_AddItemToObject(root, "deviceInfo", deviceInfo); + static char *device_info_json = NULL; + device_info_json = cJSON_Print(root); + ctx = st_conn_init(onboarding_config, onboarding_config_len, (unsigned char*)device_info_json, strlen(device_info_json)); + ad2_printf_host(false, "DeviceInfo JSON: %s", device_info_json); + + //cJSON_free(device_info_json); + cJSON_Delete(root); + if (ctx != NULL) { iot_err = st_conn_set_noti_cb(ctx, iot_noti_cb, NULL); if (iot_err) { diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index bede77ce..4582b97f 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -14,8 +14,6 @@ CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y CONFIG_FREERTOS_USE_TRACE_FACILITY=y # General settings -CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y -CONFIG_LOG_DEFAULT_LEVEL=5 CONFIG_LOG_COLORS=n CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y CONFIG_BOOTLOADER_LOG_LEVEL=0 @@ -97,18 +95,9 @@ CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +# CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO is not set # CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG is not set # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set -#CONFIG_STDK_IOT_CORE_LOG_FILE=y -#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y -#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 -#CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y -#CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y -#CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y -#CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y -#CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y -#CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y # AD2IoT network settings CONFIG_AD2IOT_USE_WIFI=y From d9e323aed5a43524e0739d743df5f5e18b562bd2 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 13:40:11 -0700 Subject: [PATCH 79/97] ... --- .github/workflows/build.yml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 72e3db2b..1fe0d38e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,14 +60,6 @@ jobs: rm sdkconfig # No need to make clean later build with pio will use a different work folder. - - name: Add esp32-poe-iso stsdk build to release package - run: | - mkdir $PP/esp32/esp32-poe-iso-stsdk - cp build/partition_table/partition-table.bin $PP/esp32/esp32-poe-iso-stsdk/partitions.bin - cp build/alarmdecoder_ad2iot_esp32.bin $PP/esp32/esp32-poe-iso-stsdk/firmware.bin - cp build/bootloader/bootloader.bin $PP/esp32/esp32-poe-iso-stsdk/ - cp build/ota_data_initial.bin $PP/esp32/esp32-poe-iso-stsdk/ - - name: Install PlatformIO Core run: pip install --upgrade platformio @@ -77,14 +69,28 @@ jobs: - name: Build spiffs.bin for esp32-poe-iso run: pio run -t buildfs -e esp32-poe-iso - - name: Add esp32-poe-iso webui build to release package + - name: Create release package folders for each branch. run: | + mkdir $PP/esp32/esp32-poe-iso-stsdk mkdir $PP/esp32/esp32-poe-iso-webui - cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-webui/ + + - name: Add esp32-poe-iso stsdk firmware build to release package + run: | + cp build/alarmdecoder_ad2iot_esp32.bin $PP/esp32/esp32-poe-iso-stsdk/firmware.bin + + - name: Add esp32-poe-iso webui firmware build to release package + run: | cp .pio/build/esp32-poe-iso/firmware.bin $PP/esp32/esp32-poe-iso-webui/ + + - name: Add common firmware files for each branch to the package. + cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-stsdk/ cp .pio/build/esp32-poe-iso/bootloader.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/bootloader.bin $PP/esp32/esp32-poe-iso-stsdk/ cp .pio/build/esp32-poe-iso/partitions.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/partitions.bin $PP/esp32/esp32-poe-iso-stsdk/ cp .pio/build/esp32-poe-iso/ota_data_initial.bin $PP/esp32/esp32-poe-iso-webui/ + cp .pio/build/esp32-poe-iso/ota_data_initial.bin $PP/esp32/esp32-poe-iso-stsdk/ - name: Upload firmware package Artifact uses: actions/upload-artifact@v3 From 58c58648347290f2afb9ba898d644144945e9a31 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 13:42:21 -0700 Subject: [PATCH 80/97] ... --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1fe0d38e..6d89aeca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,6 +83,7 @@ jobs: cp .pio/build/esp32-poe-iso/firmware.bin $PP/esp32/esp32-poe-iso-webui/ - name: Add common firmware files for each branch to the package. + run: | cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-webui/ cp .pio/build/esp32-poe-iso/spiffs.bin $PP/esp32/esp32-poe-iso-stsdk/ cp .pio/build/esp32-poe-iso/bootloader.bin $PP/esp32/esp32-poe-iso-webui/ From 71b875ea3e44fd7b7644224975449f6767d0ae75 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 16:07:29 -0700 Subject: [PATCH 81/97] ... --- components/stsdk/stsdk_main.cpp | 27 +++++++++++++++------------ sdkconfig.defaults.stsdk | 6 +++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/components/stsdk/stsdk_main.cpp b/components/stsdk/stsdk_main.cpp index f27d8895..196e96a7 100644 --- a/components/stsdk/stsdk_main.cpp +++ b/components/stsdk/stsdk_main.cpp @@ -41,6 +41,8 @@ static const char *TAG = "STSDK"; #include "esp_netif.h" #endif +static bool _enabled = false; + // specific includes #include "stsdk_main.h" #include "ota_util.h" @@ -224,7 +226,6 @@ static void _cli_cmd_stsdk_event(const char *string) ad2_lcase(subcmd); int i; - bool en; for(i = 0;; ++i) { if (STSDK_SUBCMD[i] == 0) { ad2_printf_host(false, "What?\r\n"); @@ -243,10 +244,9 @@ static void _cli_cmd_stsdk_event(const char *string) ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); } - // show contents of this slot - en = false; - ad2_get_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, &en); - ad2_printf_host(true, "SmartThings Direct Connected Devices SDK client is '%s'.\r\n", (en ? "Enabled" : "Disabled")); + // load the current and show contents of this slot. + ad2_get_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, &_enabled); + ad2_printf_host(true, "SmartThings Direct Connected Devices SDK client is '%s'.\r\n", (_enabled ? "Enabled" : "Disabled")); break; /** * Forget all STSDK state revert back to adoption mode. @@ -263,10 +263,11 @@ static void _cli_cmd_stsdk_event(const char *string) // arg found save if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { ad2_set_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_SERIAL, arg.c_str()); + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); break; } // If no arg then return current show contents of this slot - ad2_printf_host(true, "SmartThings 'serial' arg missing.\r\n"); + ad2_printf_host(true, "SmartThings '" STSDK_SUBCMD_SERIAL "' arg missing.\r\n"); break; /** * SmartThings PrivateKey. @@ -275,10 +276,11 @@ static void _cli_cmd_stsdk_event(const char *string) // arg found save if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { ad2_set_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_PRIVKEY, arg.c_str()); + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); break; } // If no arg then return current show contents of this slot - ad2_printf_host(true, "SmartThings 'serial' arg missing.\r\n"); + ad2_printf_host(true, "SmartThings '" STSDK_SUBCMD_PRIVKEY "' arg missing.\r\n"); break; /** * SmartThings PublicKey. @@ -287,10 +289,11 @@ static void _cli_cmd_stsdk_event(const char *string) // arg found save if (ad2_copy_nth_arg(arg, string, 2, true) >= 0) { ad2_set_config_key_string(STSDK_CONFIG_SECTION, STSDK_SUBCMD_PUBKEY, arg.c_str()); + ad2_printf_host(true, "Success setting value. Restart required to take effect.\r\n"); break; } // If no arg then return current show contents of this slot - ad2_printf_host(true, "SmartThings 'serial' arg missing.\r\n"); + ad2_printf_host(true, "SmartThings '" STSDK_SUBCMD_PUBKEY "' arg missing.\r\n"); break; default: @@ -969,11 +972,10 @@ void stsdk_init(void) unsigned int onboarding_config_len = onboarding_config_end - onboarding_config_start; int iot_err; - bool en = false; - ad2_get_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, &en); + ad2_get_config_key_bool(STSDK_CONFIG_SECTION, STSDK_SUBCMD_ENABLE, &_enabled); // nothing more needs to be done once commands are set if not enabled. - if (!en) { + if (!_enabled) { ESP_LOGI(TAG, "STSDK disabled"); return; } @@ -999,7 +1001,6 @@ void stsdk_init(void) static char *device_info_json = NULL; device_info_json = cJSON_Print(root); ctx = st_conn_init(onboarding_config, onboarding_config_len, (unsigned char*)device_info_json, strlen(device_info_json)); - ad2_printf_host(false, "DeviceInfo JSON: %s", device_info_json); //cJSON_free(device_info_json); cJSON_Delete(root); @@ -1321,6 +1322,8 @@ void stsdk_connection_start(void) iot_pin_t *pin_num = NULL; int err; + if (!_enabled) return; + #if defined(SET_PIN_NUMBER_CONFRIM) pin_num = (iot_pin_t *) malloc(sizeof(iot_pin_t)); if (!pin_num) { diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 4582b97f..120448c7 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -95,7 +95,7 @@ CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -# CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO is not set +CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y # CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG is not set # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set @@ -105,9 +105,9 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=n +CONFIG_AD2IOT_TOP=y CONFIG_AD2IOT_FTP_DAEMON=y -CONFIG_AD2IOT_MQTT_CLIENT=n +CONFIG_AD2IOT_MQTT_CLIENT=y CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y CONFIG_AD2IOT_TWILIO_CLIENT=y From 86d42e1fa4a343f7cca3c942a2a98a108a5a497e Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 16:19:22 -0700 Subject: [PATCH 82/97] ... --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d89aeca..6848a3a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,6 @@ jobs: uses: actions/checkout@v3 with: repository: SmartThingsCommunity/st-device-sdk-c-ref - ref: release/v1.4 path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings From 7ca985e9a24d0a1b99b87d8f3e5bb5c0f1b6754c Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 16:33:58 -0700 Subject: [PATCH 83/97] Some final cleanup and finalizing last changes. --- .github/workflows/build.yml | 1 + CHANGELOG.md | 5 +++-- README.md | 4 ++-- components/ad2mqtt/ad2mqtt.cpp | 4 ++-- components/alarmdecoder-api/alarmdecoder_api.cpp | 8 +++++--- components/pushover/pushover.cpp | 4 ++-- components/twilio/twilio.cpp | 4 ++-- sdkconfig.defaults.stsdk | 4 ++-- 8 files changed, 19 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6848a3a4..6d89aeca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,6 +41,7 @@ jobs: uses: actions/checkout@v3 with: repository: SmartThingsCommunity/st-device-sdk-c-ref + ref: release/v1.4 path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings diff --git a/CHANGELOG.md b/CHANGELOG.md index f6f0eaa9..c78d4cad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,14 +40,15 @@ Changes: - TODO: Find more time to audit and cleanup code. - Fixed some small errors in the default configuration ini file and made sure basic switches have examples in components. - Get STSDK building again. - - TODO: Confirm adopting works. So far I have not been successful. + - Confirm adopting works after fixing key and serial storage omissions. - Improved documentation fixing errors and adding config file examples in each section. ### Change log + - [X] SM API,MQTT,PUSHOVER,TWILIO: Replace "fault" with "trouble" in error messages and code comments. Improve error reporting when validating and loading switches during init. - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :(. No loss now we can generate a release file something that seemed much more difficult with travis-ci. Add a workflow file named ```CI build``` to test and build a release file with compiled firmware and instructions. See the ```CI build``` build Summary page for the Artifacts file ```AD2IoT-Release-Package``` - [X] SM CORE: Docs improvements. - [X] SM FTPD: Does not build with stsdk. Had to wrap in extern 'C' because stsdk already imports as extern. Testing did not show any issues and none were expected. - [X] SM STSDK: Build and uploaded set keys but was not able to adopt. '''Error 81-001 Something went wrong''' - - [X] SM CORE: Testing modules build. All built even mqtt? Ok... I did not expect that. Needs testing. + - [X] SM CORE: Testing stsdk and webui modules build. Currently not able to add ```top``` or ```mqtt``` modules with ```stsdk``` build. - [X] SM CORE: Update README.md docs on building project including stsdk and platformio. - [X] SM CORE: Add fixes for stsdk code that I have been sitting on. Mostly just CDECL stuff. - [X] SM CORE: Fix CMakeList.txt to fetch SimpleIni from github and include it for stsdk building. diff --git a/README.md b/README.md index 8addf014..b324a0e4 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ If the upgrade fails it may be the result of low memory on the device. Try disab See the README-FLASH-ESP32.md inside the release file for instructions on flashing the firmware to a ESP32-POE-ISO board over USB. ### 3.1. webUI build (webui) - esp32/esp32-poe-iso-webui -- Enabled components: Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd. +- Enabled components: Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd, top. - Optional uSD card with a FAT32 root partition is required for webUI. - Copy the contents of contrib/webUI/flash-drive folder into the root directory of the card. @@ -72,7 +72,7 @@ See the README-FLASH-ESP32.md inside the release file for instructions on flashi - Reboot the device after inserting the card for changes to take effect. ### 3.2. SmartThings build (stsdk) - esp32/esp32-poe-iso-stsdk -- Enabled components: SmartThings, Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd. +- Enabled components: SmartThings, Pushover, Twilio, Sendgrid, ser2sock, webUI, ftpd. This build is compiled using the [st-device-sdk-c-ref](https://github.com/SmartThingsCommunity/st-device-sdk-c-ref) from the SmartThings github repo and has the webUI component disabled. diff --git a/components/ad2mqtt/ad2mqtt.cpp b/components/ad2mqtt/ad2mqtt.cpp index 2638ea5d..3d8552f6 100644 --- a/components/ad2mqtt/ad2mqtt.cpp +++ b/components/ad2mqtt/ad2mqtt.cpp @@ -1347,12 +1347,12 @@ void mqtt_init() } else { // incomplete switch so delete it. delete es1; - ESP_LOGE(TAG, "Error in config section [switch %i]. Missing required open, close, or fault filter expressions.", swID); + ESP_LOGE(TAG, "Error in config section [switch %i]. Need at least one open, close, or trouble filter expressions.", swID); } } else { if (open_output_format.length() || close_output_format.length() || trouble_output_format.length()) { - ESP_LOGE(TAG, "Error in config for switch [switch %i]. Missing on or more required open,close, or fault output expressions.", swID); + ESP_LOGE(TAG, "Section config error. Need at least one open, close, or trouble output strings for switch %i.", swID); } } } diff --git a/components/alarmdecoder-api/alarmdecoder_api.cpp b/components/alarmdecoder-api/alarmdecoder_api.cpp index ea0ea613..6da7354c 100644 --- a/components/alarmdecoder-api/alarmdecoder_api.cpp +++ b/components/alarmdecoder-api/alarmdecoder_api.cpp @@ -1289,7 +1289,7 @@ bool AlarmDecoderParser::put(uint8_t *buff, int8_t len) && !ad2ps->exit_now) { // not exit countdown // get the numeric section and use as a zone #. - // conver base 16 to base 10 if needed. + // convert base 16 to base 10 if needed. bool _ishex = std::count_if(ad2ps->last_numeric_message.begin(), ad2ps->last_numeric_message.end(), [](unsigned char c) { @@ -1319,9 +1319,11 @@ bool AlarmDecoderParser::put(uint8_t *buff, int8_t len) // standard zone fault report. // [00000011000000000A--],002,[f70600ef1002000018020000000000],"FAULT 02 " - // check zone(system_issue) set for zone fault report entry. + // alarm zone(alarm_event_occurred) report. Set for zone alarm report entry. + // [00110001111000010A--],011,[f70200ff101110802b020000000000],"ALARM 11 GARAGE DOOR " + // check zone(system_issue) set for zone trouble report entry. // [00000401000000100A--],009,[f700001f1009040208020000000000],"CHECK 09 " - if (ad2ps->system_issue) { + if (ad2ps->system_issue || ad2ps->alarm_event_occurred) { // Update the zone state object and set timeout if (ad2ps->zone_states[_zone].state() != AD2_STATE_TROUBLE) { _send_event = true; diff --git a/components/pushover/pushover.cpp b/components/pushover/pushover.cpp index f7c41460..7b6ff377 100644 --- a/components/pushover/pushover.cpp +++ b/components/pushover/pushover.cpp @@ -601,12 +601,12 @@ void pushover_init() // incomplete switch so delete it and supporting pointers. delete pslots; delete es1; - ESP_LOGE(TAG, "Error in config section [switch %i]. Missing required open, close, or fault filter expressions.", swID); + ESP_LOGE(TAG, "Error in config section [switch %i]. Need at least one open, close, or trouble filter expressions.", swID); } } else { if (open_output_format.length() || close_output_format.length() || trouble_output_format.length()) { - ESP_LOGE(TAG, "Error in config for switch [switch %i]. Missing on or more required open,close, or fault output expressions.", swID); + ESP_LOGE(TAG, "Section config error. Need at least one open, close, or trouble output strings for switch %i.", swID); } } } diff --git a/components/twilio/twilio.cpp b/components/twilio/twilio.cpp index b41649a4..7bb72a83 100644 --- a/components/twilio/twilio.cpp +++ b/components/twilio/twilio.cpp @@ -979,12 +979,12 @@ void twilio_init() // incomplete switch so delete it and supporting pointers. delete pslots; delete es1; - ESP_LOGE(TAG, "Error in config section [switch %i]. Missing required open, close, or fault filter expressions.", swID); + ESP_LOGE(TAG, "Error in config section [switch %i]. Need at least one open, close, or trouble filter expressions.", swID); } } else { if (open_output_format.length() || close_output_format.length() || trouble_output_format.length()) { - ESP_LOGE(TAG, "Error in config for switch [switch %i]. Missing on or more required open,close, or fault output expressions.", swID); + ESP_LOGE(TAG, "Section config error. Need at least one open, close, or trouble output strings for switch %i.", swID); } } } diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 120448c7..856d0e9d 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -105,9 +105,9 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=y +CONFIG_AD2IOT_TOP=n CONFIG_AD2IOT_FTP_DAEMON=y -CONFIG_AD2IOT_MQTT_CLIENT=y +CONFIG_AD2IOT_MQTT_CLIENT=n CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y CONFIG_AD2IOT_TWILIO_CLIENT=y From f959ee6d994d6832280e7969ff1bbdd3664c887d Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 17:49:04 -0700 Subject: [PATCH 84/97] ... --- sdkconfig.defaults.stsdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 856d0e9d..0d7144d2 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -105,7 +105,7 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=n +CONFIG_AD2IOT_TOP=y CONFIG_AD2IOT_FTP_DAEMON=y CONFIG_AD2IOT_MQTT_CLIENT=n CONFIG_AD2IOT_WEBSERVER_UI=y From 11e2a2791517751669ea52584cdb03ef5096d9e6 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 18:21:08 -0700 Subject: [PATCH 85/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d89aeca..d9b6ee77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: uses: actions/checkout@v3 with: repository: SmartThingsCommunity/st-device-sdk-c-ref - ref: release/v1.4 + ref: develop path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings From 96d345da2ca84f0ebcc2116a8f9adae2ff92b21a Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 18:34:44 -0700 Subject: [PATCH 86/97] ... --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d9b6ee77..6848a3a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,6 @@ jobs: uses: actions/checkout@v3 with: repository: SmartThingsCommunity/st-device-sdk-c-ref - ref: develop path: ./.st-device-sdk-c-ref - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings From 52d5f8511ce13f76f0411109effa1daf2d0f1cfb Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sat, 18 Mar 2023 18:44:11 -0700 Subject: [PATCH 87/97] ... --- sdkconfig.defaults.stsdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 0d7144d2..856d0e9d 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -105,7 +105,7 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=y +CONFIG_AD2IOT_TOP=n CONFIG_AD2IOT_FTP_DAEMON=y CONFIG_AD2IOT_MQTT_CLIENT=n CONFIG_AD2IOT_WEBSERVER_UI=y From eaf1ad1315ffe2cd9256614a26b453339d70aee6 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 19 Mar 2023 19:49:35 -0700 Subject: [PATCH 88/97] Building local for both STSDK and pio, Fixed some bugs in stuff. More testing next. --- CHANGELOG.md | 4 ++ README.md | 2 +- components/ad2mqtt/ad2mqtt.cpp | 96 ++++++++++++++++++++----------- components/ftpd/ftpd.cpp | 18 +++--- components/otaupdate/ota_util.cpp | 22 +++++-- components/pushover/pushover.cpp | 13 +++-- components/ser2sock/ser2sock.cpp | 20 +++++-- components/stsdk/stsdk_main.cpp | 5 ++ components/twilio/twilio.cpp | 4 +- components/webUI/webUI.cpp | 20 ++++--- main/ad2_cli_cmd.cpp | 1 - main/device_control.cpp | 43 ++++++++------ main/device_control.h | 3 +- 13 files changed, 166 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c78d4cad..936c68d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,10 @@ Changes: - Confirm adopting works after fixing key and serial storage omissions. - Improved documentation fixing errors and adding config file examples in each section. ### Change log + - [X] SM OTA: Noticed it was trying too hard to connect at first boot after first check timeout. Set retry check time to 5 minutes when network down and on too many fails skip for 24h. + - [X] SM MQTT,TWILIO,PUSOVER: Fix notify regex filter not applied to test causing a switch to fire even if a filter is set that would exclude it. + - [X] SM CORE: Service startup when network is disabled needs to be delayed waiting for the network to start. + - [X] SM CORE: cleanup some compiler warnings about unused vars. Others I need to add more error handling. - [X] SM API,MQTT,PUSHOVER,TWILIO: Replace "fault" with "trouble" in error messages and code comments. Improve error reporting when validating and loading switches during init. - [X] SM CORE: Moving from travis-ci to Github Actions for build testing. I ran out of credits :(. No loss now we can generate a release file something that seemed much more difficult with travis-ci. Add a workflow file named ```CI build``` to test and build a release file with compiled firmware and instructions. See the ```CI build``` build Summary page for the Artifacts file ```AD2IoT-Release-Package``` - [X] SM CORE: Docs improvements. diff --git a/README.md b/README.md index b324a0e4..b4c414d2 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ See the README-FLASH-ESP32.md inside the release file for instructions on flashi - Reboot the device after inserting the card for changes to take effect. ### 3.2. SmartThings build (stsdk) - esp32/esp32-poe-iso-stsdk -- Enabled components: SmartThings, Pushover, Twilio, Sendgrid, ser2sock, webUI, ftpd. +- Enabled components: SmartThings, Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd, top. This build is compiled using the [st-device-sdk-c-ref](https://github.com/SmartThingsCommunity/st-device-sdk-c-ref) from the SmartThings github repo and has the webUI component disabled. diff --git a/components/ad2mqtt/ad2mqtt.cpp b/components/ad2mqtt/ad2mqtt.cpp index 3d8552f6..7c0f145d 100644 --- a/components/ad2mqtt/ad2mqtt.cpp +++ b/components/ad2mqtt/ad2mqtt.cpp @@ -36,6 +36,9 @@ static const char *TAG = "MQTT"; // esp component includes #include "mqtt_client.h" +// enable verbose debug logging +//#define MQTT_DEBUG + /* Constants that aren't configurable in menuconfig */ #define MQTT_COMMAND "mqtt" #define MQTT_ENABLE_SUBCMD "enable" @@ -819,7 +822,9 @@ void mqtt_free() void on_search_match_cb_mqtt(std::string *msg, AD2PartitionState *s, void *arg) { AD2EventSearch *es = (AD2EventSearch *)arg; - +#if defined(MQTT_DEBUG) + ESP_LOGI(TAG, "ON_SEARCH_MATCH_CB: '%s' -> '%s' [switch %i]", msg->c_str(), es->out_message.c_str(), es->INT_ARG); +#endif std::string message = es->out_message; // Grab the topic using the virtual switch ID pre saved into INT_ARG @@ -843,6 +848,13 @@ void on_search_match_cb_mqtt(std::string *msg, AD2PartitionState *s, void *arg) MQTT_DEF_QOS, MQTT_DEF_RETAIN, MQTT_DEF_STORE); + + if (msg_id) { + ESP_LOGI(TAG,"Switch #%i match message '%s'. Sending '%s'", es->INT_ARG, msg->c_str(), es->out_message.c_str()); + } else { + ESP_LOGE(TAG,"Error adding mqtt message."); + } + cJSON_free(state); cJSON_Delete(root); } @@ -926,7 +938,6 @@ static void _cli_cmd_mqtt_smart_alert_switch(std::string &subcmd, const char *in MQTT_CONFIG_SWITCH_SUFFIX_TROUBLE); std::string sk; - bool command_found = false; ad2_printf_host(false, "## [mqtt] switch %i configuration.\r\n", swID); while (ss >> sk) { tbuf = ""; @@ -1115,40 +1126,23 @@ void mqtt_register_cmds() } /** - * Initialize queue and SSL + * @brief daemon startup task + * + * @param [in]pvParameters currently not used NULL. */ -void mqtt_init() +void mqtt_startup_task(void *pvParameters) { - // if netif not enabled then we can't start. - if (!hal_get_netif_started()) { - ad2_printf_host(true, "%s client disabled. Network interface not enabled.", TAG); - return; - } - - bool en = false; - ad2_get_config_key_bool(MQTT_CONFIG_SECTION, MQTT_ENABLE_SUBCMD, &en); - - // nothing more needs to be done once commands are set if not enabled. - if (!en) { - ad2_printf_host(true, "%s client disabled.", TAG); - return; - } - -#if 0 // debug logging settings. - esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); - esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); - esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); +#if defined(MQTT_DEBUG) + ESP_LOGI(TAG, "MQTT waiting for network layer to start."); #endif - - // load commands subscription enable/disable setting - ad2_get_config_key_bool(MQTT_CONFIG_SECTION, MQTT_CMDEN_SUBCMD, &commands_enabled); - - // generate our client's unique user id. UUID. - ad2_genUUID(0x10, mqttclient_UUID); - ad2_printf_host(true, "%s: Init UUID: %s", TAG, mqttclient_UUID.c_str()); + while (1) { + if (!hal_get_netif_started()) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } else { + break; + } + } + ESP_LOGI(TAG, "Network layer is OK. %s client starting.", TAG); // configure and start MQTT client esp_err_t err; @@ -1200,6 +1194,39 @@ void mqtt_init() ESP_LOGE(TAG, "esp_mqtt_client_start return error: %s.", esp_err_to_name(err)); } + vTaskDelete(NULL); +} + +/** + * Initialize queue and SSL + */ +void mqtt_init() +{ + bool en = false; + ad2_get_config_key_bool(MQTT_CONFIG_SECTION, MQTT_ENABLE_SUBCMD, &en); + + // nothing more needs to be done once commands are set if not enabled. + if (!en) { + ad2_printf_host(true, "%s client disabled.", TAG); + return; + } + +#if 0 // debug logging settings. + esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); + esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); + esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); +#endif + + // load commands subscription enable/disable setting + ad2_get_config_key_bool(MQTT_CONFIG_SECTION, MQTT_CMDEN_SUBCMD, &commands_enabled); + + // generate our client's unique user id. UUID. + ad2_genUUID(0x10, mqttclient_UUID); + ad2_printf_host(true, "%s: Init UUID: %s", TAG, mqttclient_UUID.c_str()); + // Subscribe standard AlarmDecoder events AD2Parse.subscribeTo(ON_ARM, mqtt_on_state_change, (void *)ON_ARM); AD2Parse.subscribeTo(ON_DISARM, mqtt_on_state_change, (void *)ON_DISARM); @@ -1302,6 +1329,7 @@ void mqtt_init() // load [switch N] required regex match settings std::string prefilter_regex; ad2_get_config_key_string(key.c_str(), AD2SWITCH_SK_FILTER, prefilter_regex); + es1->PRE_FILTER_REGEX = prefilter_regex; // Load all regex search patterns for open, close, and trouble sub keys. std::string regex_sk_list = AD2SWITCH_SK_OPEN " " @@ -1358,7 +1386,7 @@ void mqtt_init() } ad2_printf_host(true, "%s: Init done. Found and configured %i virtual switches.", TAG, subscribers); - + xTaskCreate(&mqtt_startup_task, "mqtt startup", 1024*4, NULL, tskIDLE_PRIORITY+1, NULL); } #endif /* CONFIG_AD2IOT_MQTT_CLIENT */ diff --git a/components/ftpd/ftpd.cpp b/components/ftpd/ftpd.cpp index 5b978d88..c8ec63e6 100644 --- a/components/ftpd/ftpd.cpp +++ b/components/ftpd/ftpd.cpp @@ -1781,9 +1781,17 @@ static void _cli_cmd_ftpd_event(const char *string) void ftp_daemon_task(void *pvParameters) { #if defined(FTPD_DEBUG) - ESP_LOGI(TAG, "ftp daemon task starting."); + ESP_LOGI(TAG, "%s waiting for network layer to start.", TAG); #endif + while (1) { + if (!hal_get_netif_started()) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } else { + break; + } + } if (ad2ftpd != nullptr) { + ESP_LOGI(TAG, "Network layer is OK. %s daemon service starting.", TAG); ad2ftpd->start(); } vTaskDelete(NULL); @@ -1826,12 +1834,6 @@ void ftpd_register_cmds() */ void ftpd_init() { - // if netif not enabled then we can't start. - if (!hal_get_netif_started()) { - ad2_printf_host(true, "%s daemon disabled. Network interface not enabled.", TAG); - return; - } - bool en = false; ad2_get_config_key_bool(FTPD_CONFIG_SECTION, FTPD_SUBCMD_ENABLE, &en); @@ -1857,7 +1859,7 @@ void ftpd_init() } } - ad2_printf_host(true, "%s: Init done. Daemon starting.", TAG); + ad2_printf_host(true, "%s: Init done.", TAG); xTaskCreate(&ftp_daemon_task, "ftp daemon", 1024*8, NULL, tskIDLE_PRIORITY+1, NULL); } diff --git a/components/otaupdate/ota_util.cpp b/components/otaupdate/ota_util.cpp index cb252f58..e6a25391 100644 --- a/components/otaupdate/ota_util.cpp +++ b/components/otaupdate/ota_util.cpp @@ -56,6 +56,7 @@ static const char *TAG = "AD2OTA"; #define OTA_VERSION_CMD "version" #define OTA_FIRST_CHECK_DELAY_MS 30*1000 +#define OTA_RETRY_CHECK_DELAY_MS 300*1000 #define OTA_SOCKET_TIMEOUT 10*1000 // forward decl @@ -719,7 +720,14 @@ esp_err_t ota_https_read_version_info(char **version_info, unsigned int *version */ static void ota_polling_task_func(void *arg) { + uint32_t delay = OTA_FIRST_CHECK_DELAY_MS; + static int fail_count = 0; while (1) { + // failed too many times skip for 24h + if (fail_count > 2) { + fail_count--; + delay = 24 * 3600; + } #if defined(AD2_STACK_REPORT) #define EXTRA_INFO_EVERY 1 static int extra_info = EXTRA_INFO_EVERY; @@ -729,7 +737,7 @@ static void ota_polling_task_func(void *arg) } #endif - vTaskDelay(OTA_FIRST_CHECK_DELAY_MS / portTICK_PERIOD_MS); + vTaskDelay(delay / portTICK_PERIOD_MS); ESP_LOGI(TAG, "Starting check new version with current version '%s'-%s", FIRMWARE_VERSION, FIRMWARE_BUILDFLAGS); @@ -738,8 +746,10 @@ static void ota_polling_task_func(void *arg) continue; } - if (!hal_get_network_connected()) { - ESP_LOGI(TAG, "Device update check aborted. No internet connection."); + if (!hal_get_netif_started()) { + ESP_LOGI(TAG, "Device update check aborted. Network interface not started."); + delay = OTA_RETRY_CHECK_DELAY_MS; + fail_count++; continue; } @@ -759,9 +769,13 @@ static void ota_polling_task_func(void *arg) if (available_version) { free(available_version); } + fail_count++; continue; } + // reset fail count upon success + fail_count = 0; + // Update and notify subscribers of a new version if (available_version) { ota_available_version = available_version; @@ -775,7 +789,7 @@ static void ota_polling_task_func(void *arg) } } - /* Set polling period */ + /* Get polling period in days from server response and set it */ unsigned int polling_day = ota_get_polling_period_day(); unsigned int task_delay_sec = polling_day * 24 * 3600; vTaskDelay(task_delay_sec * 1000 / portTICK_PERIOD_MS); diff --git a/components/pushover/pushover.cpp b/components/pushover/pushover.cpp index 7b6ff377..063558c1 100644 --- a/components/pushover/pushover.cpp +++ b/components/pushover/pushover.cpp @@ -98,7 +98,6 @@ class request_message */ static void _sendQ_ready_handler(esp_http_client_handle_t client, esp_http_client_config_t *config) { - esp_err_t err; // if perform failed this can be NULL if (client) { request_message *r = (request_message*) config->user_data; @@ -109,7 +108,7 @@ static void _sendQ_ready_handler(esp_http_client_handle_t client, esp_http_clien "&message=" + ad2_urlencode(r->message)); // does not copy data just a pointer so we have to maintain memory. - err = esp_http_client_set_post_field(client, r->post.c_str(), r->post.length()); + esp_http_client_set_post_field(client, r->post.c_str(), r->post.length()); } } @@ -247,7 +246,9 @@ void on_search_match_cb_pushover(std::string *msg, AD2PartitionState *s, void *a // Add client config to the http_sendQ for processing. bool res = ad2_add_http_sendQ(r->config_client, _sendQ_ready_handler, _sendQ_done_handler); - if (!res) { + if (res) { + ESP_LOGI(TAG,"Switch #%i match message '%s'. Sending '%s' to acid #%i", es->INT_ARG, msg->c_str(), es->out_message.c_str(), notify_slot); + } else { ESP_LOGE(TAG,"Error adding HTTP request to ad2_add_http_sendQ."); // destroy storage class if we fail to add to the sendQ delete r; @@ -293,11 +294,11 @@ static void _cli_cmd_pushover_event_generic(std::string &subcmd, const char *str // if (ad2_copy_nth_arg(buf, string, 3) >= 0) { ad2_set_config_key_string(PUSHOVER_CONFIG_SECTION, subcmd.c_str(), buf.c_str(), accountId); - ad2_printf_host(false, "Setting #%02i '%s' value '%s' finished.\r\n", accountId, subcmd.c_str(), buf.c_str()); + ad2_printf_host(false, "Setting #%i '%s' value '%s' finished.\r\n", accountId, subcmd.c_str(), buf.c_str()); } else { buf = ""; ad2_get_config_key_string(PUSHOVER_CONFIG_SECTION, subcmd.c_str(), buf, accountId); - ad2_printf_host(false, "Current #%02i '%s' value '%s'\r\n", accountId, subcmd.c_str(), buf.length() ? buf.c_str() : "EMPTY"); + ad2_printf_host(false, "Current #%i '%s' value '%s'\r\n", accountId, subcmd.c_str(), buf.length() ? buf.c_str() : "EMPTY"); } } else { ad2_printf_host(false, "Missing or invalid [1-8].\r\n"); @@ -360,7 +361,6 @@ static void _cli_cmd_pushover_smart_alert_switch(std::string &subcmd, const char PUSHOVER_CONFIG_SWITCH_SUFFIX_TROUBLE); std::string sk; - bool command_found = false; ad2_printf_host(false, "## [pushover] switch %i configuration.\r\n", swID); while (ss >> sk) { tbuf = ""; @@ -555,6 +555,7 @@ void pushover_init() // load [switch N] required regex match settings std::string prefilter_regex; ad2_get_config_key_string(key.c_str(), AD2SWITCH_SK_FILTER, prefilter_regex); + es1->PRE_FILTER_REGEX = prefilter_regex; // Load all regex search patterns for open, close, and trouble sub keys. std::string regex_sk_list = AD2SWITCH_SK_OPEN " " diff --git a/components/ser2sock/ser2sock.cpp b/components/ser2sock/ser2sock.cpp index 38dde8d0..66229d10 100644 --- a/components/ser2sock/ser2sock.cpp +++ b/components/ser2sock/ser2sock.cpp @@ -257,10 +257,9 @@ void ser2sockd_init(void) return; } - ad2_printf_host(true, "%s: Init done, daemon starting.", TAG); - // ser2sockd worker thread // 20210815SM: 1284 bytes stack free after first connection. + ad2_printf_host(true, "%s: Init done, daemon starting.", TAG); xTaskCreate(&ser2sockd_server_task, "AD2 ser2sockd", 1024*4, NULL, tskIDLE_PRIORITY+1, NULL); } @@ -698,12 +697,25 @@ void ser2sockd_server_task(void *pvParameters) struct timeval wait; #if defined(S2SD_DEBUG) - ESP_LOGI(TAG, "ser2sock server task starting."); + ESP_LOGI(TAG, "%s waiting for network layer to start.", TAG); +#endif + while (1) { + if (!hal_get_netif_started()) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } else { + break; + } + } + ESP_LOGI(TAG, "Network layer is OK. %s client starting.", TAG); + + +#if defined(S2SD_DEBUG) + ESP_LOGI(TAG, "%s waiting for network IP layer to start.", TAG); #endif for (;;) { if (hal_get_network_connected()) { #if defined(S2SD_DEBUG) - ESP_LOGI(TAG, "network up creating listening socket"); + ESP_LOGI(TAG, "Network IP layer is OK. %s daemon service starting.", TAG); #endif #if CONFIG_LWIP_IPV6 // IPv6 socket will listen on both IPv4 and IPv6 at the same time. diff --git a/components/stsdk/stsdk_main.cpp b/components/stsdk/stsdk_main.cpp index 196e96a7..6b844d9a 100644 --- a/components/stsdk/stsdk_main.cpp +++ b/components/stsdk/stsdk_main.cpp @@ -1002,6 +1002,11 @@ void stsdk_init(void) device_info_json = cJSON_Print(root); ctx = st_conn_init(onboarding_config, onboarding_config_len, (unsigned char*)device_info_json, strlen(device_info_json)); + // if ctx is good then the network layer should be up. + if (ctx != NULL) { + hal_set_netif_started(true); + } + //cJSON_free(device_info_json); cJSON_Delete(root); diff --git a/components/twilio/twilio.cpp b/components/twilio/twilio.cpp index 7bb72a83..ca5a7a78 100644 --- a/components/twilio/twilio.cpp +++ b/components/twilio/twilio.cpp @@ -500,7 +500,7 @@ void on_search_match_cb_tw(std::string *msg, AD2PartitionState *s, void *arg) AD2EventSearch *es = (AD2EventSearch *)arg; #if defined(DEBUG_TWILIO) - ESP_LOGI(TAG, "ON_SEARCH_MATCH_CB: '%s' -> '%s' notify slot #%02i", msg->c_str(), es->out_message.c_str(), es->INT_ARG); + ESP_LOGI(TAG, "ON_SEARCH_MATCH_CB: '%s' -> '%s' notify slot #%i", msg->c_str(), es->out_message.c_str(), es->INT_ARG); #endif // es->PTR_ARG is the notification slots std::list for this notification. std::list *notify_list = (std::list*)es->PTR_ARG; @@ -663,7 +663,7 @@ static void _cli_cmd_twilio_event_generic(std::string &subcmd, const char *strin buf = "Y"; } } - ad2_printf_host(false, "Current acid #%02i '%s' value '%s'\r\n", accountId, subcmd.c_str(), buf.length() ? buf.c_str() : "EMPTY"); + ad2_printf_host(false, "Current acid #%i '%s' value '%s'\r\n", accountId, subcmd.c_str(), buf.length() ? buf.c_str() : "EMPTY"); } } else { ad2_printf_host(false, "Missing or invalid [1-999].\r\n"); diff --git a/components/webUI/webUI.cpp b/components/webUI/webUI.cpp index a29532fb..9e4936e8 100644 --- a/components/webUI/webUI.cpp +++ b/components/webUI/webUI.cpp @@ -583,6 +583,17 @@ esp_err_t http_acl_test(httpd_handle_t hd, int sockfd) void webui_server_task(void *pvParameters) { esp_err_t err; +#if defined(FTPD_DEBUG) + ESP_LOGI(TAG, "%s waiting for network layer to start.", TAG); +#endif + while (1) { + if (!hal_get_netif_started()) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } else { + break; + } + } + ESP_LOGI(TAG, "Network layer OK. %s daemon service starting.", TAG); // Configure the web server and handlers. server_config.uri_match_fn = httpd_uri_match_wildcard; @@ -758,12 +769,6 @@ void webui_register_cmds() */ void webui_init(void) { - // if netif not enabled then we can't start. - if (!hal_get_netif_started()) { - ad2_printf_host(true, "%s daemon disabled. Network interface not enabled.", TAG); - return; - } - bool en = -1; ad2_get_config_key_bool(WEBUI_CONFIG_SECTION, WEBUI_SUBCMD_ENABLE, &en); @@ -784,8 +789,6 @@ void webui_init(void) } } - ad2_printf_host(true, "%s: Init done, daemon starting.", TAG); - // Subscribe to AlarmDecoder events AD2Parse.subscribeTo(ON_ARM, webui_on_state_change, (void *)ON_ARM); AD2Parse.subscribeTo(ON_DISARM, webui_on_state_change, (void *)ON_DISARM); @@ -801,6 +804,7 @@ void webui_init(void) // SUbscribe to ON_ZONE_CHANGE events AD2Parse.subscribeTo(ON_ZONE_CHANGE, webui_on_state_change, (void *)ON_ZONE_CHANGE); + ad2_printf_host(true, "%s: Init done, daemon starting.", TAG); xTaskCreate(&webui_server_task, "AD2 webUI", 1024*5, NULL, tskIDLE_PRIORITY+1, NULL); } diff --git a/main/ad2_cli_cmd.cpp b/main/ad2_cli_cmd.cpp index d6036335..4552b417 100644 --- a/main/ad2_cli_cmd.cpp +++ b/main/ad2_cli_cmd.cpp @@ -526,7 +526,6 @@ static void _cli_cmd_switch_event(const char *command_string) AD2SWITCH_SK_CLOSE " " AD2SWITCH_SK_TROUBLE); - bool command_found = false; ad2_printf_host(false, "## switch %i global configuration.\r\n[%s]\r\n", sId, key.c_str()); sk_index = 0; while (ss >> sk) { diff --git a/main/device_control.cpp b/main/device_control.cpp index 76846622..31853ce8 100644 --- a/main/device_control.cpp +++ b/main/device_control.cpp @@ -68,7 +68,8 @@ const int NET_STA_CONNECT_BIT = BIT2; const int NET_STA_DISCONNECT_BIT = BIT3; const int NET_AP_START_BIT = BIT4; const int NET_AP_STOP_BIT = BIT5; -const int NET_CONNECT_STATE_BITS = BIT1|BIT2|BIT3|BIT4|BIT5; +const int NET_NETIF_HAS_IP = BIT6; +const int NET_CONNECT_STATE_BITS = BIT1|BIT2|BIT3|BIT4|BIT5|BIT6; static bool switchAState = SWITCH_OFF; static bool switchBState = SWITCH_OFF; @@ -439,8 +440,7 @@ void hal_init_network_stack() ESP_ERROR_CHECK(esp_event_loop_create_default()); #endif - - xEventGroupSetBits(g_ad2_net_event_group, NET_NETIF_STARTED_BIT); + hal_set_netif_started(true); ESP_LOGI(TAG, "network TCP/IP stack init finish"); return; @@ -982,6 +982,18 @@ bool hal_get_netif_started() return xEventGroupGetBits(g_ad2_net_event_group) & NET_NETIF_STARTED_BIT; } +/** + * @brief Set network interface stack init state. + */ +void hal_set_netif_started(bool started) +{ + if (started) { + xEventGroupSetBits(g_ad2_net_event_group, NET_NETIF_STARTED_BIT); + } else { + xEventGroupClearBits(g_ad2_net_event_group, NET_NETIF_STARTED_BIT); + } +} + /** * @brief Get ip network connection state. */ @@ -990,6 +1002,18 @@ bool hal_get_network_connected() return xEventGroupGetBits(g_ad2_net_event_group) & NET_STA_CONNECT_BIT; } +/** + * @brief SET ip network connection state. + */ +void hal_set_network_connected(bool connected) +{ + if (connected) { + xEventGroupSetBits(g_ad2_net_event_group, NET_STA_CONNECT_BIT); + } else { + xEventGroupClearBits(g_ad2_net_event_group, NET_STA_CONNECT_BIT); + } +} + /** * @brief Do an OTA update. */ @@ -1006,18 +1030,6 @@ uint64_t hal_uptime_us() return esp_timer_get_time(); } -/** - * @brief get CONNECTED state. - */ -void hal_set_network_connected(bool set) -{ - ESP_LOGD(TAG, "hal_set_network_connected %i", set); - if (set) { - xEventGroupSetBits(g_ad2_net_event_group, NET_STA_CONNECT_BIT); - } else { - xEventGroupClearBits(g_ad2_net_event_group, NET_STA_CONNECT_BIT); - } -} /** * @brief Initialize the uSD reader if one is connected. @@ -1051,7 +1063,6 @@ bool hal_init_sd_card() } else { ad2_printf_host(false, " pass."); // show stats and return true - size_t total = 0, used = 0; FATFS *fs; DWORD fre_clust, fre_sect, tot_sect; FRESULT res; diff --git a/main/device_control.h b/main/device_control.h index 6468bba7..eb7601e3 100644 --- a/main/device_control.h +++ b/main/device_control.h @@ -133,9 +133,10 @@ void hal_set_eth_hostname(const char *); void hal_host_uart_init(); void hal_ad2_reset(); bool hal_get_netif_started(); +void hal_set_netif_started(bool connected); bool hal_get_network_connected(); +void hal_set_network_connected(bool connected); void hal_ota_do_update(const char *); -void hal_set_network_connected(bool); bool hal_init_sd_card(); void hal_get_socket_client_ip(int sockfd, std::string& IP); void hal_get_socket_local_ip(int sockfd, std::string& IP); From 0185033f03665754dc7d4c0431f8e618d35d7080 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 11:42:23 -0700 Subject: [PATCH 89/97] test automated build --- sdkconfig.defaults | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 8cdb3515..856d0e9d 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -90,22 +90,14 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings -#CONFIG_STDK_IOT_CORE=y -#CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y -#CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y -#CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -#CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +CONFIG_STDK_IOT_CORE=y +CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y +CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y +CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y +# CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG is not set # CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set -#CONFIG_STDK_IOT_CORE_LOG_FILE=y -#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_ONLY=y -#CONFIG_STDK_IOT_CORE_LOG_FILE_RAM_BUF_SIZE=8192 -#CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y -#CONFIG_STDK_IOT_CORE_OS_SUPPORT_FREERTOS=y -#CONFIG_STDK_IOT_CORE_USE_MBEDTLS=y -#CONFIG_STDK_IOT_CORE_CRYPTO_SUPPORT_ED25519=y -#CONFIG_STDK_IOT_CORE_SECURITY_BACKEND_SOFTWARE=y -#CONFIG_STDK_IOT_CORE_FS_HW_ENCRYPTION=y -#CONFIG_STDK_IOT_CORE_NET_MBEDTLS=y # AD2IoT network settings CONFIG_AD2IOT_USE_WIFI=y @@ -113,10 +105,10 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=y +CONFIG_AD2IOT_TOP=n CONFIG_AD2IOT_FTP_DAEMON=y -CONFIG_AD2IOT_MQTT_CLIENT=y +CONFIG_AD2IOT_MQTT_CLIENT=n CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y CONFIG_AD2IOT_TWILIO_CLIENT=y -CONFIG_AD2IOT_PUSHOVER_CLIENT=y \ No newline at end of file +CONFIG_AD2IOT_PUSHOVER_CLIENT=y From a37de2c5aa7e1726a10b7eec7f69367d004cf9c3 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 12:01:16 -0700 Subject: [PATCH 90/97] ... --- sdkconfig.defaults | 1 + 1 file changed, 1 insertion(+) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 856d0e9d..6106c14c 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -93,6 +93,7 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" CONFIG_STDK_IOT_CORE=y CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP_USE_SOCKET_API=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y From 3e4943f2ab6f4a633b0524730f5d7a9184395b4d Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 12:08:13 -0700 Subject: [PATCH 91/97] ... --- sdkconfig.defaults | 1 + 1 file changed, 1 insertion(+) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 6106c14c..160a3193 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -92,6 +92,7 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings CONFIG_STDK_IOT_CORE=y CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y +CONFIG_STDK_IOT_CORE_EASYSETUP_DISCOVERY_SSID=y CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP_USE_SOCKET_API=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y From cf54da743d35ba43ea4d738ffa395b7660a5b81f Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 12:18:27 -0700 Subject: [PATCH 92/97] ... --- sdkconfig.defaults.stsdk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk index 856d0e9d..160a3193 100644 --- a/sdkconfig.defaults.stsdk +++ b/sdkconfig.defaults.stsdk @@ -92,7 +92,9 @@ CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" # STSDK build settings CONFIG_STDK_IOT_CORE=y CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y +CONFIG_STDK_IOT_CORE_EASYSETUP_DISCOVERY_SSID=y CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y +CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP_USE_SOCKET_API=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y From 24ceec8fbeed913d3c22881cc3bce1174753bb89 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 12:33:00 -0700 Subject: [PATCH 93/97] ... --- .github/workflows/build.yml | 7 +-- sdkconfig.defaults.stsdk | 116 ------------------------------------ 2 files changed, 2 insertions(+), 121 deletions(-) delete mode 100644 sdkconfig.defaults.stsdk diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6848a3a4..26329525 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,8 +45,6 @@ jobs: - name: setup build environment for stsdk-c-ref and build AlarmDecoder-IoT for SmartThings run: | - # Overwrite defaults and restore when done with build. - cp sdkconfig.defaults.stsdk sdkconfig.defaults cd .st-device-sdk-c-ref git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" @@ -54,10 +52,9 @@ jobs: ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT cd .. - # Restore defaults and remove any sdkconfig created in build. - git checkout sdkconfig.defaults + # Remove any sdkconfig created in build. + ls -l sdkconfig rm sdkconfig - # No need to make clean later build with pio will use a different work folder. - name: Install PlatformIO Core run: pip install --upgrade platformio diff --git a/sdkconfig.defaults.stsdk b/sdkconfig.defaults.stsdk deleted file mode 100644 index 160a3193..00000000 --- a/sdkconfig.defaults.stsdk +++ /dev/null @@ -1,116 +0,0 @@ -# Compiler settings -CONFIG_COMPILER_CXX_EXCEPTIONS=y -CONFIG_CXX_EXCEPTIONS=y -CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 -CONFIG_COMPILER_OPTIMIZATION_SIZE=y - -# FreeRTOS settings -CONFIG_FREERTOS_UNICORE=y -CONFIG_FREERTOS_ISR_STACKSIZE=2096 -CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y -CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y -CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y -CONFIG_FREERTOS_USE_TRACE_FACILITY=y - -# General settings -CONFIG_LOG_COLORS=n -CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y -CONFIG_BOOTLOADER_LOG_LEVEL=0 - -# Hardware specific settings -CONFIG_ESP_INT_WDT_TIMEOUT_MS=3000 -## ESP32-WROOM-32E -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_BOOTLOADER_SPI_WP_PIN=7 -CONFIG_ESPTOOLPY_FLASHSIZE="4MB" -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -## ESP32-POE-ISO ETHERNET config -CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ETH_PHY_INTERFACE_RMII=y -CONFIG_ETH_RMII_CLK_OUT_GPIO=17 -CONFIG_ETH_RMII_CLK_OUTPUT=y -CONFIG_AD2IOT_ETH_PHY_LAN8720=y -CONFIG_AD2IOT_ETH_MDC_GPIO=23 -CONFIG_AD2IOT_ETH_MDIO_GPIO=18 -CONFIG_AD2IOT_ETH_PHY_RST_GPIO=-1 -CONFIG_AD2IOT_ETH_PHY_POWER_GPIO=12 -CONFIG_AD2IOT_ETH_PHY_ADDR=0 - -# Partition settings -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.4MB.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.4MB.csv" -CONFIG_PARTITION_TABLE_OFFSET=0x8000 -CONFIG_PARTITION_TABLE_MD5=y - -# FATFS settings -CONFIG_FATFS_LFN_HEAP=y -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_CODEPAGE=437 -CONFIG_FATFS_CODEPAGE_437=y -CONFIG_FATFS_MAX_LFN=255 -CONFIG_FATFS_API_ENCODING_ANSI_OEM=y -CONFIG_FATFS_FS_LOCK=0 -CONFIG_FATFS_TIMEOUT_MS=10000 -CONFIG_FATFS_PER_FILE_CACHE=y - -# Coredump settings -CONFIG_ESP_COREDUMP_ENABLE=y -CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y -CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y -CONFIG_ESP_COREDUMP_CHECKSUM_CRC32=y -CONFIG_ESP_COREDUMP_CHECK_BOOT=y -CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=20 - -# LWIP settings -CONFIG_LWIP_LOCAL_HOSTNAME="ad2iot" -CONFIG_LWIP_IPV6_AUTOCONFIG=y -CONFIG_LWIP_MAX_SOCKETS=16 - -# MQTT client settings -CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_TRANSPORT_SSL=y -CONFIG_MQTT_TRANSPORT_WEBSOCKET=y -CONFIG_MQTT_MSG_ID_INCREMENTAL=y -CONFIG_MQTT_REPORT_DELETED_MESSAGES=y - -# HTTP(s) / WebSockets server -CONFIG_ESP_HTTPS_SERVER_ENABLE=y -CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y -CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y -CONFIG_HTTPD_WS_SUPPORT=y -## TODO: Make better... -CONFIG_ESP_TLS_INSECURE=y -CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y - -# SSL/TLS certificate bundles -CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y -CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y -CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certs" - -# STSDK build settings -CONFIG_STDK_IOT_CORE=y -CONFIG_STDK_IOT_CORE_BSP_SUPPORT_ESP32=y -CONFIG_STDK_IOT_CORE_EASYSETUP_DISCOVERY_SSID=y -CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP=y -CONFIG_STDK_IOT_CORE_EASYSETUP_HTTP_USE_SOCKET_API=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_ERROR=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_WARN=y -CONFIG_STDK_IOT_CORE_LOG_LEVEL_INFO=y -# CONFIG_STDK_IOT_CORE_LOG_LEVEL_DEBUG is not set -# CONFIG_STDK_IOT_CORE_SUPPORT_STNV_PARTITION is not set - -# AD2IoT network settings -CONFIG_AD2IOT_USE_WIFI=y -CONFIG_AD2IOT_USE_ETHERNET=y -CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y - -# AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=n -CONFIG_AD2IOT_FTP_DAEMON=y -CONFIG_AD2IOT_MQTT_CLIENT=n -CONFIG_AD2IOT_WEBSERVER_UI=y -CONFIG_AD2IOT_SER2SOCKD=y -CONFIG_AD2IOT_TWILIO_CLIENT=y -CONFIG_AD2IOT_PUSHOVER_CLIENT=y From ad50bce89bfdc19c8d1b3938af076fe741c9b9f0 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 12:50:44 -0700 Subject: [PATCH 94/97] ... --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 26329525..773dc43c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,8 +52,7 @@ jobs: ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ python build.py esp32 AlarmDecoder-IoT cd .. - # Remove any sdkconfig created in build. - ls -l sdkconfig + # Remove any sdkconfig created in build to be safe. rm sdkconfig - name: Install PlatformIO Core From fb6b4e54a629c5a00a9d776fbc4e89457ee9c4bf Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 12:52:11 -0700 Subject: [PATCH 95/97] ... --- sdkconfig.defaults | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 160a3193..d23ccc25 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -107,7 +107,7 @@ CONFIG_AD2IOT_USE_ETHERNET=y CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable -CONFIG_AD2IOT_TOP=n +CONFIG_AD2IOT_TOP=y CONFIG_AD2IOT_FTP_DAEMON=y CONFIG_AD2IOT_MQTT_CLIENT=n CONFIG_AD2IOT_WEBSERVER_UI=y From 210f64f6ed2781a0ffc49530c235846a1e749454 Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Thu, 8 Jun 2023 13:08:17 -0700 Subject: [PATCH 96/97] ... --- sdkconfig.defaults | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index d23ccc25..2c890d1a 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -109,7 +109,7 @@ CONFIG_AD2IOT_USE_INTERNAL_ETHERNET=y # AD2IoT default components enable/disable CONFIG_AD2IOT_TOP=y CONFIG_AD2IOT_FTP_DAEMON=y -CONFIG_AD2IOT_MQTT_CLIENT=n +CONFIG_AD2IOT_MQTT_CLIENT=y CONFIG_AD2IOT_WEBSERVER_UI=y CONFIG_AD2IOT_SER2SOCKD=y CONFIG_AD2IOT_TWILIO_CLIENT=y From eb32abca78dabf39f76a5c7093dfcee94ea5fc9c Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 26 Nov 2023 13:10:57 -0800 Subject: [PATCH 97/97] ... --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 773dc43c..a29fbc63 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -92,4 +92,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: AD2IoT-Release-Package - path: AD2IoT-Release \ No newline at end of file + path: AD2IoT-Release