diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..a29fbc63 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,95 @@ +name: CI build + +on: [push, workflow_dispatch] + +env: + PP: AD2IoT-Release + SHELL: /bin/bash + TERM: 'xterm-256color' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - 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: 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 + + - name: Checkout st-device-sdk-c-ref + uses: actions/checkout@v3 + with: + repository: SmartThingsCommunity/st-device-sdk-c-ref + path: ./.st-device-sdk-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" + git config --global user.email "<>" + python setup.py esp32 + ln -s $RUNNER_WORKSPACE/AlarmDecoder-IoT apps/esp32/ + python build.py esp32 AlarmDecoder-IoT + cd .. + # Remove any sdkconfig created in build to be safe. + rm sdkconfig + + - name: Install PlatformIO Core + run: pip install --upgrade platformio + + - 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: Create release package folders for each branch. + run: | + mkdir $PP/esp32/esp32-poe-iso-stsdk + mkdir $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. + 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/ + 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 + with: + name: AD2IoT-Release-Package + path: AD2IoT-Release diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index afe8ed51..00000000 --- a/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -dist: xenial -sudo: required - -language: python - -python: - - "nightly" - -os: - - linux - -cache: - pip: true - directories: - - "~/.platformio" - - $HOME/astyle - -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 - -notifications: - email: - on_success: change - on_failure: change diff --git a/CHANGELOG.md b/CHANGELOG.md index 017d07c3..936c68d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,36 +4,64 @@ 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 - [ ] 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 -- [ ] 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.1] - 2022-09-18 Sean Mathews - coder @f34rdotcom +## [1.1.0 P2] - 2023-01-?? Sean Mathews - coder @f34rdotcom +Changes: + - 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 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. + - 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. + - [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 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. + - [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. + - [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.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/README.md b/README.md index a0dc4551..b4c414d2 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) @@ -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) @@ -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 @@ -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.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 -- Enabled components: Pushover, Twilio, Sendgrid, ser2sock, webUI, MQTT, ftpd. - -This build uses the latest ESP-IDF v4.3 with the SmartThings driver is disabled. +### 3.1. webUI build (webui) - esp32/esp32-poe-iso-webui +- 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. - 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, 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. @@ -99,7 +97,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. @@ -110,9 +108,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. @@ -231,6 +229,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 +255,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 +281,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} {zero padded 3 digit 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 003 +close 1 = ZONE CLOSE 003 +trouble 1 = ZONE TROUBLE 003 + +[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 +347,12 @@ Options: - Delete entry value Code string ``` +```console +# Example config file ini setting +[code] +1 = 4112 +2 = 1234 +``` - ad2term ```console Usage: ad2term [reset] @@ -325,6 +376,14 @@ 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 +# 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 @@ -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,27 +830,68 @@ 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. 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 + +# Get and install esp-idf toolchain v5.0(AF), v4.3.2(AF), 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 -``` +git clone -b v5.0 --recursive https://github.com/espressif/esp-idf.git -- Place the contents of this his project in ```st-device-sdk-c-ref/apps/esp32/``` +cd ~/esp/esp-idf +## Added esp32 to the end. Need to test above again with this change. +./install.sh esp32 -#### 6.2.2. Configure the project +## 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 +git clone https://github.com/SmartThingsCommunity/st-device-sdk-c-ref.git +cd st-device-sdk-c-ref +python setup.py esp32 + +# 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. + - Component config: + - Enable ```SmartThings IoT Core``` + - Enable ESP32 support. ```BSP Support(ESP32)``` + - Disable ```AD2Iot * FTP demon``` ``` -./build.sh esp32 AlarmDecoder-IoT menuconfig +cd ~/esp/st-device-sdk-c-ref +python build.py esp32 AlarmDecoder-IoT menuconfig ``` #### 6.2.3. Build, Flash, and Run @@ -759,7 +899,8 @@ cd ~/esp Build the project and flash it to the board, then run monitor tool to view serial output: ``` -./build.sh esp32 AlarmDecoder-IoT build flash monitor -p /dev/ttyUSB0 +cd ~/esp/st-device-sdk-c-ref +python build.py esp32 AlarmDecoder-IoT build flash monitor -p /dev/ttyUSB0 ``` (To exit the serial monitor, type ``Ctrl-]``.) 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 diff --git a/components/ad2mqtt/ad2mqtt.cpp b/components/ad2mqtt/ad2mqtt.cpp index 2638ea5d..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 " " @@ -1347,18 +1375,18 @@ 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); } } } 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/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/ftpd/ftpd.cpp b/components/ftpd/ftpd.cpp index b306cc20..c8ec63e6 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" @@ -1774,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); @@ -1819,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); @@ -1850,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 f7c41460..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 " " @@ -601,12 +602,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/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/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/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/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 616a5898..6b844d9a 100644 --- a/components/stsdk/stsdk_main.cpp +++ b/components/stsdk/stsdk_main.cpp @@ -41,10 +41,16 @@ static const char *TAG = "STSDK"; #include "esp_netif.h" #endif +static bool _enabled = false; + // specific includes #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; @@ -58,10 +64,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 */ @@ -82,6 +84,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 +202,131 @@ caps_momentary_data_t *cap_momentary_data_disarm; /** - * Enable/Disable STSDK component. + * @brief SmartThings generic command event processing + * command: [COMMAND] + * ex. + * [COMMAND] 0 arg... */ -static void _cli_cmd_enable_event(char *string) +static void _cli_cmd_stsdk_event(const 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")); - -} + // key value validation + std::string cmd; + ad2_copy_nth_arg(cmd, string, 0); + ad2_lcase(cmd); -/** - * 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 - * ex. - * stserial AaBbCcDdEeFf... - */ -static void _cli_cmd_stserial_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, "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"); + 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: 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 subcmd; + ad2_copy_nth_arg(subcmd, string, 1); + ad2_lcase(subcmd); -/** - * 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); + int i; + 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"); + } + + // 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. + */ + 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 + 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 '" STSDK_SUBCMD_SERIAL "' arg missing.\r\n"); + break; + /** + * SmartThings PrivateKey. + */ + case STSDK_SUBCMD_PRIVKEY_ID: + // 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 '" STSDK_SUBCMD_PRIVKEY "' arg missing.\r\n"); + break; + /** + * SmartThings PublicKey. + */ + case STSDK_SUBCMD_PUBKEY_ID: + // 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 '" STSDK_SUBCMD_PUBKEY "' 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 @@ -996,23 +970,46 @@ 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; - ad2_get_config_key_bool(STSDK_ENABLE, 0, nullptr, &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; } 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)); + + // 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); + if (ctx != NULL) { iot_err = st_conn_set_noti_cb(ctx, iot_noti_cb, NULL); if (iot_err) { @@ -1330,6 +1327,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) { @@ -1465,6 +1464,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/components/twilio/twilio.cpp b/components/twilio/twilio.cpp index 65019f5f..ca5a7a78 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) { @@ -474,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; @@ -637,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"); @@ -953,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/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/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png b/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png new file mode 100644 index 00000000..eae14081 Binary files /dev/null and b/contrib/ESP32-DOWNLOAD-TOOL-UPLOADING-FIRMWARE.png differ diff --git a/contrib/README-FLASH-ESP32.md b/contrib/README-FLASH-ESP32.md new file mode 100644 index 00000000..294e2394 --- /dev/null +++ b/contrib/README-FLASH-ESP32.md @@ -0,0 +1,23 @@ +### 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 + +- 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 + + +#### 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 diff --git a/contrib/README-FLASH.md b/contrib/README-FLASH.md deleted file mode 100644 index f950eb2f..00000000 --- a/contrib/README-FLASH.md +++ /dev/null @@ -1,13 +0,0 @@ -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 - - -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. Drivers may be required. -Press start. - -Use Putty to connect to the COM port and configure the device. 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 9fbcdc21..4244866d 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 ############################################################################### @@ -37,7 +38,11 @@ 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. ad2config = address=18&mode=A ############################################################################### @@ -160,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)"} @@ -198,12 +204,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 003 +close 1 = ZONE CLOSE 003 +trouble 1 = ZONE TROUBLE 003 + [switch 60] # RFX serial 0123456 default = -1 @@ -420,6 +436,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 +449,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 @@ -446,7 +470,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: @@ -495,6 +519,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 +534,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/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) diff --git a/main/ad2_cli_cmd.cpp b/main/ad2_cli_cmd.cpp index 24159839..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) { @@ -704,7 +703,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" @@ -803,6 +802,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 }, { 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" 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 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); diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 00f7f015..2c890d1a 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -1,18 +1,50 @@ -# GENERAL +# 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_OPTIMIZATION_LEVEL_RELEASE=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 -# CONFIG_FATFS_LFN_NONE is not set + +# FATFS settings CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_CODEPAGE_437=y CONFIG_FATFS_CODEPAGE=437 @@ -22,61 +54,63 @@ 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" + +# 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 -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 -CONFIG_AD2IOT_SER2SOCKD=y -CONFIG_AD2IOT_WEBSERVER_UI=y -CONFIG_AD2IOT_MQTT_CLIENT=y