[LED] Refactor LED handling (#2051)

Refactor LED handling into a library
Use a task instead of relying on the loop for precise timing

Co-authored-by: Florian <1technophile@users.noreply.github.com>
This commit is contained in:
FlorianandFlorian authored and GitHub committed 2024-09-13 09:55:56 -05:00
1 parent 20af9ccf11
commit 435b8ca3d9
14 files changed
+932 -437

No files matched your search

+1
View File
@@ -9,6 +9,7 @@ main/certs/private*
lib/* lib/*
!lib/esp32-bt-lib !lib/esp32-bt-lib
!lib/TheengsUtils !lib/TheengsUtils
!lib/LEDManager
CMakeLists.txt CMakeLists.txt
dependencies.lock dependencies.lock
sdkconfig.* sdkconfig.*
+90 -10
View File
@@ -300,17 +300,97 @@ Minimum: 0, Maximum: 255, Default defined by DEFAULT_ADJ_BRIGHTNESS
`mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"brightness":200}'` `mosquitto_pub -t "home/OpenMQTTGateway/commands/MQTTtoSYS/config" -m '{"brightness":200}'`
## State LED usage ## Understanding LED Indicators in OpenMQTTGateway
With boards having one or several RGB Led, OpenMQTTGateway uses them to provide visual feedback about its current state. This guide will help you interpret these LED signals to understand what's happening with your gateway.
The gateway can support up to 3 LED to display its operating state: ## LED Color Guide
* LED_INFO OpenMQTTGateway uses a variety of colors to indicate different states:
switched ON when network and MQTT connection are OK
5s ON, 5s OFF when MQTT is disconnected
2s ON, 2s OFF when NETWORK is disconnected
* LED_RECEIVE Green (0x00FF00): Indicates normal operation or successful connections
Blink for `TimeLedON` 1s when the gateway receive a signal from one of its module so as to send to MQTT Blue (0x0000FF): Shows processing or offline status
Orange (0xFFA500): Indicates waiting states or minor issues
Yellow (0xFFFF00): Used during the onboarding process
Red (0xFF0000): Signals an error state
Magenta (0xFF00FF): Indicates local Over-The-Air (OTA) updates
Purple (0x8000FF): Shows remote OTA updates are in progress
* LED_SEND ## Understanding Gateway States
Blink for `TimeLedON` 1s when the gateway send a signal with one of its module from an MQTT command Here's what different LED behaviors mean:
### Power On
Color: Green
Behavior: Solid light
Meaning: The gateway is powered and operational
### Processing
Color: Blue
Behavior: Blinking (3 times)
Meaning: The gateway is processing data
### Waiting for Onboarding
Color: Orange
Behavior: Solid light
Meaning: The gateway is ready to be set up
### Onboarding in Progress
Color: Yellow
Behavior: Solid light
Meaning: The gateway is being configured
### Network Connected
Color: Green
Behavior: Solid light
Meaning: Successfully connected to the network
### Network Disconnected
Color: Orange
Behavior: Blinking
Meaning: Lost connection to the network
### MQTT Broker Connected
Color: Green
Behavior: Solid light
Meaning: Successfully connected to the MQTT broker
### MQTT Broker Disconnected
Color: Orange
Behavior: Blinking
Meaning: Lost connection to the MQTT broker
### Offline
Color: Blue
Behavior: Blinking
Meaning: The gateway is offline
### Local OTA Update
Color: Magenta
Behavior: Blinking
Meaning: A local Over-The-Air update is in progress
### Remote OTA Update
Color: Purple
Behavior: Blinking
Meaning: A remote Over-The-Air update is in progress
### Error
Color: Red
Behavior: Blinking (3 times)
Meaning: An error has occurred
### Actuator On/Off
Color: Green
Behavior: Depends on actuator state
Meaning: Indicates the state of a connected actuator
+90 -86
View File
@@ -62,8 +62,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DESP32_ETHERNET=true' '-DESP32_ETHERNET=true'
'-DETH_PHY_TYPE=ETH_PHY_LAN8720' '-DETH_PHY_TYPE=ETH_PHY_LAN8720'
'-DETH_PHY_ADDR=0' '-DETH_PHY_ADDR=0'
@@ -71,13 +71,13 @@ build_flags =
'-DETH_PHY_MDC=23' '-DETH_PHY_MDC=23'
'-DETH_PHY_MDIO=18' '-DETH_PHY_MDIO=18'
'-DETH_CLK_MODE=ETH_CLOCK_GPIO16_OUT' '-DETH_CLK_MODE=ETH_CLOCK_GPIO16_OUT'
'-DANEOPIX_IND_DATA_GPIO=32' '-DLED_ADDRESSABLE_PIN1=32'
'-DANEOPIX_IND_NUM_LEDS=4' '-DLED_ADDRESSABLE_NUM=4'
'-DANEOPIX_INFO_LED=0' '-DLED_BROKER=0'
'-DANEOPIX_SEND_RECEIVE_LED=1' '-DLED_PROCESSING=1'
'-DANEOPIX_ERROR_LED=1' '-DLED_ERROR=1'
'-DANEOPIX_BRIGHTNESS=10' '-DDEFAULT_ADJ_BRIGHTNESS=10'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DAttemptBLEConnect=false' '-DAttemptBLEConnect=false'
'-DUSE_MAC_AS_GATEWAY_NAME' '-DUSE_MAC_AS_GATEWAY_NAME'
'-DGATEWAY_MANUFACTURER="Theengs"' '-DGATEWAY_MANUFACTURER="Theengs"'
@@ -100,8 +100,6 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2'
'-DLED_SEND_RECEIVE_ON=0'
'-DESP32_ETHERNET=true' '-DESP32_ETHERNET=true'
'-DETH_PHY_TYPE=ETH_PHY_LAN8720' '-DETH_PHY_TYPE=ETH_PHY_LAN8720'
'-DETH_PHY_ADDR=0' '-DETH_PHY_ADDR=0'
@@ -109,13 +107,14 @@ build_flags =
'-DETH_PHY_MDC=23' '-DETH_PHY_MDC=23'
'-DETH_PHY_MDIO=18' '-DETH_PHY_MDIO=18'
'-DETH_CLK_MODE=ETH_CLOCK_GPIO16_OUT' '-DETH_CLK_MODE=ETH_CLOCK_GPIO16_OUT'
'-DANEOPIX_IND_DATA_GPIO=32' '-DLED_ADDRESSABLE=true'
'-DANEOPIX_IND_NUM_LEDS=4' '-DLED_ADDRESSABLE_PIN1=32'
'-DANEOPIX_INFO_LED=0' '-DLED_ADDRESSABLE_NUM=4'
'-DANEOPIX_SEND_RECEIVE_LED=1' '-DLED_ERROR=3'
'-DANEOPIX_ERROR_LED=1' '-DLED_PROCESSING=3'
'-DANEOPIX_BRIGHTNESS=100' '-DLED_BROKER=2'
'-DRGB_INDICATORS=true' '-DLED_NETWORK=1'
'-DLED_POWER=0'
'-DAttemptBLEConnect=false' '-DAttemptBLEConnect=false'
'-DTRIGGER_GPIO=4' '-DTRIGGER_GPIO=4'
'-DUSE_MAC_AS_GATEWAY_NAME' '-DUSE_MAC_AS_GATEWAY_NAME'
@@ -331,8 +330,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
custom_description = Regular BLE gateway with adaptive scanning activated, automatically adapts the scan parameters depending on your devices custom_description = Regular BLE gateway with adaptive scanning activated, automatically adapts the scan parameters depending on your devices
@@ -348,8 +347,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
'-DMQTT_BROKER_MODE=true' '-DMQTT_BROKER_MODE=true'
custom_description = MQTT Broker with BLE gateway with adaptive scanning activated, automatically adapts the scan parameters depending on your devices custom_description = MQTT Broker with BLE gateway with adaptive scanning activated, automatically adapts the scan parameters depending on your devices
@@ -366,8 +365,8 @@ build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DBLEDecoder=false' '-DBLEDecoder=false'
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
'-DMQTTDecodeTopic="undecoded"' '-DMQTTDecodeTopic="undecoded"'
custom_description = BLE gateway with the decoding offloaded to Theengs Gateway custom_description = BLE gateway with the decoding offloaded to Theengs Gateway
@@ -385,8 +384,8 @@ build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-UZmqttDiscovery="HADiscovery"' '-UZmqttDiscovery="HADiscovery"'
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DARDUINO_LOOP_STACK_SIZE=17500' '-DARDUINO_LOOP_STACK_SIZE=17500'
'-DMQTT_SECURE_DEFAULT=true' '-DMQTT_SECURE_DEFAULT=true'
'-DMQTT_CERT_VALIDATE_DEFAULT=true' '-DMQTT_CERT_VALIDATE_DEFAULT=true'
@@ -410,8 +409,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=13' '-DLED_PIN=13'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_ESP32_FTH_BLE"' '-DGateway_Name="OMG_ESP32_FTH_BLE"'
custom_description = BLE Gateway custom_description = BLE Gateway
custom_hardware = ESP32 Feather Adafruit custom_hardware = ESP32 Feather Adafruit
@@ -428,8 +427,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=22' '-DLED_PIN=22'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_LOLIN32LITE_BLE"' '-DGateway_Name="OMG_LOLIN32LITE_BLE"'
;; Low power parameters, uncomment and fill credentials ;; Low power parameters, uncomment and fill credentials
'-DDEFAULT_LOW_POWER_MODE=INTERVAL' '-DDEFAULT_LOW_POWER_MODE=INTERVAL'
@@ -458,8 +457,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=33' '-DLED_PIN=33'
'-DLED_SEND_RECEIVE_ON=1' '-DLED_PIN_ON=1'
'-DTRIGGER_GPIO=34' '-DTRIGGER_GPIO=34'
'-DESP32_ETHERNET=true' '-DESP32_ETHERNET=true'
'-DGateway_Name="OMG_ESP32_OLM_GTWE"' '-DGateway_Name="OMG_ESP32_OLM_GTWE"'
@@ -553,8 +552,8 @@ build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DZgatewayIR="IR"' '-DZgatewayIR="IR"'
'-DLED_SEND_RECEIVE=19' '-DLED_PIN=19'
'-DLED_SEND_RECEIVE_ON=1' '-DLED_PIN_ON=1'
'-DTRIGGER_GPIO=35' '-DTRIGGER_GPIO=35'
'-DIR_EMITTER_GPIO=17' '-DIR_EMITTER_GPIO=17'
'-DDEFAULT_LOW_POWER_MODE=ALWAYS_ON' '-DDEFAULT_LOW_POWER_MODE=ALWAYS_ON'
@@ -578,7 +577,7 @@ build_flags =
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DZsensorGPIOInput="GPIOInput"' '-DZsensorGPIOInput="GPIOInput"'
'-DZboardM5STACK="M5Stack"' '-DZboardM5STACK="M5Stack"'
'-DLED_SEND_RECEIVE=15' '-DLED_PIN=15'
'-DTRIGGER_GPIO=37' '-DTRIGGER_GPIO=37'
'-DSLEEP_BUTTON=38' '-DSLEEP_BUTTON=38'
'-DINPUT_GPIO=39' '-DINPUT_GPIO=39'
@@ -626,8 +625,8 @@ build_flags =
'-DZboardM5STICKC="M5StickC"' '-DZboardM5STICKC="M5StickC"'
'-DACTUATOR_ONOFF_GPIO=10' '-DACTUATOR_ONOFF_GPIO=10'
'-DINPUT_GPIO=37' '-DINPUT_GPIO=37'
'-DLED_SEND_RECEIVE=10' '-DLED_PIN=10'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DSLEEP_BUTTON=39' '-DSLEEP_BUTTON=39'
'-DTRIGGER_GPIO=39' '-DTRIGGER_GPIO=39'
'-DIR_EMITTER_INVERTED=true' '-DIR_EMITTER_INVERTED=true'
@@ -657,8 +656,8 @@ build_flags =
'-DZboardM5STICKCP="M5StickCP"' '-DZboardM5STICKCP="M5StickCP"'
'-DACTUATOR_ONOFF_GPIO=10' '-DACTUATOR_ONOFF_GPIO=10'
'-DINPUT_GPIO=37' '-DINPUT_GPIO=37'
'-DLED_SEND_RECEIVE=10' '-DLED_PIN=10'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DSLEEP_BUTTON=39' '-DSLEEP_BUTTON=39'
'-DTRIGGER_GPIO=39' '-DTRIGGER_GPIO=39'
'-DIR_EMITTER_INVERTED=true' '-DIR_EMITTER_INVERTED=true'
@@ -687,9 +686,14 @@ build_flags =
'-DTRIGGER_GPIO=39' '-DTRIGGER_GPIO=39'
'-DSLEEP_BUTTON=39' '-DSLEEP_BUTTON=39'
'-DIR_EMITTER_GPIO=12' '-DIR_EMITTER_GPIO=12'
'-DANEOPIX_IND_DATA_GPIO=27' '-DLED_ADDRESSABLE_PIN1=27'
'-DANEOPIX_IND_NUM_LEDS=25' '-DLED_ADDRESSABLE_NUM=25'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DLED_ERROR=4'
'-DLED_PROCESSING=3'
'-DLED_BROKER=2'
'-DLED_NETWORK=1'
'-DLED_POWER=0'
'-DGateway_Name="OMG_ATOM_M"' '-DGateway_Name="OMG_ATOM_M"'
board_upload.speed = 1500000 board_upload.speed = 1500000
custom_description = Compact enclosure ESP32 with BLE gateway custom_description = Compact enclosure ESP32 with BLE gateway
@@ -713,9 +717,9 @@ build_flags =
'-DTRIGGER_GPIO=39' '-DTRIGGER_GPIO=39'
'-DSLEEP_BUTTON=39' '-DSLEEP_BUTTON=39'
'-DIR_EMITTER_GPIO=12' '-DIR_EMITTER_GPIO=12'
'-DANEOPIX_IND_DATA_GPIO=27' '-DLED_ADDRESSABLE_PIN1=27'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DGateway_Name="OMG_ATOM_L"' '-DGateway_Name="OMG_ATOM_L"'
board_upload.speed = 1500000 board_upload.speed = 1500000
custom_description = Compact enclosure ESP32 with BLE gateway custom_description = Compact enclosure ESP32 with BLE gateway
@@ -1145,11 +1149,11 @@ build_flags =
'-DZgatewayLORA="LORA"' '-DZgatewayLORA="LORA"'
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DGateway_Name="OMG_ESP32_BLE_LORA"' '-DGateway_Name="OMG_ESP32_BLE_LORA"'
'-DLED_SEND_RECEIVE=21' # T-BEAM board V0.5 '-DLED_PIN=21' # T-BEAM board V0.5
# '-DLED_SEND_RECEIVE=14' # T-BEAM board V0.7 # '-DLED_PIN=14' # T-BEAM board V0.7
# '-DLED_SEND_RECEIVE=4' # T-BEAM board V1.0+ # '-DLED_PIN=4' # T-BEAM board V1.0+
'-DTimeLedON=0.05' '-DTimeLedON=0.05'
'-DLED_SEND_RECEIVE_ON=1' # Set 0 for board V1.0+ '-DLED_PIN_ON=1' # Set 0 for board V1.0+
# for V0.5 and V0.7 ONLY (V1.0+ as onboard AXP202 dedicated chip, need driver) # for V0.5 and V0.7 ONLY (V1.0+ as onboard AXP202 dedicated chip, need driver)
# it's a 100K/100K divider (so 2 divider) and connected to GPIO35 # it's a 100K/100K divider (so 2 divider) and connected to GPIO35
'-DZsensorADC="ADC"' '-DZsensorADC="ADC"'
@@ -1173,9 +1177,9 @@ build_flags =
'-DZgatewayLORA="LORA"' '-DZgatewayLORA="LORA"'
'-DLORA_BAND=868E6' '-DLORA_BAND=868E6'
'-DGateway_Name="OMG_ESP32_LORA"' '-DGateway_Name="OMG_ESP32_LORA"'
'-DLED_SEND_RECEIVE=25' '-DLED_PIN=25'
'-DTimeLedON=0.1' '-DTimeLedON=0.1'
'-DLED_SEND_RECEIVE_ON=1' '-DLED_PIN_ON=1'
; *** ssd1306 Display Options *** ; *** ssd1306 Display Options ***
'-DZdisplaySSD1306="HELTEC_SSD1306"' '-DZdisplaySSD1306="HELTEC_SSD1306"'
; '-DLOG_TO_OLED=true' ; Enable log to OLED ; '-DLOG_TO_OLED=true' ; Enable log to OLED
@@ -1352,7 +1356,7 @@ build_flags =
${com-esp.build_flags} ${com-esp.build_flags}
'-DZgatewayIR="IR"' '-DZgatewayIR="IR"'
'-DTRIGGER_GPIO=13' '-DTRIGGER_GPIO=13'
'-DLED_SEND_RECEIVE=4' '-DLED_PIN=4'
'-DIR_EMITTER_GPIO=14' '-DIR_EMITTER_GPIO=14'
'-DIR_RECEIVER_GPIO=5' '-DIR_RECEIVER_GPIO=5'
'-UMQTTsetMQTT' ;We remove this function to have sufficient FLASH available for OTA, you should also use ESPWifiManualSetup and 'board_build.ldscript = eagle.flash.1m64.ld' to save flash memory and have OTA working '-UMQTTsetMQTT' ;We remove this function to have sufficient FLASH available for OTA, you should also use ESPWifiManualSetup and 'board_build.ldscript = eagle.flash.1m64.ld' to save flash memory and have OTA working
@@ -1565,8 +1569,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DTimeBtwRead=0' '-DTimeBtwRead=0'
'-DScan_duration=3000' '-DScan_duration=3000'
'-DAttemptBLEConnect=false' '-DAttemptBLEConnect=false'
@@ -1585,9 +1589,9 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DANEOPIX_IND_DATA_GPIO=48' '-DLED_ADDRESSABLE_PIN1=48'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
custom_description = BLE gateway on the S3 custom_description = BLE gateway on the S3
@@ -1605,9 +1609,9 @@ build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DZgatewayIR="IR"' '-DZgatewayIR="IR"'
'-DANEOPIX_IND_DATA_GPIO=35' '-DLED_ADDRESSABLE_PIN1=35'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DTRIGGER_GPIO=41' '-DTRIGGER_GPIO=41'
'-DIR_EMITTER_GPIO=12' '-DIR_EMITTER_GPIO=12'
'-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3
@@ -1628,9 +1632,9 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DANEOPIX_IND_DATA_GPIO=8' '-DLED_ADDRESSABLE_PIN1=8'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
custom_description = BLE gateway on the C3 custom_description = BLE gateway on the C3
@@ -1647,7 +1651,7 @@ build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_INFO=19' '-DLED_INFO=19'
'-DLED_SEND_RECEIVE=20' '-DLED_PIN=20'
'-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3
'-DGateway_Name="OMG_AirM2M_Core_ESP32C3"' '-DGateway_Name="OMG_AirM2M_Core_ESP32C3"'
custom_description = BLE gateway on the C3 custom_description = BLE gateway on the C3
@@ -1666,11 +1670,11 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DANEOPIX_IND_DATA_GPIO=8' '-DLED_ADDRESSABLE_PIN1=8'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
; '-DANEOPIX_BRIGHTNESS=10' ; 0 - 255, default 20 ; '-DDEFAULT_ADJ_BRIGHTNESS=10' ; 0 - 255, default 20
'-DANEOPIX_COLOR_SCHEME=2' ; blue based signalling colors '-DANEOPIX_COLOR_SCHEME=2' ; blue based signalling colors
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DNO_INT_TEMP_READING=true' ; No internal temperature reading on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; No internal temperature reading on ESP32 C3 or S3
'-DTRIGGER_GPIO=7' '-DTRIGGER_GPIO=7'
'-DGateway_Name="OpenMQTTGateway_ESP32C3_DKC02"' '-DGateway_Name="OpenMQTTGateway_ESP32C3_DKC02"'
@@ -1698,11 +1702,11 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DANEOPIX_IND_DATA_GPIO=7' '-DLED_ADDRESSABLE_PIN1=7'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
; '-DANEOPIX_BRIGHTNESS=10' ; 0 - 255, default 20 ; '-DDEFAULT_ADJ_BRIGHTNESS=10' ; 0 - 255, default 20
'-DANEOPIX_COLOR_SCHEME=1' ; Alternative LED colour scheme: 2 = blue/gold. 1 = green/gold '-DANEOPIX_COLOR_SCHEME=1' ; Alternative LED colour scheme: 2 = blue/gold. 1 = green/gold
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
; The momentary switch on the board is connected to GPIO9 ; The momentary switch on the board is connected to GPIO9
'-DTRIGGER_GPIO=9' '-DTRIGGER_GPIO=9'
'-DNO_INT_TEMP_READING=true' ; No internal temperature on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; No internal temperature on ESP32 C3 or S3
@@ -1738,9 +1742,9 @@ build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DTRIGGER_GPIO=3' '-DTRIGGER_GPIO=3'
'-DANEOPIX_IND_DATA_GPIO=2' '-DLED_ADDRESSABLE_PIN1=2'
'-DANEOPIX_IND_NUM_LEDS=1' '-DLED_ADDRESSABLE_NUM=1'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
'-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3 '-DNO_INT_TEMP_READING=true' ; Internal temperature reading not building on ESP32 C3 or S3
'-DUSE_MAC_AS_GATEWAY_NAME' '-DUSE_MAC_AS_GATEWAY_NAME'
custom_description = BLE gateway on ESP32C3 custom_description = BLE gateway on ESP32C3
@@ -1759,8 +1763,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_THINGPULSE_ETH_BLE"' '-DGateway_Name="OMG_THINGPULSE_ETH_BLE"'
'-DESP32_ETHERNET=true' '-DESP32_ETHERNET=true'
'-DETH_PHY_TYPE=ETH_PHY_LAN8720' '-DETH_PHY_TYPE=ETH_PHY_LAN8720'
@@ -1769,13 +1773,13 @@ build_flags =
'-DETH_PHY_MDC=23' '-DETH_PHY_MDC=23'
'-DETH_PHY_MDIO=18' '-DETH_PHY_MDIO=18'
'-DETH_CLK_MODE=ETH_CLOCK_GPIO16_OUT' '-DETH_CLK_MODE=ETH_CLOCK_GPIO16_OUT'
'-DANEOPIX_IND_DATA_GPIO=32' '-DLED_ADDRESSABLE_PIN1=32'
'-DANEOPIX_IND_NUM_LEDS=4' '-DLED_ADDRESSABLE_NUM=4'
'-DANEOPIX_INFO_LED=0' '-DLED_BROKER=0'
'-DANEOPIX_SEND_RECEIVE_LED=1' '-DLED_PROCESSING=1'
'-DANEOPIX_ERROR_LED=2' '-DLED_ERROR=2'
'-DANEOPIX_BRIGHTNESS=255' '-DDEFAULT_ADJ_BRIGHTNESS=255'
'-DRGB_INDICATORS=true' '-DLED_ADDRESSABLE=true'
; '-DsimplePublishing=true' ; '-DsimplePublishing=true'
custom_description = BLE Gateway using ethernet or wifi with external antenna custom_description = BLE Gateway using ethernet or wifi with external antenna
custom_hardware = ThingPulse gateway single ESP32 custom_hardware = ThingPulse gateway single ESP32
@@ -1793,8 +1797,8 @@ lib_deps =
build_flags = build_flags =
${com-esp32.build_flags} ${com-esp32.build_flags}
'-DZgatewayBT="BT"' '-DZgatewayBT="BT"'
'-DLED_SEND_RECEIVE=2' '-DLED_PIN=2'
'-DLED_SEND_RECEIVE_ON=0' '-DLED_PIN_ON=0'
'-DGateway_Name="OMG_ESP32_BLE"' '-DGateway_Name="OMG_ESP32_BLE"'
'-DUSE_BLUFI=1' '-DUSE_BLUFI=1'
'-DARDUINO_LOOP_STACK_SIZE=17500' '-DARDUINO_LOOP_STACK_SIZE=17500'
+243
View File
@@ -0,0 +1,243 @@
/*
Theengs LEDManager - We Unite Sensors in One Open-Source Interface
Copyright: (c)Florian ROBERT
This file is part of LEDManager library.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "LEDManager.h"
LEDManager::LEDManager() : globalBrightness(255) {}
void LEDManager::addLEDStrip(int pin, int numLeds) {
LEDStrip ledStrip;
ledStrip.pin = pin;
#ifdef LED_ADDRESSABLE
ledStrip.strip = new Adafruit_NeoPixel(numLeds, pin, NEO_GRB + NEO_KHZ800);
ledStrip.strip->begin();
ledStrip.strip->show();
ledStrip.strip->setBrightness(globalBrightness);
#else
pinMode(pin, OUTPUT);
#endif
ledStrip.ledStates.resize(numLeds, {OFF, OFF, 0, 0, 0, 0, 0, false, 255, FADE_AMOUNT, {OFF, 0, -1, false}});
ledStrips.push_back(ledStrip);
}
void LEDManager::setMode(int stripIndex, int ledIndex, Mode mode, uint32_t color, int durationOrBlinkCount) {
if (stripIndex >= 0 && stripIndex < ledStrips.size()) {
if (ledIndex == -1) {
for (int i = 0; i < ledStrips[stripIndex].ledStates.size(); i++) {
setModeForSingleLED(stripIndex, i, mode, color, durationOrBlinkCount);
}
} else if (ledIndex >= 0 && ledIndex < ledStrips[stripIndex].ledStates.size()) {
setModeForSingleLED(stripIndex, ledIndex, mode, color, durationOrBlinkCount);
}
}
}
void LEDManager::setModeForSingleLED(int stripIndex, int ledIndex, Mode mode, uint32_t color, int durationOrBlinkCount) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
if ((state.mode == BLINK || state.mode == PULSE) && state.durationOrBlinkCount > 0) {
state.queuedState = {mode, color, durationOrBlinkCount, true};
return;
}
if (mode != BLINK && mode != PULSE) {
state.previousMode = state.mode;
state.previousColor = state.color;
}
state.mode = mode;
state.color = color;
state.durationOrBlinkCount = durationOrBlinkCount;
state.lastUpdateTime = millis();
state.blinkCounter = 0;
state.isBlinkOn = false;
state.brightness = globalBrightness;
state.fadeAmount = FADE_AMOUNT;
state.queuedState.isQueued = false;
}
void LEDManager::setBrightness(uint8_t brightness) {
#ifdef LED_ADDRESSABLE
globalBrightness = brightness;
for (auto& ledStrip : ledStrips) {
ledStrip.strip->setBrightness(brightness);
for (auto& state : ledStrip.ledStates) {
state.brightness = brightness;
}
}
#endif
}
void LEDManager::setLEDColor(int stripIndex, int ledIndex, uint32_t color) {
if (stripIndex < 0 || stripIndex >= ledStrips.size()) return;
if (ledIndex < 0 || ledIndex >= ledStrips[stripIndex].ledStates.size()) return;
uint8_t r, g, b;
extractRGB(color, r, g, b);
r = (r * globalBrightness) / 255;
g = (g * globalBrightness) / 255;
b = (b * globalBrightness) / 255;
#ifdef LED_ADDRESSABLE
ledStrips[stripIndex].strip->setPixelColor(ledIndex, r, g, b);
ledStrips[stripIndex].strip->show();
#else
// For non-addressable LEDs, we'll use the first LED of each strip
if (ledIndex == 0) {
int pin = ledStrips[stripIndex].pin;
analogWrite(pin, (r + g + b) / 3); // Average of RGB for single-color LED
}
#endif
}
void LEDManager::update() {
for (int stripIndex = 0; stripIndex < ledStrips.size(); stripIndex++) {
for (int ledIndex = 0; ledIndex < ledStrips[stripIndex].ledStates.size(); ledIndex++) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
switch (state.mode) {
case BLINK:
handleBlink(stripIndex, ledIndex);
break;
case PULSE:
handlePulse(stripIndex, ledIndex);
break;
case STATIC:
handleStatic(stripIndex, ledIndex);
break;
case OFF:
setLEDColor(stripIndex, ledIndex, 0);
break;
}
}
#ifdef LED_ADDRESSABLE
ledStrips[stripIndex].strip->show();
#endif
}
}
void LEDManager::handleBlink(int stripIndex, int ledIndex) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
unsigned long currentTime = millis();
if (currentTime - state.lastUpdateTime >= BLINK_INTERVAL) {
state.lastUpdateTime = currentTime;
if (state.durationOrBlinkCount > 0) {
if (state.blinkCounter == 0) {
state.blinkCounter = state.durationOrBlinkCount * 2;
} else {
state.blinkCounter--;
if (state.blinkCounter == 0) {
if (state.queuedState.isQueued) {
applyQueuedState(stripIndex, ledIndex);
} else {
returnToPreviousState(stripIndex, ledIndex);
}
return;
}
}
}
state.isBlinkOn = !state.isBlinkOn;
if (state.isBlinkOn) {
setLEDColor(stripIndex, ledIndex, state.color);
} else {
setLEDColor(stripIndex, ledIndex, 0);
}
}
}
void LEDManager::handlePulse(int stripIndex, int ledIndex) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
unsigned long currentTime = millis();
if (currentTime - state.lastUpdateTime >= PULSE_INTERVAL) {
state.lastUpdateTime = currentTime;
state.brightness += state.fadeAmount;
if (state.brightness <= 0 || state.brightness >= 255) {
state.fadeAmount = -state.fadeAmount;
state.brightness = constrain(state.brightness, 0, 255);
if (state.durationOrBlinkCount > 0) {
state.durationOrBlinkCount--;
if (state.durationOrBlinkCount == 0) {
if (state.queuedState.isQueued) {
applyQueuedState(stripIndex, ledIndex);
} else {
returnToPreviousState(stripIndex, ledIndex);
}
return;
}
}
}
uint32_t adjustedColor = (state.color & 0xFF000000) |
(((state.color & 0x00FF0000) * state.brightness / 255) & 0x00FF0000) |
(((state.color & 0x0000FF00) * state.brightness / 255) & 0x0000FF00) |
(((state.color & 0x000000FF) * state.brightness / 255) & 0x000000FF);
setLEDColor(stripIndex, ledIndex, adjustedColor);
}
}
void LEDManager::handleStatic(int stripIndex, int ledIndex) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
unsigned long currentTime = millis();
if (state.durationOrBlinkCount > 0) {
if (currentTime - state.lastUpdateTime >= static_cast<unsigned long>(state.durationOrBlinkCount) * 1000) {
if (state.queuedState.isQueued) {
applyQueuedState(stripIndex, ledIndex);
} else {
returnToPreviousState(stripIndex, ledIndex);
}
return;
}
}
setLEDColor(stripIndex, ledIndex, state.color);
}
void LEDManager::returnToPreviousState(int stripIndex, int ledIndex) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
state.mode = state.previousMode;
state.color = state.previousColor;
state.durationOrBlinkCount = -1; // Set to infinite for the previous state
state.lastUpdateTime = millis();
state.blinkCounter = 0;
state.isBlinkOn = false;
state.brightness = globalBrightness;
state.fadeAmount = FADE_AMOUNT;
}
void LEDManager::applyQueuedState(int stripIndex, int ledIndex) {
auto& state = ledStrips[stripIndex].ledStates[ledIndex];
state.mode = state.queuedState.mode;
state.color = state.queuedState.color;
state.durationOrBlinkCount = state.queuedState.durationOrBlinkCount;
state.lastUpdateTime = millis();
state.blinkCounter = 0;
state.isBlinkOn = false;
state.brightness = globalBrightness;
state.fadeAmount = FADE_AMOUNT;
state.queuedState.isQueued = false;
}
void LEDManager::extractRGB(uint32_t color, uint8_t& r, uint8_t& g, uint8_t& b) {
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = color & 0xFF;
}
+107
View File
@@ -0,0 +1,107 @@
/*
Theengs LEDManager - We Unite Sensors in One Open-Source Interface
Copyright: (c)Florian ROBERT
This file is part of LEDManager library.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef LED_MANAGER_H
#define LED_MANAGER_H
#include <Arduino.h>
#include <vector>
#ifdef LED_ADDRESSABLE
# include <Adafruit_NeoPixel.h>
#endif
#ifndef BLINK_INTERVAL
# define BLINK_INTERVAL 500
#endif
#ifndef PULSE_INTERVAL
# define PULSE_INTERVAL 30
#endif
#ifndef FADE_AMOUNT
# define FADE_AMOUNT 5
#endif
// Define the pins for the RGB LED power if needed
#ifndef LED_ADDRESSABLE_POWER
# define LED_ADDRESSABLE_POWER -1
#endif
class LEDManager {
public:
enum Mode { OFF,
STATIC,
BLINK,
PULSE };
LEDManager();
void init();
void addLEDStrip(int pin, int numLeds);
void setMode(int stripIndex, int ledIndex, Mode mode, uint32_t color, int durationOrBlinkCount = -1);
void update();
void setBrightness(uint8_t brightness);
private:
struct QueuedState {
Mode mode;
uint32_t color;
int durationOrBlinkCount;
bool isQueued;
};
struct LEDState {
Mode mode;
Mode previousMode;
uint32_t color;
uint32_t previousColor;
int durationOrBlinkCount;
unsigned long lastUpdateTime;
int blinkCounter;
bool isBlinkOn;
int brightness;
int fadeAmount;
QueuedState queuedState;
};
struct LEDStrip {
#ifdef LED_ADDRESSABLE
Adafruit_NeoPixel* strip;
#endif
int pin;
std::vector<LEDState> ledStates;
};
std::vector<LEDStrip> ledStrips;
int globalBrightness;
void setModeForSingleLED(int stripIndex, int ledIndex, Mode mode, uint32_t color, int durationOrBlinkCount);
void setLEDColor(int stripIndex, int ledIndex, uint32_t color);
void handleBlink(int stripIndex, int ledIndex);
void handlePulse(int stripIndex, int ledIndex);
void handleStatic(int stripIndex, int ledIndex);
void returnToPreviousState(int stripIndex, int ledIndex);
void applyQueuedState(int stripIndex, int ledIndex);
void extractRGB(uint32_t color, uint8_t& r, uint8_t& g, uint8_t& b);
};
#endif // LED_MANAGER_H
+132
View File
@@ -0,0 +1,132 @@
# LEDManager Library
## Overview
The LEDManager library provides a flexible and easy-to-use interface for controlling LEDs in projects. It supports both addressable LED strips and individual non-addressable LEDs, offering various modes of operation such as static, blinking, and pulsing. The library is designed to work seamlessly with PlatformIO and can be easily configured using build flags.
## Features
- Support for both addressable LED strips and individual non-addressable LEDs
- Multiple operation modes: OFF, STATIC, BLINK, and PULSE
- Individual control of LEDs within each strip (for addressable LEDs)
- Global brightness control
- Queueing of LED states for complex sequences
- Automatic return to previous state after temporary modes
- Compatible with PlatformIO build flags for easy configuration
- Customizable color schemes
## Installation
1. Clone this repository or download the ZIP file.
2. Extract the contents to your PlatformIO project's `lib` directory.
## Configuration
Configure the LEDManager library using build flags in your `platformio.ini` file:
```ini
build_flags =
; For addressable LEDs:
-DLED_ADDRESSABLE=true
; For non-addressable LEDs, comment out the line above
; Optional timing configurations:
-DBLINK_INTERVAL=500
-DPULSE_INTERVAL=30
-DFADE_AMOUNT=5
```
## Usage
Here's a basic example of how to use the LEDManager library:
```cpp
#include "LEDManager.h"
LEDManager ledManager;
void setup() {
#ifdef LED_ADDRESSABLE
ledManager.addLEDStrip(5, 30); // Add addressable LED strip on pin 5 with 30 LEDs
#else
ledManager.addLEDStrip(5, 1); // Add non-addressable LED on pin 5
ledManager.addLEDStrip(6, 1); // Add non-addressable LED on pin 6
#endif
ledManager.setBrightness(128); // Set global brightness to 50%
}
void loop() {
#ifdef LED_ADDRESSABLE
// Set all LEDs on the strip to static green
ledManager.setMode(0, -1, LEDManager::STATIC, LED_COLOR_GREEN);
// Blink first 5 LEDs red for 3 times
for (int i = 0; i < 5; i++) {
ledManager.setMode(0, i, LEDManager::BLINK, LED_COLOR_RED, 3);
}
#else
// Set first LED to static green
ledManager.setMode(0, 0, LEDManager::STATIC, LED_COLOR_GREEN);
// Blink second LED red
ledManager.setMode(1, 0, LEDManager::BLINK, LED_COLOR_RED, 3);
#endif
ledManager.update();
delay(100);
}
```
## API Reference
### Initialization and Setup
```cpp
LEDManager ledManager;
ledManager.addLEDStrip(int pin, int numLeds);
```
### Setting LED Mode
```cpp
ledManager.setMode(int stripIndex, int ledIndex, Mode mode, uint32_t color, int durationOrBlinkCount = -1);
```
- `stripIndex`: Index of the LED strip (0-based)
- `ledIndex`: LED index within the strip (0-based) or -1 for all LEDs in the strip (addressable LEDs only)
- `mode`: `LEDManager::OFF`, `LEDManager::STATIC`, `LEDManager::BLINK`, or `LEDManager::PULSE`
- `color`: Color value (use predefined colors from LEDColorDefinitions.h or custom 24-bit RGB values)
- `durationOrBlinkCount`: Duration for STATIC mode (in milliseconds), blink/pulse count for BLINK/PULSE modes (-1 for infinite)
### Setting Brightness
```cpp
ledManager.setBrightness(brightness);
```
- `brightness`: Global brightness value (0-255)
### Updating LEDs
Call this method in your main loop to update LED states:
```cpp
ledManager.update();
```
## Advanced Configuration
You can customize the behavior of the LEDManager by defining the following build flags:
- `BLINK_INTERVAL`: Sets the interval (in milliseconds) between blink states (default: 500)
- `PULSE_INTERVAL`: Sets the interval (in milliseconds) between pulse updates (default: 30)
- `FADE_AMOUNT`: Sets the increment/decrement value for pulsing (default: 5)
## Contributing
Contributions to the LEDManager library are welcome! Please feel free to submit a Pull Request.
## License
This library is released under the LGPL V3 License.
+75 -251
View File
@@ -434,260 +434,84 @@ ss_cnt_parameters cnt_parameters_array[cnt_parameters_array_size] = {
# define ota_timeout_millis 30000 # define ota_timeout_millis 30000
#endif #endif
/*-------------ERRORS, INFOS, SEND RECEIVE Display through LED----------------*/ // LED index depending on state, each state can have a different LED index or be grouped if there is a limited number of LEDs
#ifndef RGB_INDICATORS // Management of Errors, reception/emission and informations indicators with basic LED #ifndef LED_ERROR
/*-------------DEFINE PINs FOR STATUS LEDs----------------*/ # define LED_ERROR 0
# ifndef LED_SEND_RECEIVE #endif
# ifdef ESP8266 #ifndef LED_PROCESSING
//# define LED_SEND_RECEIVE 40 # define LED_PROCESSING 0
# elif ESP32 #endif
//# define LED_SEND_RECEIVE 40 #ifndef LED_BROKER
# endif # define LED_BROKER 0
# endif #endif
# ifndef LED_SEND_RECEIVE_ON #ifndef LED_NETWORK
# define LED_SEND_RECEIVE_ON HIGH # define LED_NETWORK 0
# endif #endif
# ifndef LED_ERROR #ifndef LED_POWER
# ifdef ESP8266 # define LED_POWER -1
//# define LED_ERROR 42 #endif
# elif ESP32
//# define LED_ERROR 42
# endif
# endif
# ifndef LED_ERROR_ON
# define LED_ERROR_ON HIGH
# endif
# ifndef RGB_LED_ON_ON
# define RGB_LED_ON_ON HIGH
# endif
# ifndef LED_INFO
# ifdef ESP8266
//# define LED_INFO 44
# elif ESP32
//# define LED_INFO 44
# endif
# endif
# ifndef LED_INFO_ON
# define LED_INFO_ON HIGH
# endif
# ifdef RGB_LED_ON
# define SetupIndicatorError() \
pinMode(RGB_LED_ON, OUTPUT);
# define ONIndicatorON() digitalWrite(RGB_LED_ON, RGB_LED_ON_ON)
# else
# define ONIndicatorON()
# endif
# ifdef LED_ERROR
# define SetupIndicatorError() \
pinMode(LED_ERROR, OUTPUT); \
ErrorIndicatorOFF();
# define ErrorIndicatorON() digitalWrite(LED_ERROR, LED_ERROR_ON)
# define ErrorIndicatorOFF() digitalWrite(LED_ERROR, !LED_ERROR_ON)
# else
# define SetupIndicatorError()
# define ErrorIndicatorON()
# define ErrorIndicatorOFF()
# endif
# ifdef LED_SEND_RECEIVE
# define SetupIndicatorSendReceive() \
pinMode(LED_SEND_RECEIVE, OUTPUT); \
SendReceiveIndicatorOFF();
# define SendReceiveIndicatorON() digitalWrite(LED_SEND_RECEIVE, LED_SEND_RECEIVE_ON)
# define SendReceiveIndicatorOFF() digitalWrite(LED_SEND_RECEIVE, !LED_SEND_RECEIVE_ON)
# else
# define SetupIndicatorSendReceive()
# define SendReceiveIndicatorON()
# define SendReceiveIndicatorOFF()
# endif
# ifdef LED_INFO
# define SetupIndicatorInfo() \
pinMode(LED_INFO, OUTPUT); \
InfoIndicatorOFF();
# define InfoIndicatorON() digitalWrite(LED_INFO, LED_INFO_ON)
# define InfoIndicatorOFF() digitalWrite(LED_INFO, !LED_INFO_ON)
# else
# define SetupIndicatorInfo()
# define InfoIndicatorON()
# define InfoIndicatorOFF()
# endif
# define CriticalIndicatorON() // Not used
# define PowerIndicatorON() // Not used
# define PowerIndicatorOFF() // Not used
# define SetupIndicators() // Not used
#else // Management of Errors, reception/emission and informations indicators with RGB LED
# include <Adafruit_NeoPixel.h>
# ifndef ANEOPIX_IND_TYPE // needs library constants
# define ANEOPIX_IND_TYPE NEO_GRB + NEO_KHZ800 // ws2812 and alike
# endif
Adafruit_NeoPixel leds(ANEOPIX_IND_NUM_LEDS, ANEOPIX_IND_DATA_GPIO, ANEOPIX_IND_TYPE);
# ifdef ANEOPIX_IND_DATA_GPIO2 // Only used for Critical Indicator
// assume the same LED type
Adafruit_NeoPixel leds2(ANEOPIX_IND_NUM_LEDS, ANEOPIX_IND_DATA_GPIO2, ANEOPIX_IND_TYPE);
# endif
# ifdef ANEOPIX_IND_DATA_GPIO3
// assume the same LED type
Adafruit_NeoPixel leds3(ANEOPIX_IND_NUM_LEDS, ANEOPIX_IND_DATA_GPIO3, ANEOPIX_IND_TYPE);
# endif
# ifndef RGB_LED_POWER // Single standard LED pin
# define RGB_LED_POWER -1 // If the RGB Led is linked to GPIO pin for power define it here #ifndef LED_PIN
# ifdef LED_BUILTIN
# define LED_PIN LED_BUILTIN
# endif # endif
# ifndef ANEOPIX_BRIGHTNESS #endif
# define ANEOPIX_BRIGHTNESS 20 // Set Default maximum RGB brightness to approx 10% (0-255 scale) #ifndef LED_PIN_ON
# define LED_PIN_ON HIGH
#endif
#ifndef LED_ACTUATOR_ONOFF
# ifdef LED_BUILTIN
# define LED_ACTUATOR_ONOFF LED_BUILTIN
# endif # endif
# ifndef DEFAULT_ADJ_BRIGHTNESS #endif
# define DEFAULT_ADJ_BRIGHTNESS 255 // Set Default RGB adjustable brightness
# endif
# ifndef ANEOPIX_COLOR_SCHEME // allow for different color combinations
# define ANEOPIX_COLOR_SCHEME 0
# endif
// Allow to set LED used (for example thingpulse gateway has 4 we use them independently)
# ifndef ANEOPIX_ON_LED
# define ANEOPIX_ON_LED 0 // First Led
# endif
# ifndef ANEOPIX_INFO_LED
# define ANEOPIX_INFO_LED 0 // First Led
# endif
# ifndef ANEOPIX_SEND_RECEIVE_LED
# define ANEOPIX_SEND_RECEIVE_LED 0 // First Led
# endif
# ifndef ANEOPIX_ERROR_LED
# define ANEOPIX_ERROR_LED 0 // First Led
# endif
# ifndef ANEOPIX_CRITICAL_LED
# define ANEOPIX_CRITICAL_LED 0 // First Led
# endif
// compile time calculation of color values
# define ANEOPIX_RED ((0xFF * ANEOPIX_BRIGHTNESS) >> 8) << 16
# define ANEOPIX_RED_DIM ((0x3F * ANEOPIX_BRIGHTNESS) >> 8) << 16 // dimmed /4
# define ANEOPIX_ORANGE (((0xFF * ANEOPIX_BRIGHTNESS) >> 8) << 16) | \
(((0xA5 * ANEOPIX_BRIGHTNESS) >> 8) << 8)
# define ANEOPIX_GOLD (((0xFF * ANEOPIX_BRIGHTNESS) >> 8) << 16) | \
(((0xD7 * ANEOPIX_BRIGHTNESS) >> 8) << 8)
# define ANEOPIX_GREEN ((0xFF * ANEOPIX_BRIGHTNESS) >> 8) << 8
# define ANEOPIX_GREEN_DIM ((0x3F * ANEOPIX_BRIGHTNESS) >> 8) << 8 // dimmed /4
# define ANEOPIX_AQUA (((0xFF * ANEOPIX_BRIGHTNESS) >> 8) << 8) | \
(0xFF * ANEOPIX_BRIGHTNESS) >> 8
# define ANEOPIX_BLUE (0xFF * ANEOPIX_BRIGHTNESS) >> 8
# define ANEOPIX_BLUE_DIM (0x3F * ANEOPIX_BRIGHTNESS) >> 8 // dimmed /4
# define ANEOPIX_BLACK 0
# if ANEOPIX_COLOR_SCHEME == 0 // TODO adapt to other boards
// original color combination remains default #ifndef DEFAULT_ADJ_BRIGHTNESS
# define ANEOPIX_INFO ANEOPIX_GREEN # define DEFAULT_ADJ_BRIGHTNESS 255 // Set Default RGB adjustable brightness
# define ANEOPIX_ERROR ANEOPIX_ORANGE #endif
# define ANEOPIX_SENDRECEIVE ANEOPIX_BLUE
# define ANEOPIX_CRITICAL ANEOPIX_RED // second led #ifndef LED_POWER_COLOR
# define ANEOPIX_POWER ANEOPIX_GREEN // second led # define LED_POWER_COLOR 0x00FF00 // Green
# define ANEOPIX_BOOT ANEOPIX_BLACK // unused #endif
# define ANEOPIX_OFF ANEOPIX_BLACK #ifndef LED_PROCESSING_COLOR
// color combinations tested for good visibility of onboard leds # define LED_PROCESSING_COLOR 0x0000FF // Blue
# elif ANEOPIX_COLOR_SCHEME == 1 #endif
# define ANEOPIX_INFO ANEOPIX_GREEN_DIM // dimmed green info background #ifndef LED_WAITING_ONBOARD_COLOR
# define ANEOPIX_ERROR ANEOPIX_RED_DIM # define LED_WAITING_ONBOARD_COLOR 0xFFA500 // Orange
# define ANEOPIX_SENDRECEIVE ANEOPIX_GOLD // bright gold = sending #endif
# define ANEOPIX_CRITICAL ANEOPIX_BLACK // unused #ifndef LED_ONBOARD_COLOR
# define ANEOPIX_POWER ANEOPIX_BLACK // unused # define LED_ONBOARD_COLOR 0xFFFF00 // Yellow
# define ANEOPIX_BOOT ANEOPIX_AQUA #endif
# define ANEOPIX_OFF ANEOPIX_BLACK #ifndef LED_NETWORK_OK_COLOR
# else # define LED_NETWORK_OK_COLOR 0x00FF00 // Green
# define ANEOPIX_INFO ANEOPIX_BLUE_DIM // dimmed blue info background #endif
# define ANEOPIX_ERROR ANEOPIX_RED_DIM #ifndef LED_NETWORK_ERROR_COLOR
# define ANEOPIX_SENDRECEIVE ANEOPIX_GOLD // bright gold = sending # define LED_NETWORK_ERROR_COLOR 0xFFA500 // Orange
# define ANEOPIX_CRITICAL ANEOPIX_BLACK // unused #endif
# define ANEOPIX_POWER ANEOPIX_BLACK // unused #ifndef LED_BROKER_OK_COLOR
# define ANEOPIX_BOOT ANEOPIX_AQUA # define LED_BROKER_OK_COLOR 0x00FF00 // Green
# define ANEOPIX_OFF ANEOPIX_BLACK #endif
# endif #ifndef LED_BROKER_ERROR_COLOR
# if !defined(ANEOPIX_IND_DATA_GPIO2) && !defined(ANEOPIX_IND_DATA_GPIO3) # define LED_BROKER_ERROR_COLOR 0xFFA500 // Orange
// during boot the RGB LED is on to signal also reboots #endif
# define SetupIndicators() \ #ifndef LED_OFFLINE_COLOR
if (RGB_LED_POWER > -1) { \ # define LED_OFFLINE_COLOR 0x0000FF // Blue
pinMode(RGB_LED_POWER, OUTPUT); \ #endif
digitalWrite(RGB_LED_POWER, HIGH); \ #ifndef LED_OTA_LOCAL_COLOR
} \ # define LED_OTA_LOCAL_COLOR 0xFF00FF // Magenta
leds.begin(); \ #endif
leds.setPixelColor(ANEOPIX_INFO_LED, ANEOPIX_BOOT); \ #ifndef LED_OTA_REMOTE_COLOR
leds.show(); # define LED_OTA_REMOTE_COLOR 0x8000FF // Purple
# elif defined(ANEOPIX_IND_DATA_GPIO2) && !defined(ANEOPIX_IND_DATA_GPIO3) #endif
# define SetupIndicators() \ #ifndef LED_ERROR_COLOR
if (RGB_LED_POWER > -1) { \ # define LED_ERROR_COLOR 0xFF0000 // Red
pinMode(RGB_LED_POWER, OUTPUT); \ #endif
digitalWrite(RGB_LED_POWER, HIGH); \ #ifndef LED_ACTUATOR_ONOFF_COLOR
} \ # define LED_ACTUATOR_ONOFF_COLOR 0x00FF00 // Green
leds.begin(); \ #endif
leds2.begin(); #ifndef LED_COLOR_BLACK
# else # define LED_COLOR_BLACK 0x000000
# define SetupIndicators() \
if (RGB_LED_POWER > -1) { \
pinMode(RGB_LED_POWER, OUTPUT); \
digitalWrite(RGB_LED_POWER, HIGH); \
} \
leds.begin(); \
leds2.begin(); \
leds3.begin();
# endif
# ifndef RGB_LED_ERROR
# define RGB_LED_ERROR leds
# endif
# ifndef RGB_LED_SR
# define RGB_LED_SR leds
# endif
# ifndef RGB_LED_INFO
# define RGB_LED_INFO leds
# endif
# ifndef RGB_LED_ON
# define RGB_LED_ON leds
# endif
# define ONIndicatorON() \
RGB_LED_ON.setPixelColor(ANEOPIX_ON_LED, ANEOPIX_POWER); \
RGB_LED_ON.setBrightness(SYSConfig.rgbbrightness); \
RGB_LED_ON.show();
# define ErrorIndicatorON() \
RGB_LED_ERROR.setPixelColor(ANEOPIX_ERROR_LED, ANEOPIX_ERROR); \
RGB_LED_ERROR.setBrightness(SYSConfig.rgbbrightness); \
RGB_LED_ERROR.show();
# define ErrorIndicatorOFF() \
RGB_LED_ERROR.setPixelColor(ANEOPIX_ERROR_LED, ANEOPIX_OFF); \
RGB_LED_ERROR.show();
# define SendReceiveIndicatorON() \
RGB_LED_SR.setPixelColor(ANEOPIX_SEND_RECEIVE_LED, ANEOPIX_SENDRECEIVE); \
RGB_LED_SR.setBrightness(SYSConfig.rgbbrightness); \
RGB_LED_SR.show();
# define SendReceiveIndicatorOFF() \
RGB_LED_SR.setPixelColor(ANEOPIX_SEND_RECEIVE_LED, ANEOPIX_OFF); \
RGB_LED_SR.show();
# define InfoIndicatorON() \
RGB_LED_INFO.setPixelColor(ANEOPIX_INFO_LED, ANEOPIX_INFO); \
RGB_LED_INFO.setBrightness(SYSConfig.rgbbrightness); \
RGB_LED_INFO.show();
# define InfoIndicatorOFF() \
RGB_LED_INFO.setPixelColor(ANEOPIX_INFO_LED, ANEOPIX_OFF); \
RGB_LED_INFO.show();
# ifdef ANEOPIX_IND_DATA_GPIO2 // Used for relay power indicator
// For the critical ON indicator there is no method to turn it off, the only way is to unplug the device
// This enable to have persistence of the indicator to inform the user
# ifndef LED_CRITICAL
# define LED_CRITICAL leds2
# endif
# ifndef LED_POWER
# define LED_POWER leds2
# endif
# define CriticalIndicatorON() \
LED_CRITICAL.setPixelColor(ANEOPIX_INFO_LED, ANEOPIX_CRITICAL); \
LED_CRITICAL.setBrightness(255); \
LED_CRITICAL.show();
# define PowerIndicatorON() \
LED_POWER.setPixelColor(ANEOPIX_INFO_LED, ANEOPIX_INFO); \
LED_POWER.setBrightness(SYSConfig.rgbbrightness); \
LED_POWER.show();
# define PowerIndicatorOFF() \
LED_POWER.setPixelColor(ANEOPIX_INFO_LED, ANEOPIX_OFF); \
LED_POWER.show();
# endif
# define SetupIndicatorInfo()
# define SetupIndicatorSendReceive()
# define SetupIndicatorError()
#endif #endif
#ifdef ESP8266 #ifdef ESP8266
@@ -827,7 +651,7 @@ struct SYSConfig_s {
bool offline; bool offline;
bool discovery; // HA discovery convention bool discovery; // HA discovery convention
bool ohdiscovery; // OH discovery specificities bool ohdiscovery; // OH discovery specificities
#ifdef RGB_INDICATORS #ifdef LED_ADDRESSABLE
int rgbbrightness; // brightness of the RGB LED int rgbbrightness; // brightness of the RGB LED
#endif #endif
enum PowerMode powerMode; enum PowerMode powerMode;
+22 -10
View File
@@ -100,11 +100,13 @@ void ONOFFConfig_load(){};
# endif # endif
void updatePowerIndicator() { void updatePowerIndicator() {
# ifdef LED_ACTUATOR_ONOFF
if (digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) { if (digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) {
PowerIndicatorON(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_ACTUATOR_ONOFF_COLOR);
} else { } else {
PowerIndicatorOFF(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_COLOR_BLACK);
} }
# endif
} }
void setupONOFF() { void setupONOFF() {
@@ -142,11 +144,13 @@ void MQTTtoONOFF(char* topicOri, JsonObject& ONOFFdata) {
Log.notice(F("GPIO number: %d" CR), gpio); Log.notice(F("GPIO number: %d" CR), gpio);
pinMode(gpio, OUTPUT); pinMode(gpio, OUTPUT);
digitalWrite(gpio, boolSWITCHTYPE); digitalWrite(gpio, boolSWITCHTYPE);
# ifdef LED_ACTUATOR_ONOFF
if (boolSWITCHTYPE == ACTUATOR_ON) { if (boolSWITCHTYPE == ACTUATOR_ON) {
PowerIndicatorON(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_ACTUATOR_ONOFF_COLOR);
} else { } else {
PowerIndicatorOFF(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_COLOR_BLACK);
} }
# endif
# ifdef ESP32 # ifdef ESP32
if (ONOFFConfig.useLastStateOnStart) { if (ONOFFConfig.useLastStateOnStart) {
ONOFFdata["save"] = true; ONOFFdata["save"] = true;
@@ -221,11 +225,13 @@ void MQTTtoONOFF(char* topicOri, char* datacallback) {
ON = false; ON = false;
digitalWrite(gpio, ON); digitalWrite(gpio, ON);
# ifdef LED_ACTUATOR_ONOFF
if (ON == ACTUATOR_ON) { if (ON == ACTUATOR_ON) {
PowerIndicatorON(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_ACTUATOR_ONOFF_COLOR);
} else { } else {
PowerIndicatorOFF(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_COLOR_BLACK);
} }
# endif
// we acknowledge the sending by publishing the value to an acknowledgement topic // we acknowledge the sending by publishing the value to an acknowledgement topic
char b = ON; char b = ON;
pub(subjectGTWONOFFtoMQTT, &b); pub(subjectGTWONOFFtoMQTT, &b);
@@ -246,7 +252,9 @@ void overLimitTemp(void* pvParameters) {
if (digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) { // This could be with the previous condition, but it is better to trigger the digitalRead only if the previous condition is met to avoid the digitalRead if (digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) { // This could be with the previous condition, but it is better to trigger the digitalRead only if the previous condition is met to avoid the digitalRead
Log.error(F("[ActuatorONOFF] OverTemperature detected ( %F > %F ) switching OFF Actuator" CR), internalTempc, MAX_TEMP_ACTUATOR); Log.error(F("[ActuatorONOFF] OverTemperature detected ( %F > %F ) switching OFF Actuator" CR), internalTempc, MAX_TEMP_ACTUATOR);
ActuatorTrigger(); ActuatorTrigger();
CriticalIndicatorON(); # ifdef LED_ACTUATOR_ONOFF
ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_ERROR_COLOR, -1);
# endif
} }
} }
previousInternalTempc = internalTempc; previousInternalTempc = internalTempc;
@@ -266,7 +274,9 @@ void overLimitCurrent(float RN8209current) {
if (digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) { // This could be with the previous condition, but it is better to trigger the digitalRead only if the previous condition is met to avoid the digitalRead if (digitalRead(ACTUATOR_ONOFF_GPIO) == ACTUATOR_ON) { // This could be with the previous condition, but it is better to trigger the digitalRead only if the previous condition is met to avoid the digitalRead
Log.error(F("[ActuatorONOFF] OverCurrent detected ( %F > %F ) switching OFF Actuator" CR), RN8209current, MAX_CURRENT_ACTUATOR); Log.error(F("[ActuatorONOFF] OverCurrent detected ( %F > %F ) switching OFF Actuator" CR), RN8209current, MAX_CURRENT_ACTUATOR);
ActuatorTrigger(); ActuatorTrigger();
CriticalIndicatorON(); # ifdef LED_ACTUATOR_ONOFF
ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_ERROR_COLOR, -1);
# endif
} }
} }
RN8209previousCurrent = RN8209current; RN8209previousCurrent = RN8209current;
@@ -284,11 +294,13 @@ void ActuatorTrigger() {
uint8_t level = !digitalRead(ACTUATOR_ONOFF_GPIO); uint8_t level = !digitalRead(ACTUATOR_ONOFF_GPIO);
Log.trace(F("Actuator triggered %d" CR), level); Log.trace(F("Actuator triggered %d" CR), level);
digitalWrite(ACTUATOR_ONOFF_GPIO, level); digitalWrite(ACTUATOR_ONOFF_GPIO, level);
# ifdef LED_ACTUATOR_ONOFF
if (level == ACTUATOR_ON) { if (level == ACTUATOR_ON) {
PowerIndicatorON(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_ACTUATOR_ONOFF_COLOR);
} else { } else {
PowerIndicatorOFF(); ledManager.setMode(LED_ACTUATOR_ONOFF, 0, LEDManager::Mode::STATIC, LED_COLOR_BLACK);
} }
# endif
# ifdef ESP32 # ifdef ESP32
if (ONOFFConfig.useLastStateOnStart) { if (ONOFFConfig.useLastStateOnStart) {
-1
View File
@@ -203,6 +203,5 @@ void M5Print(char* line1, char* line2, char* line3) {
M5.Lcd.drawString(line2, 5, M5.Lcd.height() * 0.8, 1); M5.Lcd.drawString(line2, 5, M5.Lcd.height() * 0.8, 1);
M5.Lcd.drawString(line3, 5, M5.Lcd.height() * 0.9, 1); M5.Lcd.drawString(line3, 5, M5.Lcd.height() * 0.9, 1);
delay(2000); delay(2000);
InfoIndicatorOFF(); // to switch off no need of condition
} }
#endif #endif
+7 -2
View File
@@ -53,8 +53,13 @@ void testDevice() {
void testLeds() { void testLeds() {
Log.notice(F("LED Test" CR)); Log.notice(F("LED Test" CR));
InfoIndicatorON(); ledManager.setMode(0, 0, LEDManager::Mode::STATIC, LED_NETWORK_OK_COLOR, -1);
SendReceiveIndicatorON(); delay(1000);
ledManager.setMode(0, 1, LEDManager::Mode::STATIC, LED_NETWORK_OK_COLOR, -1);
delay(1000);
ledManager.setMode(0, 2, LEDManager::Mode::STATIC, LED_NETWORK_OK_COLOR, -1);
delay(1000);
ledManager.setMode(0, 3, LEDManager::Mode::STATIC, LED_NETWORK_OK_COLOR, -1);
Log.notice(F("LED Test Finished" CR)); Log.notice(F("LED Test Finished" CR));
} }
+1 -1
View File
@@ -557,7 +557,7 @@ void pubMqttDiscovery() {
stateClassNone, //State Class stateClassNone, //State Class
"false", "true" //state_off, state_on "false", "true" //state_off, state_on
); );
# ifdef RGB_INDICATORS # ifdef LED_ADDRESSABLE
createDiscovery("number", //set Type createDiscovery("number", //set Type
subjectSYStoMQTT, "SYS: LED Brightness", (char*)getUniqueId("rgbb", "").c_str(), //set state_topic,name,uniqueId subjectSYStoMQTT, "SYS: LED Brightness", (char*)getUniqueId("rgbb", "").c_str(), //set state_topic,name,uniqueId
will_Topic, "", "{{ (value_json.rgbb/2.55) | round(0) }}", //set availability_topic,device_class,value_template, will_Topic, "", "{{ (value_json.rgbb/2.55) | round(0) }}", //set availability_topic,device_class,value_template,
-2
View File
@@ -64,8 +64,6 @@ void MeasureGPIOInput() {
resetTime = millis(); resetTime = millis();
} else if ((millis() - resetTime) > 3000) { } else if ((millis() - resetTime) > 3000) {
Log.trace(F("Button Held" CR)); Log.trace(F("Button Held" CR));
InfoIndicatorOFF();
SendReceiveIndicatorOFF();
// Switching off the relay during reset or failsafe operations // Switching off the relay during reset or failsafe operations
# ifdef ZactuatorONOFF # ifdef ZactuatorONOFF
uint8_t level = digitalRead(ACTUATOR_ONOFF_GPIO); uint8_t level = digitalRead(ACTUATOR_ONOFF_GPIO);
+5 -5
View File
@@ -1937,7 +1937,7 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
// Queue completed message // Queue completed message
if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) { if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title); Log.warning(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message); free(message);
} else { } else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title); // Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
@@ -2003,7 +2003,7 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
// Queue completed message // Queue completed message
if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) { if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title); Log.warning(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message); free(message);
} else { } else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title); // Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
@@ -2331,7 +2331,7 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
line4.toCharArray(message->line4, WEBUI_TEXT_WIDTH); line4.toCharArray(message->line4, WEBUI_TEXT_WIDTH);
if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) { if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title); Log.warning(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message); free(message);
} else { } else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title); // Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
@@ -2389,7 +2389,7 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
// Queue completed message // Queue completed message
if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) { if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title); Log.warning(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message); free(message);
} else { } else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title); // Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
@@ -2441,7 +2441,7 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {
// Queue completed message // Queue completed message
if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) { if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title); Log.warning(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message); free(message);
} else { } else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title); // Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
+159 -69
View File
@@ -38,7 +38,8 @@ enum GatewayState {
BROKER_DISCONNECTED, BROKER_DISCONNECTED,
LOCAL_OTA_IN_PROGRESS, LOCAL_OTA_IN_PROGRESS,
REMOTE_OTA_IN_PROGRESS, REMOTE_OTA_IN_PROGRESS,
SLEEPING SLEEPING,
ERROR
}; };
GatewayState gatewayState = GatewayState::WAITING_ONBOARDING; GatewayState gatewayState = GatewayState::WAITING_ONBOARDING;
@@ -86,8 +87,11 @@ bool ready_to_sleep = false;
#include <memory> #include <memory>
#include "LEDManager.h"
#include "TheengsUtils.h" #include "TheengsUtils.h"
LEDManager ledManager;
struct JsonBundle { struct JsonBundle {
StaticJsonDocument<JSON_MSG_BUFFER> doc; StaticJsonDocument<JSON_MSG_BUFFER> doc;
}; };
@@ -382,6 +386,8 @@ void Config_update(JsonObject& data, const char* key, T& var) {
bool jsonDispatch(JsonObject& data) { bool jsonDispatch(JsonObject& data) {
bool res = false; bool res = false;
if (data.containsKey("origin")) { if (data.containsKey("origin")) {
GatewayState previousGatewayState = gatewayState;
gatewayState = GatewayState::PROCESSING;
#if message_UTCtimestamp == true #if message_UTCtimestamp == true
data["UTCtime"] = TheengsUtils::UTCtimestamp(); data["UTCtime"] = TheengsUtils::UTCtimestamp();
#endif #endif
@@ -405,8 +411,10 @@ bool jsonDispatch(JsonObject& data) {
res = true; res = true;
} }
#endif #endif
gatewayState = previousGatewayState; // restore the previous state
} else { } else {
Log.error(F("No origin in JSON filtered" CR)); Log.error(F("No origin in JSON filtered" CR));
gatewayState = GatewayState::ERROR;
} }
return res; return res;
} }
@@ -416,6 +424,7 @@ boolean enqueueJsonObject(const StaticJsonDocument<JSON_MSG_BUFFER>& jsonDoc, in
receivedMessages++; receivedMessages++;
if (jsonDoc.size() == 0) { if (jsonDoc.size() == 0) {
Log.error(F("Empty JSON, skipping" CR)); Log.error(F("Empty JSON, skipping" CR));
gatewayState = GatewayState::ERROR;
return true; return true;
} }
if (queueLength >= QueueSize) { if (queueLength >= QueueSize) {
@@ -430,6 +439,7 @@ boolean enqueueJsonObject(const StaticJsonDocument<JSON_MSG_BUFFER>& jsonDoc, in
// Semaphore check before enqueueing a document // Semaphore check before enqueueing a document
if (xSemaphoreTake(xQueueMutex, pdMS_TO_TICKS(timeout)) == pdFALSE) { if (xSemaphoreTake(xQueueMutex, pdMS_TO_TICKS(timeout)) == pdFALSE) {
Log.error(F("xQueueMutex not taken" CR)); Log.error(F("xQueueMutex not taken" CR));
gatewayState = GatewayState::ERROR;
blockedMessages++; blockedMessages++;
return false; return false;
} }
@@ -474,6 +484,7 @@ std::string generateHash(const std::string& input) {
void buildTopicFromId(JsonObject& Jsondata, const char* origin) { void buildTopicFromId(JsonObject& Jsondata, const char* origin) {
if (!Jsondata.containsKey("id")) { if (!Jsondata.containsKey("id")) {
Log.error(F("No id in Jsondata" CR)); Log.error(F("No id in Jsondata" CR));
gatewayState = GatewayState::ERROR;
return; return;
} }
@@ -491,6 +502,7 @@ void buildTopicFromId(JsonObject& Jsondata, const char* origin) {
topic = Jsondata["uuid"].as<std::string>(); topic = Jsondata["uuid"].as<std::string>();
} else { } else {
Log.error(F("No uuid in Jsondata" CR)); Log.error(F("No uuid in Jsondata" CR));
gatewayState = GatewayState::ERROR;
} }
} }
@@ -520,6 +532,7 @@ void emptyQueue() {
#ifdef ESP32 #ifdef ESP32
if (xSemaphoreTake(xQueueMutex, pdMS_TO_TICKS(QueueSemaphoreTimeOutTask)) == pdFALSE) { if (xSemaphoreTake(xQueueMutex, pdMS_TO_TICKS(QueueSemaphoreTimeOutTask)) == pdFALSE) {
Log.error(F("xQueueMutex not taken" CR)); Log.error(F("xQueueMutex not taken" CR));
gatewayState = GatewayState::ERROR;
return; return;
} }
#endif #endif
@@ -530,6 +543,7 @@ void emptyQueue() {
#endif #endif
if (error) { if (error) {
Log.error(F("deserialize jsonQueue.front() failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity()); Log.error(F("deserialize jsonQueue.front() failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity());
gatewayState = GatewayState::ERROR;
} else { } else {
if (jsonDispatch(obj)) if (jsonDispatch(obj))
queueLengthSum++; queueLengthSum++;
@@ -566,6 +580,7 @@ bool pub(const char* topicori, JsonObject& data) {
} }
if (data.size() == 0) { if (data.size() == 0) {
Log.error(F("Empty JSON, not published" CR)); Log.error(F("Empty JSON, not published" CR));
gatewayState = GatewayState::ERROR;
return res; return res;
} }
String topic = String(mqtt_topic) + String(gateway_name) + String(topicori); String topic = String(mqtt_topic) + String(gateway_name) + String(topicori);
@@ -662,11 +677,11 @@ bool pubMQTT(const char* topic, const char* payload, bool retainFlag) {
#ifdef ESP32 #ifdef ESP32
if (xSemaphoreTake(xMqttMutex, pdMS_TO_TICKS(QueueSemaphoreTimeOutTask)) == pdFALSE) { if (xSemaphoreTake(xMqttMutex, pdMS_TO_TICKS(QueueSemaphoreTimeOutTask)) == pdFALSE) {
Log.error(F("xMqttMutex not taken" CR)); Log.error(F("xMqttMutex not taken" CR));
gatewayState = GatewayState::ERROR;
return res; return res;
} }
#endif #endif
if (mqtt && mqtt->connected()) { if (mqtt && mqtt->connected()) {
SendReceiveIndicatorON();
Log.notice(F("[ OMG->MQTT ] topic: %s msg: %s " CR), topic, payload); Log.notice(F("[ OMG->MQTT ] topic: %s msg: %s " CR), topic, payload);
res = mqtt->publish(topic, payload, 0, retainFlag); res = mqtt->publish(topic, payload, 0, retainFlag);
} else { } else {
@@ -784,7 +799,7 @@ void SYSConfig_init() {
SYSConfig.discovery = DEFAULT_DISCOVERY; SYSConfig.discovery = DEFAULT_DISCOVERY;
SYSConfig.ohdiscovery = OpenHABDiscovery; SYSConfig.ohdiscovery = OpenHABDiscovery;
#endif #endif
#ifdef RGB_INDICATORS #ifdef LED_ADDRESSABLE
SYSConfig.rgbbrightness = DEFAULT_ADJ_BRIGHTNESS; SYSConfig.rgbbrightness = DEFAULT_ADJ_BRIGHTNESS;
#endif #endif
SYSConfig.powerMode = DEFAULT_LOW_POWER_MODE; SYSConfig.powerMode = DEFAULT_LOW_POWER_MODE;
@@ -798,7 +813,7 @@ void SYSConfig_fromJson(JsonObject& SYSdata) {
Config_update(SYSdata, "disc", SYSConfig.discovery); Config_update(SYSdata, "disc", SYSConfig.discovery);
Config_update(SYSdata, "ohdisc", SYSConfig.ohdiscovery); Config_update(SYSdata, "ohdisc", SYSConfig.ohdiscovery);
#endif #endif
#ifdef RGB_INDICATORS #ifdef LED_ADDRESSABLE
Config_update(SYSdata, "rgbb", SYSConfig.rgbbrightness); Config_update(SYSdata, "rgbb", SYSConfig.rgbbrightness);
#endif #endif
Config_update(SYSdata, "powermode", SYSConfig.powerMode); Config_update(SYSdata, "powermode", SYSConfig.powerMode);
@@ -816,7 +831,7 @@ void SYSConfig_save() {
SYSdata["disc"] = SYSConfig.discovery; SYSdata["disc"] = SYSConfig.discovery;
SYSdata["ohdisc"] = SYSConfig.ohdiscovery; SYSdata["ohdisc"] = SYSConfig.ohdiscovery;
# endif # endif
# ifdef RGB_INDICATORS # ifdef LED_ADDRESSABLE
SYSdata["rgbb"] = SYSConfig.rgbbrightness; SYSdata["rgbb"] = SYSConfig.rgbbrightness;
# endif # endif
String conf = ""; String conf = "";
@@ -855,6 +870,7 @@ void SYSConfig_load() {
preferences.end(); preferences.end();
if (error) { if (error) {
Log.error(F("SYS config deserialization failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity()); Log.error(F("SYS config deserialization failed: %s, buffer capacity: %u" CR), error.c_str(), jsonBuffer.capacity());
gatewayState = GatewayState::ERROR;
return; return;
} }
if (jsonBuffer.isNull()) { if (jsonBuffer.isNull()) {
@@ -878,7 +894,7 @@ std::pair<String, uint16_t> discoverMQTTbroker() {
Log.trace(F("Browsing for MQTT service" CR)); Log.trace(F("Browsing for MQTT service" CR));
int n = MDNS.queryService("mqtt", "tcp"); int n = MDNS.queryService("mqtt", "tcp");
if (n == 0) { if (n == 0) {
Log.error(F("no services found" CR)); Log.warning(F("no services found" CR));
} else { } else {
Log.trace(F("%d service(s) found" CR), n); Log.trace(F("%d service(s) found" CR), n);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
@@ -889,7 +905,7 @@ std::pair<String, uint16_t> discoverMQTTbroker() {
Log.trace(F("One MQTT server found setting parameters" CR)); Log.trace(F("One MQTT server found setting parameters" CR));
return {MDNS.IP(0).toString(), uint16_t(MDNS.port(0))}; return {MDNS.IP(0).toString(), uint16_t(MDNS.port(0))};
} else { } else {
Log.error(F("Several MQTT servers found, please deactivate mDNS and set your default server" CR)); Log.warning(F("Several MQTT servers found, please deactivate mDNS and set your default server" CR));
} }
} }
return {"", 0}; return {"", 0};
@@ -1043,6 +1059,7 @@ void setupMQTT() {
if (cnt_parameters_backup) { if (cnt_parameters_backup) {
// this was the first attempt to connect to a new server and it failed, revert to old settings // this was the first attempt to connect to a new server and it failed, revert to old settings
Log.error(F("MQTT connection failed, reverting to previous settings" CR)); Log.error(F("MQTT connection failed, reverting to previous settings" CR));
gatewayState = GatewayState::ERROR;
cnt_parameters_array[cnt_index] = cnt_parameters_backup->parameters; cnt_parameters_array[cnt_index] = cnt_parameters_backup->parameters;
cnt_index = cnt_parameters_backup->cnt_index; cnt_index = cnt_parameters_backup->cnt_index;
mqttSetupPending = true; mqttSetupPending = true;
@@ -1051,10 +1068,7 @@ void setupMQTT() {
return; return;
} }
ErrorIndicatorON(); delayWithOTA(10000);
delayWithOTA(5000);
ErrorIndicatorOFF();
delayWithOTA(5000);
if (failure_number_mqtt > maxRetryWatchDog) { if (failure_number_mqtt > maxRetryWatchDog) {
# ifndef ESPWifiManualSetup # ifndef ESPWifiManualSetup
@@ -1114,12 +1128,14 @@ void setESPWifiProtocolTxPower() {
# if WifiGMode == true # if WifiGMode == true
if (esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G) != ESP_OK) { if (esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G) != ESP_OK) {
Log.error(F("Failed to change WifiMode." CR)); Log.error(F("Failed to change WifiMode." CR));
gatewayState = GatewayState::ERROR;
} }
# endif # endif
# if WifiGMode == false # if WifiGMode == false
if (esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N) != ESP_OK) { if (esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N) != ESP_OK) {
Log.error(F("Failed to change WifiMode." CR)); Log.error(F("Failed to change WifiMode." CR));
gatewayState = GatewayState::ERROR;
} }
# endif # endif
@@ -1153,12 +1169,14 @@ void setESPWifiProtocolTxPower() {
# if WifiGMode == true # if WifiGMode == true
if (!wifi_set_phy_mode(PHY_MODE_11G)) { if (!wifi_set_phy_mode(PHY_MODE_11G)) {
Log.error(F("Failed to change WifiMode." CR)); Log.error(F("Failed to change WifiMode." CR));
gatewayState = GatewayState::ERROR;
} }
# endif # endif
# if WifiGMode == false # if WifiGMode == false
if (!wifi_set_phy_mode(PHY_MODE_11N)) { if (!wifi_set_phy_mode(PHY_MODE_11N)) {
Log.error(F("Failed to change WifiMode." CR)); Log.error(F("Failed to change WifiMode." CR));
gatewayState = GatewayState::ERROR;
} }
# endif # endif
@@ -1190,6 +1208,88 @@ void setESPWifiProtocolTxPower() {
} }
#endif #endif
#ifdef ESP32
void updateAndHandleLEDsTask(void* pvParameters) {
for (;;) {
updateAndHandleLEDsTask();
vTaskDelay(pdMS_TO_TICKS(100));
}
}
#endif
void updateAndHandleLEDsTask() {
static GatewayState previousGatewayState;
if (previousGatewayState != gatewayState) {
#ifdef LED_POWER
ledManager.setMode(0, LED_POWER, LEDManager::STATIC, LED_POWER_COLOR, -1);
#endif
switch (gatewayState) {
case PROCESSING:
#ifdef LED_PROCESSING
ledManager.setMode(0, LED_PROCESSING, LEDManager::BLINK, LED_PROCESSING_COLOR, 3);
#endif
break;
case WAITING_ONBOARDING:
#ifdef LED_BROKER
ledManager.setMode(0, LED_BROKER, LEDManager::STATIC, LED_WAITING_ONBOARD_COLOR, -1);
#endif
break;
case ONBOARDING:
#ifdef LED_BROKER
ledManager.setMode(0, LED_BROKER, LEDManager::STATIC, LED_ONBOARD_COLOR, -1);
#endif
break;
case NTWK_CONNECTED:
#ifdef LED_NETWORK
ledManager.setMode(0, LED_NETWORK, LEDManager::STATIC, LED_NETWORK_OK_COLOR, -1);
#endif
break;
case BROKER_CONNECTED:
#ifdef LED_BROKER
ledManager.setMode(0, LED_BROKER, LEDManager::STATIC, LED_BROKER_OK_COLOR, -1);
#endif
break;
case NTWK_DISCONNECTED:
#ifdef LED_NETWORK
ledManager.setMode(0, LED_NETWORK, LEDManager::BLINK, LED_NETWORK_ERROR_COLOR, -1);
#endif
break;
case BROKER_DISCONNECTED:
#ifdef LED_BROKER
ledManager.setMode(0, LED_BROKER, LEDManager::BLINK, LED_BROKER_ERROR_COLOR, -1);
#endif
break;
case SLEEPING:
ledManager.setMode(0, -1, LEDManager::OFF, 0, -1);
break;
case OFFLINE:
#ifdef LED_NETWORK
ledManager.setMode(0, LED_NETWORK, LEDManager::BLINK, LED_OFFLINE_COLOR, -1);
#endif
break;
case LOCAL_OTA_IN_PROGRESS:
#ifdef LED_PROCESSING
ledManager.setMode(0, LED_PROCESSING, LEDManager::BLINK, LED_OTA_LOCAL_COLOR, -1);
#endif
break;
case REMOTE_OTA_IN_PROGRESS:
#ifdef LED_PROCESSING
ledManager.setMode(0, LED_PROCESSING, LEDManager::BLINK, LED_OTA_REMOTE_COLOR, -1);
#endif
break;
case ERROR:
#ifdef LED_ERROR
ledManager.setMode(0, LED_ERROR, LEDManager::BLINK, LED_ERROR_COLOR, 3);
#endif
break;
default:
break;
}
previousGatewayState = gatewayState;
}
ledManager.update();
}
void setup() { void setup() {
//Launch serial for debugging purposes //Launch serial for debugging purposes
Serial.begin(SERIAL_BAUD); Serial.begin(SERIAL_BAUD);
@@ -1208,12 +1308,17 @@ void setup() {
if (SYSConfig.offline) if (SYSConfig.offline)
gatewayState = GatewayState::OFFLINE; gatewayState = GatewayState::OFFLINE;
//setup LED status #ifdef LED_ADDRESSABLE
SetupIndicatorError(); # ifdef LED_ADDRESSABLE_PIN1
SetupIndicatorSendReceive(); ledManager.addLEDStrip(LED_ADDRESSABLE_PIN1, LED_ADDRESSABLE_NUM);
SetupIndicatorInfo(); # endif
SetupIndicators(); // For RGB Leds # ifdef LED_ADDRESSABLE_PIN2
ONIndicatorON(); ledManager.addLEDStrip(LED_ADDRESSABLE_PIN2, LED_ADDRESSABLE_NUM);
# endif
ledManager.setBrightness(SYSConfig.rgbbrightness);
#elif LED_PIN
ledManager.addLEDStrip(LED_PIN, 1);
#endif
#ifdef ESP8266 #ifdef ESP8266
# ifndef ZgatewaySRFB // if we are not in sonoff rf bridge case we apply the ESP8266 GPIO optimization # ifndef ZgatewaySRFB // if we are not in sonoff rf bridge case we apply the ESP8266 GPIO optimization
@@ -1221,6 +1326,7 @@ void setup() {
Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY); // enable on ESP8266 to free some pin Serial.begin(SERIAL_BAUD, SERIAL_8N1, SERIAL_TX_ONLY); // enable on ESP8266 to free some pin
# endif # endif
#elif ESP32 #elif ESP32
xTaskCreate(updateAndHandleLEDsTask, "updateAndHandleLEDsTask", 2500, NULL, 1, NULL);
xQueueMutex = xSemaphoreCreateMutex(); xQueueMutex = xSemaphoreCreateMutex();
xMqttMutex = xSemaphoreCreateMutex(); xMqttMutex = xSemaphoreCreateMutex();
# if defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5STACK) || defined(ZboardM5TOUGH) # if defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5STACK) || defined(ZboardM5TOUGH)
@@ -1239,6 +1345,7 @@ void setup() {
gpio_num_t wake_pin0 = static_cast<gpio_num_t>(ESP32_EXT0_WAKE_PIN); gpio_num_t wake_pin0 = static_cast<gpio_num_t>(ESP32_EXT0_WAKE_PIN);
if (esp_sleep_enable_ext0_wakeup(wake_pin0, ESP32_EXT0_WAKE_PIN_STATE) != ESP_OK) { if (esp_sleep_enable_ext0_wakeup(wake_pin0, ESP32_EXT0_WAKE_PIN_STATE) != ESP_OK) {
Log.error(F("Failed to set deep sleep EXT0 Wakeup." CR)); Log.error(F("Failed to set deep sleep EXT0 Wakeup." CR));
gatewayState = GatewayState::ERROR;
} }
#endif #endif
#ifdef ESP32_EXT1_WAKE_PIN #ifdef ESP32_EXT1_WAKE_PIN
@@ -1247,6 +1354,7 @@ void setup() {
esp_sleep_ext1_wakeup_mode_t wake_state1 = static_cast<esp_sleep_ext1_wakeup_mode_t>(ESP32_EXT1_WAKE_PIN_STATE); esp_sleep_ext1_wakeup_mode_t wake_state1 = static_cast<esp_sleep_ext1_wakeup_mode_t>(ESP32_EXT1_WAKE_PIN_STATE);
if (esp_sleep_enable_ext1_wakeup(wake_pin_bitmask, wake_state1) != ESP_OK) { if (esp_sleep_enable_ext1_wakeup(wake_pin_bitmask, wake_state1) != ESP_OK) {
Log.error(F("Failed to set deep sleep EXT1 Wakeup." CR)); Log.error(F("Failed to set deep sleep EXT1 Wakeup." CR));
gatewayState = GatewayState::ERROR;
} }
#endif #endif
#ifdef ESP32 #ifdef ESP32
@@ -1526,8 +1634,6 @@ void setOTA() {
ArduinoOTA.onStart([]() { ArduinoOTA.onStart([]() {
Log.trace(F("Start OTA, lock other functions" CR)); Log.trace(F("Start OTA, lock other functions" CR));
ErrorIndicatorON();
SendReceiveIndicatorON();
last_ota_activity_millis = millis(); last_ota_activity_millis = millis();
#ifdef ESP32 #ifdef ESP32
ProcessLock = true; ProcessLock = true;
@@ -1540,24 +1646,18 @@ void setOTA() {
ArduinoOTA.onEnd([]() { ArduinoOTA.onEnd([]() {
Log.trace(F("\nOTA done" CR)); Log.trace(F("\nOTA done" CR));
last_ota_activity_millis = 0; last_ota_activity_millis = 0;
ErrorIndicatorOFF();
SendReceiveIndicatorOFF();
lpDisplayPrint("OTA done"); lpDisplayPrint("OTA done");
ESPRestart(6); ESPRestart(6);
}); });
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Log.trace(F("Progress: %u%%\r" CR), (progress / (total / 100))); Log.trace(F("Progress: %u%%\r" CR), (progress / (total / 100)));
gatewayState = GatewayState::LOCAL_OTA_IN_PROGRESS; gatewayState = GatewayState::LOCAL_OTA_IN_PROGRESS;
#ifdef ESP32
//esp_task_wdt_reset();
#endif
last_ota_activity_millis = millis(); last_ota_activity_millis = millis();
}); });
ArduinoOTA.onError([](ota_error_t error) { ArduinoOTA.onError([](ota_error_t error) {
last_ota_activity_millis = millis(); last_ota_activity_millis = millis();
ErrorIndicatorOFF();
SendReceiveIndicatorOFF();
Serial.printf("Error[%u]: ", error); Serial.printf("Error[%u]: ", error);
gatewayState = GatewayState::ERROR;
if (error == OTA_AUTH_ERROR) if (error == OTA_AUTH_ERROR)
Log.error(F("Auth Failed" CR)); Log.error(F("Auth Failed" CR));
else if (error == OTA_BEGIN_ERROR) else if (error == OTA_BEGIN_ERROR)
@@ -1592,6 +1692,7 @@ void setupTLS(int index) {
Log.notice(F("Server cert found from ss_server_cert" CR)); Log.notice(F("Server cert found from ss_server_cert" CR));
} else { } else {
Log.error(F("No server cert found" CR)); Log.error(F("No server cert found" CR));
gatewayState = GatewayState::ERROR;
} }
# if AWS_IOT # if AWS_IOT
@@ -1609,6 +1710,7 @@ void setupTLS(int index) {
Log.notice(F("Client cert found from ss_client_cert" CR)); Log.notice(F("Client cert found from ss_client_cert" CR));
} else { } else {
Log.error(F("No client cert found" CR)); Log.error(F("No client cert found" CR));
gatewayState = GatewayState::ERROR;
} }
if (cnt_parameters_array[index].client_key.length() > MIN_CERT_LENGTH) { if (cnt_parameters_array[index].client_key.length() > MIN_CERT_LENGTH) {
sClient->setPrivateKey(cnt_parameters_array[index].client_key.c_str()); sClient->setPrivateKey(cnt_parameters_array[index].client_key.c_str());
@@ -1618,6 +1720,7 @@ void setupTLS(int index) {
Log.notice(F("Client key found from ss_client_key" CR)); Log.notice(F("Client key found from ss_client_key" CR));
} else { } else {
Log.error(F("No client key found" CR)); Log.error(F("No client key found" CR));
gatewayState = GatewayState::ERROR;
} }
# endif # endif
# elif defined(ESP8266) # elif defined(ESP8266)
@@ -1696,6 +1799,7 @@ void setup_wifi() {
if (!WiFi.config(ip_adress, gateway_adress, subnet_adress, dns_adress)) { if (!WiFi.config(ip_adress, gateway_adress, subnet_adress, dns_adress)) {
Log.error(F("Wifi STA Failed to configure" CR)); Log.error(F("Wifi STA Failed to configure" CR));
gatewayState = GatewayState::ERROR;
} }
# endif # endif
@@ -1757,11 +1861,6 @@ void blockingWaitForReset() {
ActuatorTrigger(); ActuatorTrigger();
} }
# endif # endif
# ifdef ESP32
//esp_task_wdt_delete(NULL);
# endif
InfoIndicatorOFF();
SendReceiveIndicatorOFF();
// Checking if the flash has already been erased to identify if we erase it or go into failsafe mode // Checking if the flash has already been erased to identify if we erase it or go into failsafe mode
// going to failsafe mode is done by doing a long button press from a state where the flash has already been erased // going to failsafe mode is done by doing a long button press from a state where the flash has already been erased
if (SPIFFS.begin()) { if (SPIFFS.begin()) {
@@ -1892,6 +1991,7 @@ void saveConfig() {
File configFile = SPIFFS.open("/config.json", "w"); File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) { if (!configFile) {
Log.error(F("failed to open config file for writing" CR)); Log.error(F("failed to open config file for writing" CR));
gatewayState = GatewayState::ERROR;
} }
serializeJson(json, configFile); serializeJson(json, configFile);
@@ -1920,6 +2020,7 @@ bool loadConfigFromFlash() {
auto error = deserializeJson(json, configFile); auto error = deserializeJson(json, configFile);
if (error) { if (error) {
Log.error(F("deserialize config failed: %s, buffer capacity: %u" CR), error.c_str(), json.capacity()); Log.error(F("deserialize config failed: %s, buffer capacity: %u" CR), error.c_str(), json.capacity());
gatewayState = GatewayState::ERROR;
} }
if (!json.isNull()) { if (!json.isNull()) {
Log.trace(F("\nparsed json, size: %u" CR), json.memoryUsage()); Log.trace(F("\nparsed json, size: %u" CR), json.memoryUsage());
@@ -2155,8 +2256,6 @@ void setupwifi(bool reset_settings) {
if (!SYSConfig.offline && !wifi_reconnect_bypass()) // if we didn't connect with saved credential we start Wifimanager web portal if (!SYSConfig.offline && !wifi_reconnect_bypass()) // if we didn't connect with saved credential we start Wifimanager web portal
{ {
InfoIndicatorON();
ErrorIndicatorON();
Log.notice(F("Connect your phone to WIFI AP: %s with PWD: %s" CR), WifiManager_ssid, ota_pass); Log.notice(F("Connect your phone to WIFI AP: %s with PWD: %s" CR), WifiManager_ssid, ota_pass);
gatewayState = GatewayState::ONBOARDING; gatewayState = GatewayState::ONBOARDING;
//fetches ssid and pass and tries to connect //fetches ssid and pass and tries to connect
@@ -2189,11 +2288,10 @@ void setupwifi(bool reset_settings) {
ESPRestart(3); ESPRestart(3);
} }
} }
InfoIndicatorOFF();
ErrorIndicatorOFF();
} }
displayPrint("Network connected"); displayPrint("Network connected");
gatewayState = GatewayState::NTWK_CONNECTED;
if (shouldSaveConfig) { if (shouldSaveConfig) {
//read updated parameters //read updated parameters
@@ -2276,6 +2374,7 @@ void setup_ethernet_esp32() {
} }
} else { } else {
Log.error(F("Ethernet not started" CR)); Log.error(F("Ethernet not started" CR));
gatewayState = GatewayState::ERROR;
} }
} }
@@ -2296,11 +2395,11 @@ void WiFiEvent(WiFiEvent_t event) {
ethConnected = true; ethConnected = true;
break; break;
case ARDUINO_EVENT_ETH_DISCONNECTED: case ARDUINO_EVENT_ETH_DISCONNECTED:
Log.error(F("Ethernet Disconnected" CR)); Log.warning(F("Ethernet Disconnected" CR));
ethConnected = false; ethConnected = false;
break; break;
case ARDUINO_EVENT_ETH_STOP: case ARDUINO_EVENT_ETH_STOP:
Log.error(F("Ethernet Stopped" CR)); Log.warning(F("Ethernet Stopped" CR));
ethConnected = false; ethConnected = false;
break; break;
default: default:
@@ -2357,8 +2456,8 @@ void loop() {
checkButton(); // check if a reset of wifi/mqtt settings is asked checkButton(); // check if a reset of wifi/mqtt settings is asked
#endif #endif
#ifdef ESP32 #ifdef ESP8266
//esp_task_wdt_reset(); updateAndHandleLEDsTask(); // With ESP8266 we need to update the LEDs in the loop
#endif #endif
if (!SYSConfig.offline) { if (!SYSConfig.offline) {
if (mqttSetupPending) { if (mqttSetupPending) {
@@ -2372,8 +2471,6 @@ void loop() {
// Switch off of the LED after TimeLedON // Switch off of the LED after TimeLedON
if (now > (timer_led_measures + (TimeLedON * 1000))) { if (now > (timer_led_measures + (TimeLedON * 1000))) {
timer_led_measures = millis(); timer_led_measures = millis();
InfoIndicatorOFF();
SendReceiveIndicatorOFF();
} }
if (ethConnected || WiFi.status() == WL_CONNECTED) { if (ethConnected || WiFi.status() == WL_CONNECTED) {
@@ -2387,7 +2484,6 @@ void loop() {
#endif #endif
mqtt->loop(); mqtt->loop();
if (mqtt->connected()) { // MQTT client is still connected if (mqtt->connected()) { // MQTT client is still connected
InfoIndicatorON();
failure_number_ntwk = 0; failure_number_ntwk = 0;
#ifdef ZmqttDiscovery #ifdef ZmqttDiscovery
@@ -2435,20 +2531,13 @@ void loop() {
} }
} }
} else if (!SYSConfig.offline) { // disconnected from network } else if (!SYSConfig.offline) { // disconnected from network
#ifdef ESP32
//esp_task_wdt_reset();
#endif
Log.warning(F("Network disconnected" CR)); Log.warning(F("Network disconnected" CR));
gatewayState = GatewayState::NTWK_DISCONNECTED; gatewayState = GatewayState::NTWK_DISCONNECTED;
ErrorIndicatorON(); if (!wifi_reconnect_bypass()) {
delay(2000); // add a delay to avoid ESP32 crash and reset
#ifdef ESP32
//esp_task_wdt_reset();
#endif
ErrorIndicatorOFF();
delay(2000);
if (!wifi_reconnect_bypass())
sleep(); sleep();
} else {
gatewayState = GatewayState::NTWK_CONNECTED;
}
} }
// Function that doesn't need an active connection // Function that doesn't need an active connection
#if defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5STACK) || defined(ZboardM5TOUGH) #if defined(ZboardM5STICKC) || defined(ZboardM5STICKCP) || defined(ZboardM5STACK) || defined(ZboardM5TOUGH)
@@ -2641,7 +2730,7 @@ String stateMeasures() {
SYSdata["uptime"] = uptime(); SYSdata["uptime"] = uptime();
SYSdata["version"] = OMG_VERSION; SYSdata["version"] = OMG_VERSION;
#ifdef RGB_INDICATORS #ifdef LED_ADDRESSABLE
SYSdata["rgbb"] = SYSConfig.rgbbrightness; SYSdata["rgbb"] = SYSConfig.rgbbrightness;
#endif #endif
#ifdef ZmqttDiscovery #ifdef ZmqttDiscovery
@@ -2656,6 +2745,7 @@ String stateMeasures() {
// Some RTL_433 decoders have memory leak, this is a temporary workaround // Some RTL_433 decoders have memory leak, this is a temporary workaround
if (freeMem < MinimumMemory) { if (freeMem < MinimumMemory) {
Log.error(F("Not enough memory %d, restarting" CR), freeMem); Log.error(F("Not enough memory %d, restarting" CR), freeMem);
gatewayState = GatewayState::ERROR;
ESPRestart(8); ESPRestart(8);
} }
#endif #endif
@@ -2796,6 +2886,7 @@ void receivingMQTT(char* topicOri, char* datacallback) {
auto error = deserializeJson(jsonBuffer, datacallback); auto error = deserializeJson(jsonBuffer, datacallback);
if (error) { if (error) {
Log.error(F("deserialize MQTT data failed: %s" CR), error.c_str()); Log.error(F("deserialize MQTT data failed: %s" CR), error.c_str());
gatewayState = GatewayState::ERROR;
return; return;
} }
@@ -2873,7 +2964,6 @@ void receivingMQTT(char* topicOri, char* datacallback) {
MQTTtoWebUI(topicOri, jsondata); MQTTtoWebUI(topicOri, jsondata);
# endif # endif
#endif #endif
SendReceiveIndicatorON();
MQTTtoSYS(topicOri, jsondata); MQTTtoSYS(topicOri, jsondata);
} else { // not a json object --> simple decoding } else { // not a json object --> simple decoding
@@ -2950,11 +3040,13 @@ bool checkForUpdates() {
auto error = deserializeJson(jsonBuffer, payload); auto error = deserializeJson(jsonBuffer, payload);
if (error) { if (error) {
Log.error(F("Deserialize MQTT data failed: %s" CR), error.c_str()); Log.error(F("Deserialize MQTT data failed: %s" CR), error.c_str());
gatewayState = GatewayState::ERROR;
} }
Log.trace(F("HttpCode %d" CR), httpCode); Log.trace(F("HttpCode %d" CR), httpCode);
Log.trace(F("Payload %s" CR), payload.c_str()); Log.trace(F("Payload %s" CR), payload.c_str());
} else { } else {
Log.error(F("Error on HTTP request")); Log.error(F("Error on HTTP request"));
gatewayState = GatewayState::ERROR;
} }
http.end(); //Free the resources http.end(); //Free the resources
Log.notice(F("Update check done, free heap: %d"), ESP.getFreeHeap()); Log.notice(F("Update check done, free heap: %d"), ESP.getFreeHeap());
@@ -2994,6 +3086,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
if (url) { if (url) {
if (!strstr((url + (strlen(url) - 5)), ".bin")) { if (!strstr((url + (strlen(url) - 5)), ".bin")) {
Log.error(F("Invalid firmware extension" CR)); Log.error(F("Invalid firmware extension" CR));
gatewayState = GatewayState::ERROR;
return; return;
} }
# if MQTT_HTTPS_FW_UPDATE_USE_PASSWORD > 0 # if MQTT_HTTPS_FW_UPDATE_USE_PASSWORD > 0
@@ -3001,10 +3094,12 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
if (pwd) { if (pwd) {
if (strcmp(pwd, ota_pass) != 0) { if (strcmp(pwd, ota_pass) != 0) {
Log.error(F("Invalid OTA password" CR)); Log.error(F("Invalid OTA password" CR));
gatewayState = GatewayState::ERROR;
return; return;
} }
} else { } else {
Log.error(F("No password sent" CR)); Log.error(F("No password sent" CR));
gatewayState = GatewayState::ERROR;
return; return;
} }
# endif # endif
@@ -3024,11 +3119,11 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
# endif # endif
} else { } else {
Log.error(F("Invalid URL" CR)); Log.error(F("Invalid URL" CR));
gatewayState = GatewayState::ERROR;
return; return;
} }
# ifdef ESP32 # ifdef ESP32
ProcessLock = true; ProcessLock = true;
//esp_task_wdt_delete(NULL); // Stop task watchdog during update
# ifdef ZgatewayBT # ifdef ZgatewayBT
stopProcessing(); stopProcessing();
# endif # endif
@@ -3036,8 +3131,6 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
Log.warning(F("Starting firmware update" CR)); Log.warning(F("Starting firmware update" CR));
gatewayState = GatewayState::REMOTE_OTA_IN_PROGRESS; gatewayState = GatewayState::REMOTE_OTA_IN_PROGRESS;
SendReceiveIndicatorON();
ErrorIndicatorON();
StaticJsonDocument<JSON_MSG_BUFFER> jsondata; StaticJsonDocument<JSON_MSG_BUFFER> jsondata;
jsondata["release_summary"] = "Update in progress ..."; jsondata["release_summary"] = "Update in progress ...";
jsondata["origin"] = subjectRLStoMQTT; jsondata["origin"] = subjectRLStoMQTT;
@@ -3106,6 +3199,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
# elif ESP8266 # elif ESP8266
Log.error(F("HTTP_UPDATE_FAILED Error (%d): %s\n" CR), ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); Log.error(F("HTTP_UPDATE_FAILED Error (%d): %s\n" CR), ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
# endif # endif
gatewayState = GatewayState::ERROR;
break; break;
case HTTP_UPDATE_NO_UPDATES: case HTTP_UPDATE_NO_UPDATES:
@@ -3129,9 +3223,6 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
break; break;
} }
SendReceiveIndicatorOFF();
ErrorIndicatorOFF();
ESPRestart(6); ESPRestart(6);
} }
} }
@@ -3144,7 +3235,7 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
*/ */
void readCntParameters(int index) { void readCntParameters(int index) {
if (index < 0 || index > 2) { if (index < 0 || index > 2) {
Log.error(F("Invalid cnt index" CR)); Log.warning(F("Invalid cnt index" CR));
return; return;
} }
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer; StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
@@ -3191,19 +3282,18 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
stateMeasures(); stateMeasures();
} }
} }
#ifdef RGB_INDICATORS #ifdef LED_ADDRESSABLE
if (SYSdata.containsKey("rgbb") && SYSdata["rgbb"].is<float>()) { if (SYSdata.containsKey("rgbb") && SYSdata["rgbb"].is<float>()) {
if (SYSdata["rgbb"] >= 0 && SYSdata["rgbb"] <= 255) { if (SYSdata["rgbb"] >= 0 && SYSdata["rgbb"] <= 255) {
SYSConfig.rgbbrightness = TheengsUtils::round2(SYSdata["rgbb"]); SYSConfig.rgbbrightness = TheengsUtils::round2(SYSdata["rgbb"]);
leds.setBrightness(SYSConfig.rgbbrightness); ledManager.setBrightness(SYSConfig.rgbbrightness);
leds.show();
# ifdef ZactuatorONOFF # ifdef ZactuatorONOFF
updatePowerIndicator(); updatePowerIndicator();
# endif # endif
Log.notice(F("RGB brightness: %d" CR), SYSConfig.rgbbrightness); Log.notice(F("RGB brightness: %d" CR), SYSConfig.rgbbrightness);
stateMeasures(); stateMeasures();
} else { } else {
Log.error(F("RGB brightness value invalid - ignoring command" CR)); Log.warning(F("RGB brightness value invalid - ignoring command" CR));
} }
} }
#endif #endif
@@ -3234,7 +3324,7 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
WiFi.waitForConnectResult(WiFi_TimeOut * 1000); WiFi.waitForConnectResult(WiFi_TimeOut * 1000);
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
Log.error(F("Failed to connect to new AP; falling back" CR)); Log.warning(F("Failed to connect to new AP; falling back" CR));
WiFi.disconnect(true); WiFi.disconnect(true);
WiFi.begin(prev_ssid.c_str(), prev_pass.c_str()); WiFi.begin(prev_ssid.c_str(), prev_pass.c_str());
#if defined(WifiGMode) || defined(WifiPower) #if defined(WifiGMode) || defined(WifiPower)
@@ -3290,7 +3380,7 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
if (SYSdata.containsKey("cnt_index") && SYSdata["cnt_index"].is<int>()) { if (SYSdata.containsKey("cnt_index") && SYSdata["cnt_index"].is<int>()) {
if (SYSdata["cnt_index"].as<int>() < 0 || SYSdata["cnt_index"].as<int>() > 2) { if (SYSdata["cnt_index"].as<int>() < 0 || SYSdata["cnt_index"].as<int>() > 2) {
Log.error(F("Invalid cnt index provided - ignoring command" CR)); Log.warning(F("Invalid cnt index provided - ignoring command" CR));
return; return;
} }
@@ -3413,7 +3503,7 @@ void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
if (SYSConfig.discovery) if (SYSConfig.discovery)
pubMqttDiscovery(); pubMqttDiscovery();
} else { } else {
Log.error(F("Discovery command not a boolean" CR)); Log.warning(F("Discovery command not a boolean" CR));
} }
Log.notice(F("Discovery state: %T" CR), SYSConfig.discovery); Log.notice(F("Discovery state: %T" CR), SYSConfig.discovery);
} }