Merge branch 'arendst/development' into development

This commit is contained in:
reloxx13 2018-09-03 20:48:49 +02:00
commit 7a43a40455
43 changed files with 561 additions and 605 deletions

View File

@ -13,13 +13,13 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute!
[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota)
### Development ### Development
[![Dev Version](https://img.shields.io/badge/development%20version-6.1.1.13-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) [![Dev Version](https://img.shields.io/badge/development%20version-6.2.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/)
[![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota)
See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information and [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information. See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information and [sonoff/_changelog.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_changelog.ino) for detailed change information.
The compiled development versions from current codebase are built around 6AM GMT+2 everyday and posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). The development codebase is checked hourly for changes and if new commits have been merged and compile successfuly they will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA too). It is important to note that these are based on the current development codebase and it is not recommended to flash it to devices used in production or which are hard to reach in the event that you need to manually flash the device if OTA failed. The last compiled commit number is also posted on the same page along with the current build status (if a firmware rebuild is in progress).
### Disclaimer ### Disclaimer
:warning: **DANGER OF ELECTROCUTION** :warning: :warning: **DANGER OF ELECTROCUTION** :warning:

View File

@ -140,6 +140,7 @@ Version 6.2.0 20180901
* Fix Sonoff Bridge data reception when using Portisch EFM8 firmware using in data buffer length (#3605) * Fix Sonoff Bridge data reception when using Portisch EFM8 firmware using in data buffer length (#3605)
* Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21
* Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h * Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h
* Add boot loop detection and perform some solutions
* Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155)
* Add support for TM1638 switch (#2226) * Add support for TM1638 switch (#2226)
* Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525) * Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525)

View File

@ -1,110 +1,74 @@
/* 6.1.1.13 20180828 /* 6.2.0.1 20180902
* Fix 6.1.1.12 regression of Mem and Var default handling (#3618) * Fix possible ambiguity on command parameters if StateText contains numbers only (#3656)
* Optimizations * Fix possible exception due to buffer overflow (#3659)
* Change define USE_ALL_SENSORS to USE_SENSORS as it doesn't contain all sensors due to duplicate I2C addresses * Add Wifi channel number to state message (#3664)
* Fix Wemo emulation to select the first relay when more than one relay is present (#3657)
* Add support for Shelly 1 and basic support for Shelly 2 - No energy monitoring yet (#2789)
* *
* 6.1.1.12 20180827 * 6.2.0 20180901
* Add commands ButtonDebounce 40..1000 and SwitchDebounce 40..1000 to have user control over debounce timing. Default is 50mS (#3594) * Allow user override of define MAX_RULE_VARS and MAX_RULE_TIMERS (#3561)
* Add rule variables %sunrise%, %sunset%, %uptime% and %time% (#3608)
* Fix handling use of default names when using names starting with shortcut character (#3392, #3600)
* Fix Sonoff Bridge data reception when using Portisch EFM8 firmware and in data buffer length (#3605)
* Add optional MQTT_TELE_RETAIN to Energy Margins message (#3612, 3614)
* Add Individual HSBColorX commands (#3430, #3615)
* Add RuleX debug options 8,9,10 (StopOnError) to control RuleX execution status after an exception restart (#3607)
*
* 6.1.1.11 20180826
* Change scheduler phase 1/3 - Fixed when sleep is enabled: Uptime, Delay, PulseTime and TelePeriod (#3581)
* Change scheduler phase 2/3 - Fixed when sleep is enabled: Blinktime (#3581)
* Change scheduler phase 3/3 - Some sensor update timings: AdcEvery 200 -> 250, Senseair 300 -> 250, SDM120 300 -> 250, SDM630 300 -> 250
*
* 6.1.1.10 20180827
* Disable wifi sleep for both Esp8266/Arduino core 2.4.1 and 2.4.2 to solve device freeze caused by Espressif SDK bug (#3554) * Disable wifi sleep for both Esp8266/Arduino core 2.4.1 and 2.4.2 to solve device freeze caused by Espressif SDK bug (#3554)
* Rewrite GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP * Change DS18B20 driver to provide better instant results
* Add command Publish2 for publishing retained MQTT messages (#3593) * Change some sensor drivers to provide instant results
* * Change define USE_ALL_SENSORS to USE_SENSORS as it doesn't contain all sensors due to duplicate I2C addresses
* 6.1.1.9 20180825 * Change some sensor update timings: AdcEvery 200 -> 250, Senseair 300 -> 250, SDM120 300 -> 250, SDM630 300 -> 250
* Allow user override of define MAX_RULE_TIMERS (#3561) * Change default Wifi config option from WPS to Wifi Manager if WPS is disabled or Wifi Smartconfig if webserver is disabled or Wifi Serial input if Smartconfig is disabled
* Allow user override of define MAX_RULE_VARS * Change SHT1x driver to provide better instant results and fix I2C interference
* Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525)
* Fix OtaMagic when file path contains a dash (-) (#3563)
* Fix EnergyReset3 (#2723)
* Change command sleep from restart after change to not restart after change (#3554)
* Add all ruletimer values to command RuleTimer result message (#3571)
* Add RGB support for Domoticz (#3547)
*
* 6.1.1.8 20180825
* Fix MQTT reconnection detection when using TasmotaMqtt library (#3558)
* Add build time setting of ButtonTopic and SwitchTopic (#3414)
* Add display features and dynamic buffering
*
* 6.1.1.7 20180818
* Add initial display support for Lcd, Oled, Matrix, Tft and e-paper - Need more docs
* Fix SDM120 reporting wrong negative values to Domoticz (#3521)
* Fix iFan02 power on state (#3412, #3530)
* Add display define USE_DISPLAY_MODES1TO5 to select display modes 1 to 5
* Add command DisplayRotate 0..3 to select persistent display rotation
*
* 6.1.1.6 20180813
* Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466)
*
* 6.1.1.5 20180812
* Fix some Pow R2 and S31 checksum errors using optimized re-sync
*
* 6.1.1.4 20180812
* Change version representation from 1.1.1a to 1.1.1.1 for better change reference
*
* 6.1.1c 20180720
* Add iFan02 Fanspeed + and Fanspeed - command options (#3415)
* Fix some Pow R2 and S31 checksum errors (#3425)
* Change CounterType 1 from milliseconds to microseconds (#3437)
* Add output support on MCP23008/MCP23017 (#3436)
* Fix LM75AD I2C sensor detection (#3408)
* Add message when JavaScript is not enabled in webbrowser (#3388)
* Fix sonoff-minimal from using default settings
* Add option + to command Rule to concatenate new rule with existing rules (#3365)
* Add initial support for sensor MPU6050 (#3352)
* Add command SerialSend4 to send binary serial data (#3345)
* Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359)
* Fix unsecure main webpage update
* Add Turkish language file (#3332)
* Fix command TimeDst/TimeStd invalid JSON (#3322)
* Fix possible WDT due to long MQTT publish handling (#3313)
* Fix CCS811 temperature and humidity compensation
* Add support for CCS811 sensor (#3309)
* Add command Timers 0/1 to globally disable or enable armed timers (#3270)
*
* 6.1.1b 20180715
* Add support for MPR121 controller in input mode for touch buttons (#3142)
* Add support for MCP230xx for general purpose input expansion and command Sensor29 (#3188)
* Fix command Scale buffer overflow (#3236)
* Fix rules once regression from v6.1.0 (#3198, #3226)
* Add default Wifi Configuration tool as define WIFI_CONFIG_NO_SSID in user_config.h if no SSID is configured (#3224)
* Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h
* Add user selection of WPS as define USE_WPS in user_config.h in preparation for core v2.4.2 (#3221)
* Change default Wifi config option from WPS to Wifi Manager if WPS is disabled
* or Wifi Smartconfig if webserver is disabled
* or Wifi Serial input if Smartconfig is disabled
* Remove WPS and SmartConfig from sonoff-minimal saving 56k code space
*
* 6.1.1a 20180714
* Fix TM1638 compile error (#3212)
* Add TM1638 switch support (#2226)
* Fix invalid response using more than 4 switches and domoticz
* Update sensor drivers to provide instant results
* Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21
* Change SHT1x driver to provide better instant results
* Fix DHT driver mixing values for different sensors (#1797)
* Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) * Change DHT driver to provide better instant results and add decimals to DHT11 (#3164)
* Change DS18x20 driver to provide better instant results (#3169) * Change DS18x20 driver to provide better instant results (#3169)
* Change DS18B20 driver to provide better instant results * Change CounterType 1 from milliseconds to microseconds (#3437)
* Change scheduler for better sleep support using Uptime, Delay, PulseTime and TelePeriod, Blinktime (#3581)
* Remove unused functionality from Sonoff-minimal to save space
* Remove WPS and SmartConfig from sonoff-minimal saving 56k code space
* Remove TSL2561 debug message and update library (#2415) * Remove TSL2561 debug message and update library (#2415)
* Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference * Remove forced restart when sleep command is executed (#3554)
* Fix invalid response using more than 4 switches and domoticz
* Fix sonoff-minimal not using default settings
* Fix unsecure main webpage update
* Fix DHT driver mixing values for different sensors (#1797)
* Fix EnergyReset3 regression not clearing total energy (#2723)
* Fix rules once regression from v6.1.0 (#3198, #3226)
* Fix command Scale buffer overflow (#3236)
* Fix possible WDT due to long MQTT publish handling (#3313)
* Fix command TimeDst/TimeStd invalid JSON (#3322)
* Fix handling of default names when using names starting with shortcut character ",0,1 or 2 (#3392, #3600, #3618)
* Fix LM75AD I2C sensor detection (#3408)
* Fix iFan02 power on state (#3412, #3530)
* Fix some Pow R2 and S31 checksum errors using optimized re-sync (#3425)
* Fix SDM120 reporting wrong negative values to Domoticz (#3521)
* Fix MQTT reconnection detection when using TasmotaMqtt library (#3558)
* Fix OtaMagic when file path contains a dash (-) (#3563)
* Fix Sonoff Bridge data reception when using Portisch EFM8 firmware using in data buffer length (#3605)
* Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21
* Add user selection of Wifi Smartconfig as define USE_SMARTCONFIG in user_config.h
* Add boot loop detection and perform some solutions
* Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155)
* Add experimental (untested) TM1638 switch support (#2226) * Add support for TM1638 switch (#2226)
* Add GPIO options ButtonXn, SwitchXn and CounterXn to select INPUT mode instead of INPUT_PULLUP (#2525)
* Add support for APDS9960 proximity sensor (#3051) * Add support for APDS9960 proximity sensor (#3051)
* Add heap and stack debug information * Add support for MPR121 controller in input mode for touch buttons (#3142)
* Add debug facilities using optional xdrv_99_debug.ino to enable in user_config.h * Add support for MCP230xx for general purpose input expansion and command Sensor29 (#3188)
* Remove not needed functionality from Sonoff-minimal to save space * Add default Wifi Configuration tool as define WIFI_CONFIG_NO_SSID in user_config.h if no SSID is configured (#3224)
* Add command Timers 0/1 to globally disable or enable armed timers (#3270)
* Add support for CCS811 sensor (#3309)
* Add Turkish language file (#3332)
* Add command SerialSend4 to send binary serial data (#3345)
* Add initial support for sensor MPU6050 (#3352)
* Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359)
* Add option + to command Rule to concatenate new rule with existing rules (#3365)
* Add message when JavaScript is not enabled in webbrowser (#3388)
* Add build time setting of ButtonTopic and SwitchTopic (#3414)
* Add iFan02 Fanspeed + and Fanspeed - command options (#3415)
* Add Individual HSBColorX commands (#3430, #3615)
* Add output support on MCP23008/MCP23017 (#3436)
* Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466)
* Add RGB support for Domoticz (#3547)
* Add all ruletimer values to command RuleTimer result message (#3571)
* Add command Publish2 for publishing retained MQTT messages (#3593)
* Add commands ButtonDebounce 40..1000 and SwitchDebounce 40..1000 to have user control over debounce timing. Default is 50mS (#3594)
* Add RuleX debug options 8,9,10 (StopOnError) to control RuleX execution status after an exception restart (#3607)
* Add rule variables %sunrise%, %sunset%, %uptime% and %time% (#3608)
* Add optional MQTT_TELE_RETAIN to Energy Margins message (#3612, 3614)
* *
* 6.1.1 20180714 * 6.1.1 20180714
* Revert wifi changes (#3177) * Revert wifi changes (#3177)

View File

@ -39,7 +39,9 @@
#define D_JSON_BLOCKED_LOOP "Blocked Loop" #define D_JSON_BLOCKED_LOOP "Blocked Loop"
#define D_JSON_BOOTVERSION "Boot" #define D_JSON_BOOTVERSION "Boot"
#define D_JSON_BOOTCOUNT "BootCount" #define D_JSON_BOOTCOUNT "BootCount"
#define D_JSON_BSSID "BSSId"
#define D_JSON_BUILDDATETIME "BuildDateTime" #define D_JSON_BUILDDATETIME "BuildDateTime"
#define D_JSON_CHANNEL "Channel"
#define D_JSON_CO2 "CarbonDioxide" #define D_JSON_CO2 "CarbonDioxide"
#define D_JSON_COMMAND "Command" #define D_JSON_COMMAND "Command"
#define D_JSON_CONNECT_FAILED "Connect failed" #define D_JSON_CONNECT_FAILED "Connect failed"
@ -236,6 +238,7 @@
#define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALSEND "SerialSend"
#define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_SERIALDELIMITER "SerialDelimiter"
#define D_CMND_BAUDRATE "Baudrate" #define D_CMND_BAUDRATE "Baudrate"
#define D_LOG_SOME_SETTINGS_RESET "Some settings have been reset"
// Commands xdrv_01_mqtt.ino // Commands xdrv_01_mqtt.ino
#define D_CMND_MQTTHOST "MqttHost" #define D_CMND_MQTTHOST "MqttHost"

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele. * Use online command Prefix to translate cmnd, stat and tele.
* *
* Updated until v6.1.1.5 * Updated until v6.2.0.1
\*********************************************************************/ \*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -60,10 +60,12 @@
#define D_BLINKOFF "Мигане изкл." #define D_BLINKOFF "Мигане изкл."
#define D_BOOT_COUNT "Брой на стартиранията" #define D_BOOT_COUNT "Брой на стартиранията"
#define D_BRIGHTLIGHT "Яркост" #define D_BRIGHTLIGHT "Яркост"
#define D_BSSID "BSSId"
#define D_BUTTON "Бутон" #define D_BUTTON "Бутон"
#define D_BY "от" // Written by me #define D_BY "от" // Written by me
#define D_BYTES "Байта" #define D_BYTES "Байта"
#define D_CELSIUS "Целзий" #define D_CELSIUS "Целзий"
#define D_CHANNEL "Канал"
#define D_CO2 "Въглероден диоксид" #define D_CO2 "Въглероден диоксид"
#define D_CODE "код" // Button code #define D_CODE "код" // Button code
#define D_COLDLIGHT "Хладна" #define D_COLDLIGHT "Хладна"
@ -438,12 +440,12 @@
#define D_PARTICALS_BEYOND "Частици" #define D_PARTICALS_BEYOND "Частици"
// xsns_32_mpu6050.ino // xsns_32_mpu6050.ino
#define D_AX_AXIS "Accel. X-Axis" #define D_AX_AXIS "Ускорение - ос X"
#define D_AY_AXIS "Accel. Y-Axis" #define D_AY_AXIS "Ускорение - ос Y"
#define D_AZ_AXIS "Accel. Z-Axis" #define D_AZ_AXIS "Ускорение - ос Z"
#define D_GX_AXIS "Gyro X-Axis" #define D_GX_AXIS "Жироскоп - ос X"
#define D_GY_AXIS "Gyro Y-Axis" #define D_GY_AXIS "Жироскоп - ос Y"
#define D_GZ_AXIS "Gyro Z-Axis" #define D_GZ_AXIS "Жироскоп - ос Z"
// sonoff_template.h // sonoff_template.h
#define D_SENSOR_NONE "Няма" #define D_SENSOR_NONE "Няма"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "BlikáníVyp" #define D_BLINKOFF "BlikáníVyp"
#define D_BOOT_COUNT "Počítadlo spuštění" #define D_BOOT_COUNT "Počítadlo spuštění"
#define D_BRIGHTLIGHT "Světlý" #define D_BRIGHTLIGHT "Světlý"
#define D_BSSID "BSSId"
#define D_BUTTON "Tlačítko" #define D_BUTTON "Tlačítko"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "Bytů" #define D_BYTES "Bytů"
#define D_CELSIUS "°C" #define D_CELSIUS "°C"
#define D_CHANNEL "Channel"
#define D_CO2 "CO2" #define D_CO2 "CO2"
#define D_CODE "kód" // Button code #define D_CODE "kód" // Button code
#define D_COLDLIGHT "Studené světlo" #define D_COLDLIGHT "Studené světlo"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "BlinkenAus" #define D_BLINKOFF "BlinkenAus"
#define D_BOOT_COUNT "Anzahl Startvorgänge" #define D_BOOT_COUNT "Anzahl Startvorgänge"
#define D_BRIGHTLIGHT "hell" #define D_BRIGHTLIGHT "hell"
#define D_BSSID "BSSId"
#define D_BUTTON "Knopf" #define D_BUTTON "Knopf"
#define D_BY "von" // Written by me #define D_BY "von" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Kanal"
#define D_CO2 "CO²" #define D_CO2 "CO²"
#define D_CODE "code" // Button code #define D_CODE "code" // Button code
#define D_COLDLIGHT "kalt" #define D_COLDLIGHT "kalt"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "Δεν αναβοσβήνει" #define D_BLINKOFF "Δεν αναβοσβήνει"
#define D_BOOT_COUNT "Αριθμός εκκινήσεων" #define D_BOOT_COUNT "Αριθμός εκκινήσεων"
#define D_BRIGHTLIGHT "Λαμπερό" #define D_BRIGHTLIGHT "Λαμπερό"
#define D_BSSID "BSSId"
#define D_BUTTON "Κουμπί" #define D_BUTTON "Κουμπί"
#define D_BY "από" // Written by me #define D_BY "από" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Κελσίου" #define D_CELSIUS "Κελσίου"
#define D_CHANNEL "Channel"
#define D_CO2 "Διοξείδιο του άνθρακα" #define D_CO2 "Διοξείδιο του άνθρακα"
#define D_CODE "κώδικας" // Button code #define D_CODE "κώδικας" // Button code
#define D_COLDLIGHT "Ψυχρός" #define D_COLDLIGHT "Ψυχρός"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "BlinkOff" #define D_BLINKOFF "BlinkOff"
#define D_BOOT_COUNT "Boot Count" #define D_BOOT_COUNT "Boot Count"
#define D_BRIGHTLIGHT "Bright" #define D_BRIGHTLIGHT "Bright"
#define D_BSSID "BSSId"
#define D_BUTTON "Button" #define D_BUTTON "Button"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel"
#define D_CO2 "Carbon dioxide" #define D_CO2 "Carbon dioxide"
#define D_CODE "code" // Button code #define D_CODE "code" // Button code
#define D_COLDLIGHT "Cold" #define D_COLDLIGHT "Cold"

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele. * Use online command Prefix to translate cmnd, stat and tele.
* *
* Updated until v6.1.1c * Updated until v6.2.0.1
\*********************************************************************/ \*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -60,10 +60,12 @@
#define D_BLINKOFF "BlinkOff" #define D_BLINKOFF "BlinkOff"
#define D_BOOT_COUNT "Conteo Reinicios" #define D_BOOT_COUNT "Conteo Reinicios"
#define D_BRIGHTLIGHT "Brillante" #define D_BRIGHTLIGHT "Brillante"
#define D_BSSID "BSSId"
#define D_BUTTON "Botón" #define D_BUTTON "Botón"
#define D_BY "por" // Written by me #define D_BY "por" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Canal"
#define D_CO2 "CO2" #define D_CO2 "CO2"
#define D_CODE "código" // Button code #define D_CODE "código" // Button code
#define D_COLDLIGHT "Fría" #define D_COLDLIGHT "Fría"
@ -460,7 +462,7 @@
#define D_SENSOR_RELAY "Relé" // Suffix "1i" #define D_SENSOR_RELAY "Relé" // Suffix "1i"
#define D_SENSOR_LED "Led" // Suffix "1i" #define D_SENSOR_LED "Led" // Suffix "1i"
#define D_SENSOR_PWM "PWM" // Suffix "1" #define D_SENSOR_PWM "PWM" // Suffix "1"
#define D_SENSOR_COUNTER "Counter" // Suffix "1" #define D_SENSOR_COUNTER "Contador" // Suffix "1"
#define D_SENSOR_IRRECV "IR RX" #define D_SENSOR_IRRECV "IR RX"
#define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx" #define D_SENSOR_MHZ_TX "MHZ Tx"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "BlinkOff" #define D_BLINKOFF "BlinkOff"
#define D_BOOT_COUNT "Nombre de boot" #define D_BOOT_COUNT "Nombre de boot"
#define D_BRIGHTLIGHT "Luminosité" #define D_BRIGHTLIGHT "Luminosité"
#define D_BSSID "BSSId"
#define D_BUTTON "Bouton" #define D_BUTTON "Bouton"
#define D_BY "par" // Written by me #define D_BY "par" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel"
#define D_CO2 "Dioxyde de carbone" #define D_CO2 "Dioxyde de carbone"
#define D_CODE "code" // Button code #define D_CODE "code" // Button code
#define D_COLDLIGHT "Froid" #define D_COLDLIGHT "Froid"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "Villogás Ki" #define D_BLINKOFF "Villogás Ki"
#define D_BOOT_COUNT "Bootolások száma" #define D_BOOT_COUNT "Bootolások száma"
#define D_BRIGHTLIGHT "Max. fényerő" #define D_BRIGHTLIGHT "Max. fényerő"
#define D_BSSID "BSSId"
#define D_BUTTON "Gomb" #define D_BUTTON "Gomb"
#define D_BY "tőle:" // Written by me #define D_BY "tőle:" // Written by me
#define D_BYTES "Byte-ok" #define D_BYTES "Byte-ok"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel"
#define D_CO2 "Szén-dioxid" #define D_CO2 "Szén-dioxid"
#define D_CODE "kód" // Button code #define D_CODE "kód" // Button code
#define D_COLDLIGHT "Hideg" #define D_COLDLIGHT "Hideg"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "BlinkOff" #define D_BLINKOFF "BlinkOff"
#define D_BOOT_COUNT "Numero di boot" #define D_BOOT_COUNT "Numero di boot"
#define D_BRIGHTLIGHT "Luminoso" #define D_BRIGHTLIGHT "Luminoso"
#define D_BSSID "BSSId"
#define D_BUTTON "Pulsante" #define D_BUTTON "Pulsante"
#define D_BY "da" // Written by me #define D_BY "da" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel"
#define D_CO2 "CO2" #define D_CO2 "CO2"
#define D_CODE "codice" // Button code #define D_CODE "codice" // Button code
#define D_COLDLIGHT "Fredda" #define D_COLDLIGHT "Fredda"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "KnipperUit" #define D_BLINKOFF "KnipperUit"
#define D_BOOT_COUNT "Herstarts" #define D_BOOT_COUNT "Herstarts"
#define D_BRIGHTLIGHT "Fel" #define D_BRIGHTLIGHT "Fel"
#define D_BSSID "BSSId"
#define D_BUTTON "DrukKnop" #define D_BUTTON "DrukKnop"
#define D_BY "door" // Written by me #define D_BY "door" // Written by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Kanaal"
#define D_CO2 "Koolstofdioxide" #define D_CO2 "Koolstofdioxide"
#define D_CODE "code" // Button code #define D_CODE "code" // Button code
#define D_COLDLIGHT "Koud" #define D_COLDLIGHT "Koud"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "MiganieWył" #define D_BLINKOFF "MiganieWył"
#define D_BOOT_COUNT "Licznik uruchomienia" #define D_BOOT_COUNT "Licznik uruchomienia"
#define D_BRIGHTLIGHT "Jasny" #define D_BRIGHTLIGHT "Jasny"
#define D_BSSID "BSSId"
#define D_BUTTON "Przycisk" #define D_BUTTON "Przycisk"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "Bajtow" #define D_BYTES "Bajtow"
#define D_CELSIUS "Celsiusza" #define D_CELSIUS "Celsiusza"
#define D_CHANNEL "Channel"
#define D_CO2 "Dwutlenku węgla" #define D_CO2 "Dwutlenku węgla"
#define D_CODE "kod" // Button code #define D_CODE "kod" // Button code
#define D_COLDLIGHT "Zimny" #define D_COLDLIGHT "Zimny"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "Pulsar desligado" #define D_BLINKOFF "Pulsar desligado"
#define D_BOOT_COUNT "Contagem de inicialização" #define D_BOOT_COUNT "Contagem de inicialização"
#define D_BRIGHTLIGHT "Brilho" #define D_BRIGHTLIGHT "Brilho"
#define D_BSSID "BSSId"
#define D_BUTTON "Botão" #define D_BUTTON "Botão"
#define D_BY "por" // Write by me #define D_BY "por" // Write by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel"
#define D_CO2 "Dióxido de carbono" #define D_CO2 "Dióxido de carbono"
#define D_CODE "Código" // Button code #define D_CODE "Código" // Button code
#define D_COLDLIGHT "Luz fria" #define D_COLDLIGHT "Luz fria"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "Piscar desligado" #define D_BLINKOFF "Piscar desligado"
#define D_BOOT_COUNT "Contagem de Inicialização" #define D_BOOT_COUNT "Contagem de Inicialização"
#define D_BRIGHTLIGHT "Brilho" #define D_BRIGHTLIGHT "Brilho"
#define D_BSSID "BSSId"
#define D_BUTTON "Botão" #define D_BUTTON "Botão"
#define D_BY "por" // Write by me #define D_BY "por" // Write by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel"
#define D_CO2 "Dioxido de Carbono" #define D_CO2 "Dioxido de Carbono"
#define D_CODE "Código" // Button code #define D_CODE "Código" // Button code
#define D_COLDLIGHT "Luz Fria" #define D_COLDLIGHT "Luz Fria"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "Не Мигать" #define D_BLINKOFF "Не Мигать"
#define D_BOOT_COUNT "Количество загрузок" #define D_BOOT_COUNT "Количество загрузок"
#define D_BRIGHTLIGHT "Яркость" #define D_BRIGHTLIGHT "Яркость"
#define D_BSSID "BSSId"
#define D_BUTTON "Кнопка" #define D_BUTTON "Кнопка"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "Байт" #define D_BYTES "Байт"
#define D_CELSIUS "Цельсия" #define D_CELSIUS "Цельсия"
#define D_CHANNEL "Channel"
#define D_CO2 "Углекислый газ" #define D_CO2 "Углекислый газ"
#define D_CODE "код" // Button code #define D_CODE "код" // Button code
#define D_COLDLIGHT "Холодный" #define D_COLDLIGHT "Холодный"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "BlinkOff" #define D_BLINKOFF "BlinkOff"
#define D_BOOT_COUNT "Yeniden başlama sayısı" #define D_BOOT_COUNT "Yeniden başlama sayısı"
#define D_BRIGHTLIGHT "Işık" #define D_BRIGHTLIGHT "Işık"
#define D_BSSID "BSSId"
#define D_BUTTON "Buton" #define D_BUTTON "Buton"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "Bayt" #define D_BYTES "Bayt"
#define D_CELSIUS "Derece" #define D_CELSIUS "Derece"
#define D_CHANNEL "Channel"
#define D_CO2 "Karbon dioksit" #define D_CO2 "Karbon dioksit"
#define D_CODE "kod" // Button code #define D_CODE "kod" // Button code
#define D_COLDLIGHT "Soğuk" #define D_COLDLIGHT "Soğuk"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "Не блимати" #define D_BLINKOFF "Не блимати"
#define D_BOOT_COUNT "Кіл-сть завант." #define D_BOOT_COUNT "Кіл-сть завант."
#define D_BRIGHTLIGHT "Яскравість" #define D_BRIGHTLIGHT "Яскравість"
#define D_BSSID "BSSId"
#define D_BUTTON "Кнопка" #define D_BUTTON "Кнопка"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "Байт" #define D_BYTES "Байт"
#define D_CELSIUS "Цельсія" #define D_CELSIUS "Цельсія"
#define D_CHANNEL "Channel"
#define D_CO2 "Вуглек. газ" #define D_CO2 "Вуглек. газ"
#define D_CODE "код" // Button code #define D_CODE "код" // Button code
#define D_COLDLIGHT "Холодний" #define D_COLDLIGHT "Холодний"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "闪烁关" #define D_BLINKOFF "闪烁关"
#define D_BOOT_COUNT "启动次数" #define D_BOOT_COUNT "启动次数"
#define D_BRIGHTLIGHT "亮" #define D_BRIGHTLIGHT "亮"
#define D_BSSID "BSSId"
#define D_BUTTON "按钮" #define D_BUTTON "按钮"
#define D_BY "汉化: killadm 作者:" // Written by me #define D_BY "汉化: killadm 作者:" // Written by me
#define D_BYTES "大小:" #define D_BYTES "大小:"
#define D_CELSIUS "摄氏" #define D_CELSIUS "摄氏"
#define D_CHANNEL "Channel"
#define D_CO2 "二氧化碳" #define D_CO2 "二氧化碳"
#define D_CODE "代码" // Button code #define D_CODE "代码" // Button code
#define D_COLDLIGHT "冷" #define D_COLDLIGHT "冷"

View File

@ -60,10 +60,12 @@
#define D_BLINKOFF "閃爍關" #define D_BLINKOFF "閃爍關"
#define D_BOOT_COUNT "啟動次數" #define D_BOOT_COUNT "啟動次數"
#define D_BRIGHTLIGHT "亮度" #define D_BRIGHTLIGHT "亮度"
#define D_BSSID "BSSId"
#define D_BUTTON "按鈕" #define D_BUTTON "按鈕"
#define D_BY "by" // Written by me #define D_BY "by" // Written by me
#define D_BYTES "大小:" #define D_BYTES "大小:"
#define D_CELSIUS "攝氏" #define D_CELSIUS "攝氏"
#define D_CHANNEL "Channel"
#define D_CO2 "二氧化碳" #define D_CO2 "二氧化碳"
#define D_CODE "代碼" // Button code #define D_CODE "代碼" // Button code
#define D_COLDLIGHT "冷" #define D_COLDLIGHT "冷"

View File

@ -94,7 +94,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t spare28 : 1; uint32_t spare28 : 1;
uint32_t spare29 : 1; uint32_t spare29 : 1;
uint32_t spare30 : 1; uint32_t spare30 : 1;
uint32_t spare31 : 1; uint32_t user_esp8285_enable : 1; // bit 31 (v6.1.1.14)
}; };
} SysBitfield3; } SysBitfield3;
@ -341,7 +341,10 @@ struct RTCMEM {
unsigned long energy_kWhtotal; // 008 unsigned long energy_kWhtotal; // 008
unsigned long pulse_counter[MAX_COUNTERS]; // 00C unsigned long pulse_counter[MAX_COUNTERS]; // 00C
power_t power; // 01C power_t power; // 01C
// 020 next free location uint16_t extended_valid; // 020 Extended valid flag (v6.1.1.14)
uint8_t fast_reboot_count; // 022
uint8_t free_023[57]; // 023
// 05C next free location (64 (=core) + 100 (=tasmota offset) + 92 (=0x5C RTCMEM struct) = 256 bytes (max = 512))
} RtcSettings; } RtcSettings;
struct TIME_T { struct TIME_T {

View File

@ -84,6 +84,7 @@ void RtcSettingsSave()
{ {
if (GetRtcSettingsCrc() != rtc_settings_crc) { if (GetRtcSettingsCrc() != rtc_settings_crc) {
RtcSettings.valid = RTC_MEM_VALID; RtcSettings.valid = RTC_MEM_VALID;
RtcSettings.extended_valid = RTC_MEM_VALID;
ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM));
rtc_settings_crc = GetRtcSettingsCrc(); rtc_settings_crc = GetRtcSettingsCrc();
#ifdef DEBUG_THEO #ifdef DEBUG_THEO
@ -103,12 +104,14 @@ void RtcSettingsLoad()
if (RtcSettings.valid != RTC_MEM_VALID) { if (RtcSettings.valid != RTC_MEM_VALID) {
memset(&RtcSettings, 0, sizeof(RTCMEM)); memset(&RtcSettings, 0, sizeof(RTCMEM));
RtcSettings.valid = RTC_MEM_VALID; RtcSettings.valid = RTC_MEM_VALID;
RtcSettings.extended_valid = RTC_MEM_VALID;
RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday;
RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal;
for (byte i = 0; i < MAX_COUNTERS; i++) { for (byte i = 0; i < MAX_COUNTERS; i++) {
RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; RtcSettings.pulse_counter[i] = Settings.pulse_counter[i];
} }
RtcSettings.power = Settings.power; RtcSettings.power = Settings.power;
// RtcSettings.fast_reboot_count = 0; // Explicit by memset
RtcSettingsSave(); RtcSettingsSave();
} }
rtc_settings_crc = GetRtcSettingsCrc(); rtc_settings_crc = GetRtcSettingsCrc();
@ -119,6 +122,11 @@ boolean RtcSettingsValid()
return (RTC_MEM_VALID == RtcSettings.valid); return (RTC_MEM_VALID == RtcSettings.valid);
} }
boolean RtcSettingsExtendedValid()
{
return (RTC_MEM_VALID == RtcSettings.extended_valid);
}
/*********************************************************************************************\ /*********************************************************************************************\
* Config - Flash * Config - Flash
\*********************************************************************************************/ \*********************************************************************************************/

View File

@ -85,6 +85,7 @@ typedef unsigned long power_t; // Power (Relay) type
#define STATES 20 // Number of states per second using 50 mSec interval #define STATES 20 // Number of states per second using 50 mSec interval
#define IMMINENT_RESET_FACTOR 10 // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 #define IMMINENT_RESET_FACTOR 10 // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40
#define BOOT_LOOP_TIME 10 // Number of seconds to stop detecting boot loops
#define SYSLOG_TIMER 600 // Seconds to restore syslog_level #define SYSLOG_TIMER 600 // Seconds to restore syslog_level
#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog #define SERIALLOG_TIMER 600 // Seconds to disable SerialLog
#define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware #define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware

View File

@ -442,7 +442,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
ShowFreeMem(PSTR("MqttDataHandler")); ShowFreeMem(PSTR("MqttDataHandler"));
strncpy(topicBuf, topic, sizeof(topicBuf)); strlcpy(topicBuf, topic, sizeof(topicBuf));
for (i = 0; i < data_len; i++) { for (i = 0; i < data_len; i++) {
if (!isspace(data[i])) break; if (!isspace(data[i])) break;
} }
@ -1532,8 +1532,8 @@ void MqttShowState()
MqttShowPWMState(); MqttShowPWMState();
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d}}"),
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str()); mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()));
} }
boolean MqttShowSensor() boolean MqttShowSensor()
@ -1567,6 +1567,11 @@ void PerformEverySecond()
{ {
uptime++; uptime++;
if (BOOT_LOOP_TIME == uptime) {
RtcSettings.fast_reboot_count = 0;
RtcSettingsSave();
}
if ((4 == uptime) && (SONOFF_IFAN02 == Settings.module)) { // Microcontroller needs 3 seconds before accepting commands if ((4 == uptime) && (SONOFF_IFAN02 == Settings.module)) { // Microcontroller needs 3 seconds before accepting commands
SetDevicePower(1, SRC_RETRY); // Sync with default power on state microcontroller being Light ON and Fan OFF SetDevicePower(1, SRC_RETRY); // Sync with default power on state microcontroller being Light ON and Fan OFF
SetDevicePower(power, SRC_RETRY); // Set required power on state SetDevicePower(power, SRC_RETRY); // Set required power on state
@ -2313,7 +2318,7 @@ void GpioInit()
pin[i] = 99; pin[i] = 99;
} }
for (byte i = 0; i < MAX_GPIO_PIN; i++) { for (byte i = 0; i < MAX_GPIO_PIN; i++) {
mpin = my_module.gp.io[i]; mpin = ValidGPIO(i, my_module.gp.io[i]);
// snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin);
// AddLog(LOG_LEVEL_DEBUG); // AddLog(LOG_LEVEL_DEBUG);
@ -2323,7 +2328,7 @@ void GpioInit()
bitSet(switch_no_pullup, mpin - GPIO_SWT1_NP); bitSet(switch_no_pullup, mpin - GPIO_SWT1_NP);
mpin -= (GPIO_SWT1_NP - GPIO_SWT1); mpin -= (GPIO_SWT1_NP - GPIO_SWT1);
} }
if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) {
bitSet(key_no_pullup, mpin - GPIO_KEY1_NP); bitSet(key_no_pullup, mpin - GPIO_KEY1_NP);
mpin -= (GPIO_KEY1_NP - GPIO_KEY1); mpin -= (GPIO_KEY1_NP - GPIO_KEY1);
} }
@ -2486,6 +2491,11 @@ void setup()
{ {
byte idx; byte idx;
RtcSettingsLoad();
if (!RtcSettingsExtendedValid()) { RtcSettings.fast_reboot_count = 0; }
RtcSettings.fast_reboot_count++;
RtcSettingsSave();
Serial.begin(baudrate); Serial.begin(baudrate);
delay(10); delay(10);
Serial.println(); Serial.println();
@ -2517,11 +2527,29 @@ void setup()
save_data_counter = Settings.save_data; save_data_counter = Settings.save_data;
sleep = Settings.sleep; sleep = Settings.sleep;
if ((resetInfo.reason == REASON_WDT_RST) || (resetInfo.reason == REASON_EXCEPTION_RST) || (resetInfo.reason == REASON_SOFT_WDT_RST) || OsWatchBlockedLoop()) { // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts)
if (RtcSettings.fast_reboot_count > 1) { // Restart twice
Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI
if (RtcSettings.fast_reboot_count > 2) { // Restart 3 times
for (byte i = 0; i < MAX_RULE_SETS; i++) { for (byte i = 0; i < MAX_RULE_SETS; i++) {
if (bitRead(Settings.rule_stop, i)) { bitWrite(Settings.rule_enabled, i, 0); } if (bitRead(Settings.rule_stop, i)) {
bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop
} }
} }
}
if (RtcSettings.fast_reboot_count > 3) { // Restarted 4 times
Settings.rule_enabled = 0; // Disable all rules
}
if (RtcSettings.fast_reboot_count > 4) { // Restarted 5 times
Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic
Settings.last_module = SONOFF_BASIC;
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors
}
}
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcSettings.fast_reboot_count);
AddLog(LOG_LEVEL_DEBUG);
}
Settings.bootcount++; Settings.bootcount++;
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount);

View File

@ -136,6 +136,9 @@ enum ProgramSelectablePins {
GPIO_DI, // my92x1 PWM input GPIO_DI, // my92x1 PWM input
GPIO_DCKI, // my92x1 CLK input GPIO_DCKI, // my92x1 CLK input
GPIO_ARIRFRCV, // AliLux RF Receive input GPIO_ARIRFRCV, // AliLux RF Receive input
GPIO_MCP39_TX, // MCP39F501 Serial output
GPIO_MCP39_RX, // MCP39F501 Serial input
GPIO_MCP39_RST, // MCP39F501 Serial reset
GPIO_USER, // User configurable GPIO_USER, // User configurable
GPIO_MAX }; GPIO_MAX };
@ -220,13 +223,15 @@ enum SupportedModules {
SONOFF_POW_R2, SONOFF_POW_R2,
SONOFF_IFAN02, SONOFF_IFAN02,
BLITZWOLF_BWSHP2, BLITZWOLF_BWSHP2,
SHELLY1,
SHELLY2,
MAXMODULE }; MAXMODULE };
/********************************************************************************************/ /********************************************************************************************/
#define MAX_GPIO_PIN 18 // Number of supported GPIO #define MAX_GPIO_PIN 18 // Number of supported GPIO
const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcontrolD6D7D5D8D0A0"; const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0";
typedef struct MYIO { typedef struct MYIO {
uint8_t io[MAX_GPIO_PIN]; uint8_t io[MAX_GPIO_PIN];
@ -271,6 +276,8 @@ const uint8_t kNiceList[MAXMODULE] PROGMEM = {
LUANIHVIO, LUANIHVIO,
YUNSHAN, YUNSHAN,
WION, WION,
SHELLY1,
SHELLY2,
BLITZWOLF_BWSHP2, BLITZWOLF_BWSHP2,
H801, H801,
MAGICHOME, MAGICHOME,
@ -514,7 +521,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor
GPIO_USER, // GPIO04 D2 Wemos I2C SDA GPIO_USER, // GPIO04 D2 Wemos I2C SDA
GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield
0, 0, 0, 0, 0, 0, // Flash connection 0, 0, 0, // Flash connection
GPIO_USER, // Flash connection or GPIO09 on ESP8285 only!
GPIO_USER, // Flash connection or GPIO10 on ESP8285 only!
0, // Flash connection
GPIO_USER, // GPIO12 D6 GPIO_USER, // GPIO12 D6
GPIO_USER, // GPIO13 D7 GPIO_USER, // GPIO13 D7
GPIO_USER, // GPIO14 D5 GPIO_USER, // GPIO14 D5
@ -903,6 +913,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_HLW_CF1, // GPIO14 BL0937 or HJL-01 CF1 voltage / current GPIO_HLW_CF1, // GPIO14 BL0937 or HJL-01 CF1 voltage / current
GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On) GPIO_REL1, // GPIO15 Relay (0 = Off, 1 = On)
0, 0 0, 0
},
{ "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/
0, 0, 0, 0,
GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On)
GPIO_SWT1_NP, // GPIO05 SW pin
0, 0, 0, 0, 0, 0, // Flash connection
0, 0, 0, 0, 0, 0
},
{ "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/
0,
GPIO_MCP39_RX, // GPIO01 MCP39F501 Serial input
0,
GPIO_MCP39_TX, // GPIO03 MCP39F501 Serial output
GPIO_REL1, // GPIO04
GPIO_REL2, // GPIO05
0, 0, 0, 0, 0, 0, // Flash connection
GPIO_SWT1_NP, // GPIO12
0,
GPIO_SWT2_NP, // GPIO14
GPIO_MCP39_RST, // GPIO15 MCP39F501 Reset
0, 0
} }
}; };
@ -985,8 +1016,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_USER, // GPIO15 (D15) GPIO_USER, // GPIO15 (D15)
GPIO_USER, // GPIO16 (D16) GPIO_USER, // GPIO16 (D16)
0 // ADC0 Analog input (A0) 0 // ADC0 Analog input (A0)
}, }
*/ */
#endif // _SONOFF_TEMPLATE_H_ #endif // _SONOFF_TEMPLATE_H_

View File

@ -20,7 +20,7 @@
#ifndef _SONOFF_VERSION_H_ #ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_
#define VERSION 0x0601010D #define VERSION 0x06020001
#define D_PROGRAMNAME "Sonoff-Tasmota" #define D_PROGRAMNAME "Sonoff-Tasmota"
#define D_AUTHOR "Theo Arends" #define D_AUTHOR "Theo Arends"

View File

@ -143,7 +143,7 @@ char* subStr(char* dest, char* str, const char *delim, int index)
int i; int i;
// Since strtok consumes the first arg, make a copy // Since strtok consumes the first arg, make a copy
strncpy(dest, str, strlen(str)); strlcpy(dest, str, strlen(str));
for (i = 1, act = dest; i <= index; i++, act = NULL) { for (i = 1, act = dest; i <= index; i++, act = NULL) {
sub = strtok_r(act, delim, &ptr); sub = strtok_r(act, delim, &ptr);
if (sub == NULL) break; if (sub == NULL) break;
@ -157,7 +157,7 @@ double CharToDouble(char *str)
// simple ascii to double, because atof or strtod are too large // simple ascii to double, because atof or strtod are too large
char strbuf[24]; char strbuf[24];
strcpy(strbuf, str); strlcpy(strbuf, str, sizeof(strbuf));
char *pt; char *pt;
double left = atoi(strbuf); double left = atoi(strbuf);
double right = 0; double right = 0;
@ -561,13 +561,13 @@ int GetStateNumber(char *state_text)
char command[CMDSZ]; char command[CMDSZ];
int state_number = -1; int state_number = -1;
if ((GetCommandCode(command, sizeof(command), state_text, kOptionOff) >= 0) || !strcasecmp(state_text, Settings.state_text[0])) { if (GetCommandCode(command, sizeof(command), state_text, kOptionOff) >= 0) {
state_number = 0; state_number = 0;
} }
else if ((GetCommandCode(command, sizeof(command), state_text, kOptionOn) >= 0) || !strcasecmp(state_text, Settings.state_text[1])) { else if (GetCommandCode(command, sizeof(command), state_text, kOptionOn) >= 0) {
state_number = 1; state_number = 1;
} }
else if ((GetCommandCode(command, sizeof(command), state_text, kOptionToggle) >= 0) || !strcasecmp(state_text, Settings.state_text[2])) { else if (GetCommandCode(command, sizeof(command), state_text, kOptionToggle) >= 0) {
state_number = 2; state_number = 2;
} }
else if (GetCommandCode(command, sizeof(command), state_text, kOptionBlink) >= 0) { else if (GetCommandCode(command, sizeof(command), state_text, kOptionBlink) >= 0) {
@ -717,6 +717,15 @@ void ShowSource(int source)
} }
} }
uint8_t ValidGPIO(uint8_t pin, uint8_t gpio)
{
uint8_t result = gpio;
if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) {
if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } // Disable possible flash GPIO9 and GPIO10
}
return result;
}
/*********************************************************************************************\ /*********************************************************************************************\
* Sleep aware time scheduler functions borrowed from ESPEasy * Sleep aware time scheduler functions borrowed from ESPEasy
\*********************************************************************************************/ \*********************************************************************************************/

View File

@ -301,11 +301,11 @@
// #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code) // #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code)
// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) // #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code)
// #define USE_DISPLAY // Add I2C Display Support for LCD, Oled and up to eigth Matrices (+19k code) // #define USE_DISPLAY // Add I2C Display Support (+2k code)
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
#define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) #define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) (+6k code)
#define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) #define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) (+16k code)
#define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) #define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) (+11k code)
#define MTX_ADDRESS1 0x71 // [DisplayAddress1] I2C address of first 8x8 matrix module #define MTX_ADDRESS1 0x71 // [DisplayAddress1] I2C address of first 8x8 matrix module
#define MTX_ADDRESS2 0x74 // [DisplayAddress2] I2C address of second 8x8 matrix module #define MTX_ADDRESS2 0x74 // [DisplayAddress2] I2C address of second 8x8 matrix module
#define MTX_ADDRESS3 0x75 // [DisplayAddress3] I2C address of third 8x8 matrix module #define MTX_ADDRESS3 0x75 // [DisplayAddress3] I2C address of third 8x8 matrix module
@ -324,9 +324,8 @@
#ifndef USE_DISPLAY #ifndef USE_DISPLAY
#define USE_DISPLAY // Add SPI Display support for 320x240 and 480x320 TFT #define USE_DISPLAY // Add SPI Display support for 320x240 and 480x320 TFT
#endif #endif
#define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display (+19k code)
// #define USE_DISPLAY_EPAPER // [DisplayModel 5] Enable e-paper display // #define USE_DISPLAY_EPAPER // [DisplayModel 5] Enable e-paper display (+19k code)
#endif // USE_SPI #endif // USE_SPI
// -- Serial sensors ------------------------------ // -- Serial sensors ------------------------------
@ -367,30 +366,15 @@
//#define USE_DEBUG_DRIVER // Use xdrv_99_debug.ino providing commands CpuChk, CfgXor, CfgDump, CfgPeek and CfgPoke //#define USE_DEBUG_DRIVER // Use xdrv_99_debug.ino providing commands CpuChk, CfgXor, CfgDump, CfgPeek and CfgPoke
/*********************************************************************************************\ /*********************************************************************************************\
* Select features and sensors enabled in previous version saving space * Optional firmware configurations
* Select none or just one for optional features and sensors as configured in sonoff_post.h
* See RELEASENOTES.md for selected features
\*********************************************************************************************/ \*********************************************************************************************/
//#define USE_CLASSIC // Create sonoff-classic (See sonoff_post.h for selected features) //#define USE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager
//#define USE_SENSORS // Create sonoff-sensors with useful sensors enabled
/*********************************************************************************************\ //#define USE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation
* Select useful sensors - overrides above undefines!! //#define BE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC
\*********************************************************************************************/
//#define USE_SENSORS // Create sonoff-sensors with useful sensors enabled (See sonoff_post.h for selected sensors)
/*********************************************************************************************\
* Select KNX without Emulation to save space
\*********************************************************************************************/
//#define USE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation (See sonoff_post.h)
/*********************************************************************************************\
* Compile a minimal version if upgrade memory gets tight ONLY TO BE USED FOR UPGRADE STEP 1!
* To be used as step 1 during upgrade.
* Step 2 is re-compile with option BE_MINIMAL commented out.
\*********************************************************************************************/
//#define BE_MINIMAL // Minimal version if upgrade memory gets tight (-45k code, -2k mem)
/*********************************************************************************************\ /*********************************************************************************************\
* No user configurable items below * No user configurable items below

View File

@ -254,7 +254,7 @@ const char HTTP_FORM_MODULE[] PROGMEM =
"<input id='w' name='w' value='6,1' hidden>" "<input id='w' name='w' value='6,1' hidden>"
"<br/><b>" D_MODULE_TYPE "</b> ({mt)<br/><select id='g99' name='g99'></select><br/>"; "<br/><b>" D_MODULE_TYPE "</b> ({mt)<br/><select id='g99' name='g99'></select><br/>";
const char HTTP_LNK_ITEM[] PROGMEM = const char HTTP_LNK_ITEM[] PROGMEM =
"<div><a href='#p' onclick='c(this)'>{v}</a>&nbsp;<span class='q'>{i} {r}%</span></div>"; "<div><a href='#p' onclick='c(this)'>{v}</a>&nbsp;({w})&nbsp<span class='q'>{i} {r}%</span></div>";
const char HTTP_LNK_SCAN[] PROGMEM = const char HTTP_LNK_SCAN[] PROGMEM =
"<div><a href='/w1'>" D_SCAN_FOR_WIFI_NETWORKS "</a></div><br/>"; "<div><a href='/w1'>" D_SCAN_FOR_WIFI_NETWORKS "</a></div><br/>";
const char HTTP_FORM_WIFI[] PROGMEM = const char HTTP_FORM_WIFI[] PROGMEM =
@ -372,8 +372,8 @@ long ajax_token = 1;
static void WebGetArg(const char* arg, char* out, size_t max) static void WebGetArg(const char* arg, char* out, size_t max)
{ {
String s = WebServer->arg(arg); String s = WebServer->arg(arg);
strncpy(out, s.c_str(), max); strlcpy(out, s.c_str(), max);
out[max-1] = '\0'; // Ensure terminating NUL // out[max-1] = '\0'; // Ensure terminating NUL
} }
void ShowWebSource(int source) void ShowWebSource(int source)
@ -789,7 +789,7 @@ void HandleModuleConfiguration()
page += FPSTR(HTTP_SCRIPT_MODULE3); page += FPSTR(HTTP_SCRIPT_MODULE3);
for (byte i = 0; i < MAX_GPIO_PIN; i++) { for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (GPIO_USER == cmodule.gp.io[i]) { if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16
page += mqtt_data; page += mqtt_data;
} }
@ -803,10 +803,10 @@ void HandleModuleConfiguration()
page.replace(F("{mt"), stemp); page.replace(F("{mt"), stemp);
page += F("<br/><table>"); page += F("<br/><table>");
for (byte i = 0; i < MAX_GPIO_PIN; i++) { for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (GPIO_USER == cmodule.gp.io[i]) { if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(stemp, 3, PINS_WEMOS +i*2);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:146px'><select id='g%d' name='g%d'></select></td></tr>"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:146px'><select id='g%d' name='g%d'></select></td></tr>"),
(WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "<font color='red'>ESP8285</font>" :(10==i)? "<font color='red'>ESP8285</font>" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i);
page += mqtt_data; page += mqtt_data;
} }
} }
@ -882,7 +882,7 @@ void HandleWifi(boolean scan)
//display networks in page //display networks in page
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (-1 == indices[i]) { continue; } // skip dups if (-1 == indices[i]) { continue; } // skip dups
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.RSSI(indices[i])); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i]));
AddLog(LOG_LEVEL_DEBUG); AddLog(LOG_LEVEL_DEBUG);
int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i]));
@ -891,6 +891,7 @@ void HandleWifi(boolean scan)
String rssiQ; String rssiQ;
rssiQ += quality; rssiQ += quality;
item.replace(F("{v}"), WiFi.SSID(indices[i])); item.replace(F("{v}"), WiFi.SSID(indices[i]));
item.replace(F("{w}"), String(WiFi.channel(indices[i])));
item.replace(F("{r}"), rssiQ); item.replace(F("{r}"), rssiQ);
uint8_t auth = WiFi.encryptionType(indices[i]); uint8_t auth = WiFi.encryptionType(indices[i]);
item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F(""));

View File

@ -455,6 +455,9 @@ boolean TimerCommand()
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.flag3.timers_enable = XdrvMailbox.payload; Settings.flag3.timers_enable = XdrvMailbox.payload;
} }
if (XdrvMailbox.payload == 2) {
Settings.flag3.timers_enable = !Settings.flag3.timers_enable;
}
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable)); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable));

View File

@ -89,7 +89,6 @@ char **disp_log_buffer;
uint8_t disp_log_buffer_cols = 0; uint8_t disp_log_buffer_cols = 0;
uint8_t disp_log_buffer_idx = 0; uint8_t disp_log_buffer_idx = 0;
uint8_t disp_log_buffer_ptr = 0; uint8_t disp_log_buffer_ptr = 0;
bool disp_log_buffer_active = false;
char **disp_screen_buffer; char **disp_screen_buffer;
uint8_t disp_screen_buffer_cols = 0; uint8_t disp_screen_buffer_cols = 0;
@ -534,6 +533,15 @@ void DisplayReAllocScreenBuffer()
DisplayAllocScreenBuffer(); DisplayAllocScreenBuffer();
} }
void DisplayFillScreen(uint8_t line)
{
byte len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]);
if (len) {
memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len);
disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0;
}
}
/*-------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------*/
void DisplayClearLogBuffer() void DisplayClearLogBuffer()
@ -582,55 +590,47 @@ void DisplayReAllocLogBuffer()
DisplayAllocLogBuffer(); DisplayAllocLogBuffer();
} }
/*-------------------------------------------------------------------------------------------*/ void DisplayLogBufferAdd(char* txt)
void DisplayLogBufferIdxInc()
{ {
if (disp_log_buffer_cols) {
strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); // This preserves the % sign where printf won't
disp_log_buffer_idx++; disp_log_buffer_idx++;
if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; }
disp_log_buffer_idx = 0;
} }
} }
void DisplayLogBufferPtrInc() char* DisplayLogBuffer(char temp_code)
{ {
char* result = NULL;
if (disp_log_buffer_cols) {
if (disp_log_buffer_idx != disp_log_buffer_ptr) {
result = disp_log_buffer[disp_log_buffer_ptr];
disp_log_buffer_ptr++; disp_log_buffer_ptr++;
if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; }
disp_log_buffer_ptr = 0;
}
}
/* char *pch = strchr(result, '~'); // = 0x7E (~) Replace degrees character (276 octal)
void DisplayPrintLog() if (pch != NULL) { result[pch - result] = temp_code; }
{
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
if (disp_log_buffer_active) {
XdspPrintLog(disp_log_buffer[disp_log_buffer_ptr]);
DisplayLogBufferPtrInc();
} }
} }
return result;
} }
*/
void DisplayLogBufferInit() void DisplayLogBufferInit()
{ {
if (Settings.display_mode) { if (Settings.display_mode) {
disp_log_buffer_idx = 0; disp_log_buffer_idx = 0;
disp_log_buffer_ptr = 0; disp_log_buffer_ptr = 0;
disp_log_buffer_active = false;
disp_refresh = Settings.display_refresh; disp_refresh = Settings.display_refresh;
snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit());
// DisplayReAllocLogBuffer(); DisplayReAllocLogBuffer();
snprintf_P(disp_log_buffer[disp_log_buffer_idx], disp_log_buffer_cols, PSTR(D_VERSION " %s"), my_version); char buffer[20];
DisplayLogBufferIdxInc(); snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s"), my_version);
snprintf_P(disp_log_buffer[disp_log_buffer_idx], disp_log_buffer_cols, PSTR("Display mode %d"), Settings.display_mode); DisplayLogBufferAdd(buffer);
DisplayLogBufferIdxInc(); snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode);
DisplayLogBufferAdd(buffer);
} }
} }
@ -668,6 +668,7 @@ const char kSensorQuantity[] PROGMEM =
void DisplayJsonValue(const char *topic, const char* device, const char* mkey, const char* value) void DisplayJsonValue(const char *topic, const char* device, const char* mkey, const char* value)
{ {
char quantity[TOPSZ]; char quantity[TOPSZ];
char buffer[Settings.display_cols[0] +1];
char spaces[Settings.display_cols[0]]; char spaces[Settings.display_cols[0]];
char source[Settings.display_cols[0] - Settings.display_cols[1]]; char source[Settings.display_cols[0] - Settings.display_cols[1]];
char svalue[Settings.display_cols[1] +1]; char svalue[Settings.display_cols[1] +1];
@ -718,12 +719,12 @@ void DisplayJsonValue(const char *topic, const char* device, const char* mkey, c
else if (JSON_CO2 == quantity_code) { else if (JSON_CO2 == quantity_code) {
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value);
} }
snprintf_P(disp_log_buffer[disp_log_buffer_idx], disp_log_buffer_cols, PSTR("%s %s"), source, svalue); snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue);
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "mkey [%s], source [%s], value [%s], quantity_code %d, log_buffer [%s]"), mkey, source, value, quantity_code, disp_log_buffer[disp_log_buffer_idx]); // snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "mkey [%s], source [%s], value [%s], quantity_code %d, log_buffer [%s]"), mkey, source, value, quantity_code, buffer);
// AddLog(LOG_LEVEL_DEBUG); // AddLog(LOG_LEVEL_DEBUG);
DisplayLogBufferIdxInc(); DisplayLogBufferAdd(buffer);
} }
void DisplayAnalyzeJson(char *topic, char *json) void DisplayAnalyzeJson(char *topic, char *json)
@ -856,7 +857,6 @@ void DisplayInitDriver()
#ifndef USE_DISPLAY_MODES1TO5 #ifndef USE_DISPLAY_MODES1TO5
Settings.display_mode = 0; Settings.display_mode = 0;
#else #else
DisplayAllocLogBuffer();
DisplayLogBufferInit(); DisplayLogBufferInit();
#endif // USE_DISPLAY_MODES1TO5 #endif // USE_DISPLAY_MODES1TO5
} }
@ -981,8 +981,7 @@ boolean DisplayCommand()
if (!Settings.display_mode) { if (!Settings.display_mode) {
DisplayText(); DisplayText();
} else { } else {
strlcpy(disp_log_buffer[disp_log_buffer_idx], XdrvMailbox.data, disp_log_buffer_cols); DisplayLogBufferAdd(XdrvMailbox.data);
DisplayLogBufferIdxInc();
} }
#endif // USE_DISPLAY_MODES1TO5 #endif // USE_DISPLAY_MODES1TO5
} else { } else {
@ -1006,22 +1005,23 @@ boolean DisplayCommand()
} }
else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) {
Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
#ifdef USE_DISPLAY_MODES1TO5 #ifdef USE_DISPLAY_MODES1TO5
if ((1 == XdrvMailbox.index) && (Settings.display_cols[0] != XdrvMailbox.payload)) { if (1 == XdrvMailbox.index) {
DisplayLogBufferInit(); DisplayLogBufferInit();
DisplayReAllocScreenBuffer(); DisplayReAllocScreenBuffer();
} }
#endif // USE_DISPLAY_MODES1TO5 #endif // USE_DISPLAY_MODES1TO5
Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]);
} }
else if (CMND_DISP_ROWS == command_code) { else if (CMND_DISP_ROWS == command_code) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) {
#ifdef USE_DISPLAY_MODES1TO5
if (Settings.display_rows != XdrvMailbox.payload) { DisplayReAllocScreenBuffer(); }
#endif // USE_DISPLAY_MODES1TO5
Settings.display_rows = XdrvMailbox.payload; Settings.display_rows = XdrvMailbox.payload;
#ifdef USE_DISPLAY_MODES1TO5
DisplayLogBufferInit();
DisplayReAllocScreenBuffer();
#endif // USE_DISPLAY_MODES1TO5
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows);
} }

View File

@ -107,16 +107,22 @@ void LcdCenter(byte row, char* txt)
line[Settings.display_cols[0]] = 0; line[Settings.display_cols[0]] = 0;
len = strlen(txt); len = strlen(txt);
offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0; offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0;
strncpy(line +offset, txt, len); strlcpy(line +offset, txt, len);
lcd->setCursor(0, row); lcd->setCursor(0, row);
lcd->print(line); lcd->print(line);
} }
void LcdPrintLogLine() boolean LcdPrintLog()
{ {
if (!disp_screen_buffer_cols) { boolean result = false;
DisplayAllocScreenBuffer();
} else { disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\337');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1; uint8_t last_row = Settings.display_rows -1;
for (byte i = 0; i < last_row; i++) { for (byte i = 0; i < last_row; i++) {
@ -124,39 +130,19 @@ void LcdPrintLogLine()
lcd->setCursor(0, i); // Col 0, Row i lcd->setCursor(0, i); // Col 0, Row i
lcd->print(disp_screen_buffer[i +1]); lcd->print(disp_screen_buffer[i +1]);
} }
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal) DisplayFillScreen(last_row);
if (pch != NULL) {
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\337'; // = 0xDF
}
strlcpy(disp_screen_buffer[last_row], disp_log_buffer[disp_log_buffer_ptr], disp_screen_buffer_cols);
// Fill with spaces
byte len = disp_screen_buffer_cols - strlen(disp_screen_buffer[last_row]);
if (len) {
memset(disp_screen_buffer[last_row] + strlen(disp_screen_buffer[last_row]), 0x20, len);
disp_screen_buffer[last_row][disp_screen_buffer_cols -1] = 0;
}
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]);
AddLog(LOG_LEVEL_DEBUG); AddLog(LOG_LEVEL_DEBUG);
lcd->setCursor(0, last_row); lcd->setCursor(0, last_row);
lcd->print(disp_screen_buffer[last_row]); lcd->print(disp_screen_buffer[last_row]);
}
}
void LcdPrintLog() result = true;
{
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
if (disp_log_buffer_active) {
LcdPrintLogLine();
DisplayLogBufferPtrInc();
} }
} }
return result;
} }
void LcdTime() void LcdTime()
@ -182,10 +168,7 @@ void LcdRefresh() // Every second
break; break;
case 3: // Local case 3: // Local
case 5: { // Mqtt case 5: { // Mqtt
LcdPrintLog(); if (!LcdPrintLog()) { LcdTime(); }
if (!disp_log_buffer_active) {
LcdTime();
}
break; break;
} }
} }

View File

@ -133,11 +133,15 @@ void Ssd1306OnOff()
#ifdef USE_DISPLAY_MODES1TO5 #ifdef USE_DISPLAY_MODES1TO5
void Ssd1306PrintLogLine() void Ssd1306PrintLog()
{ {
if (!disp_screen_buffer_cols) { disp_refresh--;
DisplayAllocScreenBuffer(); if (!disp_refresh) {
} else { disp_refresh = Settings.display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1; uint8_t last_row = Settings.display_rows -1;
oled->clearDisplay(); oled->clearDisplay();
@ -147,39 +151,15 @@ void Ssd1306PrintLogLine()
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
oled->println(disp_screen_buffer[i]); oled->println(disp_screen_buffer[i]);
} }
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal) DisplayFillScreen(last_row);
if (pch != NULL) {
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8
}
strlcpy(disp_screen_buffer[last_row], disp_log_buffer[disp_log_buffer_ptr], disp_screen_buffer_cols);
// Fill with spaces
byte len = disp_screen_buffer_cols - strlen(disp_screen_buffer[last_row]);
if (len) {
memset(disp_screen_buffer[last_row] + strlen(disp_screen_buffer[last_row]), 0x20, len);
disp_screen_buffer[last_row][disp_screen_buffer_cols -1] = 0;
}
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]);
AddLog(LOG_LEVEL_DEBUG); AddLog(LOG_LEVEL_DEBUG);
oled->println(disp_screen_buffer[last_row]); oled->println(disp_screen_buffer[last_row]);
oled->display(); oled->display();
} }
}
void Ssd1306PrintLog()
{
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
if (disp_log_buffer_active) {
Ssd1306PrintLogLine();
DisplayLogBufferPtrInc();
}
} }
} }

View File

@ -39,6 +39,7 @@ int16_t mtx_y = 0;
char mtx_buffer[MTX_MAX_SCREEN_BUFFER]; char mtx_buffer[MTX_MAX_SCREEN_BUFFER];
uint8_t mtx_mode = 0; uint8_t mtx_mode = 0;
uint8_t mtx_loop = 0; uint8_t mtx_loop = 0;
uint8_t mtx_done = 0;
/*********************************************************************************************/ /*********************************************************************************************/
@ -109,9 +110,7 @@ void MatrixScrollLeft(char* txt, int loop)
// Move text position left by 1 pixel. // Move text position left by 1 pixel.
mtx_x--; mtx_x--;
int16_t len = strlen(txt); int16_t len = strlen(txt);
if (mtx_x < -(len *6)) { if (mtx_x < -(len *6)) { mtx_state = loop; }
mtx_state = loop;
}
} }
break; break;
} }
@ -159,9 +158,7 @@ void MatrixScrollUp(char* txt, int loop)
mtx_y--; // Move text position up by 1 pixel. mtx_y--; // Move text position up by 1 pixel.
mtx_counter = STATES * 1; // Hold text for 1 seconds mtx_counter = STATES * 1; // Hold text for 1 seconds
} }
if (mtx_y < -(wordcounter *8)) { if (mtx_y < -(wordcounter *8)) { mtx_state = loop; }
mtx_state = loop;
}
} }
break; break;
} }
@ -220,16 +217,14 @@ void MatrixInitDriver()
void MatrixOnOff() void MatrixOnOff()
{ {
if (!disp_power) { if (!disp_power) { MatrixClear(); }
MatrixClear();
}
} }
void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
{ {
snprintf(mtx_buffer, sizeof(mtx_buffer), str); snprintf(mtx_buffer, sizeof(mtx_buffer), str);
mtx_mode = x; mtx_mode = x &1; // Use x for selecting scroll up (0) or scroll left (1)
mtx_loop = y; mtx_loop = y &1; // Use y for selecting no loop (0) or loop (1)
if (!mtx_state) { mtx_state = 1; } if (!mtx_state) { mtx_state = 1; }
} }
@ -237,40 +232,36 @@ void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8
#ifdef USE_DISPLAY_MODES1TO5 #ifdef USE_DISPLAY_MODES1TO5
void MatrixBufferScroll(uint8_t direction) void MatrixPrintLog(uint8_t direction)
{ {
if (disp_log_buffer_idx != disp_log_buffer_ptr) { char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer;
if (!mtx_state) { if (txt != NULL) {
mtx_state = 1; if (!mtx_state) { mtx_state = 1; }
}
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal) if (!mtx_done) {
if (pch != NULL) {
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8
}
if (direction) {
MatrixScrollUp(disp_log_buffer[disp_log_buffer_ptr], 0);
} else {
// Remove extra spaces // Remove extra spaces
uint8_t space = 0; uint8_t space = 0;
uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER;
mtx_buffer[0] = '\0'; mtx_buffer[0] = '\0';
for (byte i = 0; i < max_cols; i++) { for (byte i = 0; i < max_cols; i++) {
if (disp_log_buffer[disp_log_buffer_ptr][i] == ' ') { if (txt[i] == ' ') {
space++; space++;
} else { } else {
space = 0; space = 0;
} }
if (space < 2) { if (space < 2) {
strncat(mtx_buffer, (const char*)disp_log_buffer[disp_log_buffer_ptr] +i, 1); strncat(mtx_buffer, (const char*)txt +i, 1);
} }
} }
mtx_done = 1;
}
if (direction) {
MatrixScrollUp(mtx_buffer, 0);
} else {
MatrixScrollLeft(mtx_buffer, 0); MatrixScrollLeft(mtx_buffer, 0);
} }
if (!mtx_state) { if (!mtx_state) { mtx_done = 0; }
DisplayLogBufferPtrInc();
}
} else { } else {
char disp_time[9]; // 13:45:43 char disp_time[9]; // 13:45:43
@ -310,11 +301,11 @@ void MatrixRefresh() // Every second
break; break;
} }
case 4: case 4:
MatrixBufferScroll(0); MatrixPrintLog(0);
break; break;
case 1: // Time and user text case 1: // Time and user text
case 5: // Time, user text and MQTT case 5: // Time, user text and MQTT
MatrixBufferScroll(1); MatrixPrintLog(1);
break; break;
#endif // USE_DISPLAY_MODES1TO5 #endif // USE_DISPLAY_MODES1TO5
} }

View File

@ -54,7 +54,7 @@ void Ili9341InitMode()
tft->setCursor(0, 0); tft->setCursor(0, 0);
tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
tft->setTextSize(2); tft->setTextSize(2);
tft->println("HEADER"); // tft->println("HEADER");
tft_scroll = TFT_TOP; tft_scroll = TFT_TOP;
} }
@ -65,6 +65,11 @@ void Ili9341Init(uint8_t mode)
switch(mode) { switch(mode) {
case DISPLAY_INIT_MODE: case DISPLAY_INIT_MODE:
Ili9341InitMode(); Ili9341InitMode();
#ifdef USE_DISPLAY_MODES1TO5
if (Settings.display_rotate) {
DisplayClearScreenBuffer();
}
#endif // USE_DISPLAY_MODES1TO5
break; break;
case DISPLAY_INIT_PARTIAL: case DISPLAY_INIT_PARTIAL:
case DISPLAY_INIT_FULL: case DISPLAY_INIT_FULL:
@ -82,6 +87,12 @@ void Ili9341InitDriver()
tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]);
tft->begin(); tft->begin();
#ifdef USE_DISPLAY_MODES1TO5
if (Settings.display_rotate) {
DisplayAllocScreenBuffer();
}
#endif // USE_DISPLAY_MODES1TO5
Ili9341InitMode(); Ili9341InitMode();
} }
} }
@ -126,41 +137,49 @@ void Ili9341OnOff()
#ifdef USE_DISPLAY_MODES1TO5 #ifdef USE_DISPLAY_MODES1TO5
void Ili9341PrintLogLine()
{
tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); // Add background color to solve flicker
tft->setCursor(0, tft_scroll);
byte size = Settings.display_size;
tft->setTextSize(size);
uint16_t theight = size * TFT_FONT_HEIGTH;
tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); // Erase line
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal)
if (pch != NULL) {
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8
}
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), disp_log_buffer[disp_log_buffer_ptr]);
AddLog(LOG_LEVEL_DEBUG);
tft->print(disp_log_buffer[disp_log_buffer_ptr]);
tft_scroll += theight;
if (tft_scroll >= (tft->height() - TFT_BOTTOM)) {
tft_scroll = TFT_TOP;
}
tft->scrollTo(tft_scroll);
}
void Ili9341PrintLog() void Ili9341PrintLog()
{ {
disp_refresh--; disp_refresh--;
if (!disp_refresh) { if (!disp_refresh) {
disp_refresh = Settings.display_refresh; disp_refresh = Settings.display_refresh;
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr); if (Settings.display_rotate) {
if (disp_log_buffer_active) { if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
Ili9341PrintLogLine(); }
DisplayLogBufferPtrInc();
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
byte size = Settings.display_size;
uint16_t theight = size * TFT_FONT_HEIGTH;
tft->setTextSize(size);
tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); // Add background color to solve flicker
if (!Settings.display_rotate) { // Use hardware scroll
tft->setCursor(0, tft_scroll);
tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); // Erase line
tft->print(txt);
tft_scroll += theight;
if (tft_scroll >= (tft->height() - TFT_BOTTOM)) {
tft_scroll = TFT_TOP;
}
tft->scrollTo(tft_scroll);
} else {
uint8_t last_row = Settings.display_rows -1;
tft_scroll = theight; // Start below header
tft->setCursor(0, tft_scroll);
for (byte i = 0; i < last_row; i++) {
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
// tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); // Erase line
tft->print(disp_screen_buffer[i]);
tft_scroll += theight;
tft->setCursor(0, tft_scroll);
}
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
DisplayFillScreen(last_row);
tft->print(disp_screen_buffer[last_row]);
}
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), txt);
AddLog(LOG_LEVEL_DEBUG);
} }
} }
} }
@ -168,17 +187,21 @@ void Ili9341PrintLog()
void Ili9341Refresh() // Every second void Ili9341Refresh() // Every second
{ {
if (Settings.display_mode) { // Mode 0 is User text if (Settings.display_mode) { // Mode 0 is User text
char tftdt[21]; char tftdt[Settings.display_cols[0] +1];
char disp_time[9]; // 13:45:43 char date4[11]; // 24-04-2017
char disp_date4[11]; // 24-04-2017 char space[Settings.display_cols[0] - 17];
char time[9]; // 13:45:43
snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
snprintf_P(disp_date4, sizeof(disp_date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year);
tft->setTextSize(2); tft->setTextSize(2);
tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); // Add background color to solve flicker tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); // Add background color to solve flicker
tft->setCursor(0, 0); tft->setCursor(0, 0);
snprintf_P(tftdt, sizeof(tftdt), PSTR("%s %s"), disp_date4, disp_time);
snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year);
memset(space, 0x20, sizeof(space));
space[sizeof(space) -1] = '\0';
snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time);
tft->print(tftdt); tft->print(tftdt);
switch (Settings.display_mode) { switch (Settings.display_mode) {

View File

@ -386,12 +386,18 @@ void HandleUpnpEvent()
String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP); String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP);
//differentiate get and set state //differentiate get and set state
if (request.indexOf(F("SetBinaryState")) > 0) { if (request.indexOf(F("SetBinaryState")) > 0) {
uint8_t power = POWER_TOGGLE;
if (request.indexOf(F("State>1</Binary")) > 0) { if (request.indexOf(F("State>1</Binary")) > 0) {
ExecuteCommandPower(devices_present, POWER_ON, SRC_WEMO); power = POWER_ON;
} }
else if (request.indexOf(F("State>0</Binary")) > 0) { else if (request.indexOf(F("State>0</Binary")) > 0) {
ExecuteCommandPower(devices_present, POWER_OFF, SRC_WEMO); power = POWER_OFF;
} }
if (power != POWER_TOGGLE) {
uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1
ExecuteCommandPower(device, power, SRC_WEMO);
}
} }
else if(request.indexOf(F("GetBinaryState")) > 0){ else if(request.indexOf(F("GetBinaryState")) > 0){
state_xml.replace(F("Set"), F("Get")); state_xml.replace(F("Set"), F("Get"));

View File

@ -111,7 +111,7 @@ void CounterShow(boolean json)
} }
header++; header++;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"C%d\":%s"), mqtt_data, stemp, i +1, counter); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"C%d\":%s"), mqtt_data, stemp, i +1, counter);
strcpy(stemp, ","); strlcpy(stemp, ",", sizeof(stemp));
#ifdef USE_DOMOTICZ #ifdef USE_DOMOTICZ
if ((0 == tele_period) && (1 == dsxflg)) { if ((0 == tele_period) && (1 == dsxflg)) {
DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]);

View File

@ -186,7 +186,7 @@ void Ds18x20Show(boolean json)
dsxflg++; dsxflg++;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"),
mqtt_data, stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); mqtt_data, stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature);
strcpy(stemp, ","); strlcpy(stemp, ",", sizeof(stemp));
#ifdef USE_DOMOTICZ #ifdef USE_DOMOTICZ
if ((0 == tele_period) && (1 == dsxflg)) { if ((0 == tele_period) && (1 == dsxflg)) {
DomoticzSensor(DZ_TEMP, temperature); DomoticzSensor(DZ_TEMP, temperature);

View File

@ -191,7 +191,7 @@ void Ads1115Show(boolean json)
} }
dsxflg++; dsxflg++;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value);
strcpy(stemp, ","); strlcpy(stemp, ",", sizeof(stemp));
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} else { } else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value);

View File

@ -111,7 +111,7 @@ void Ads1115Show(boolean json)
} }
dsxflg++; dsxflg++;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value);
strcpy(stemp, ","); strlcpy(stemp, ",", sizeof(stemp));
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} else { } else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value);

View File

@ -54,6 +54,9 @@
#define APDS9960_CHIPID_1 0xAB #define APDS9960_CHIPID_1 0xAB
#define APDS9960_CHIPID_2 0x9C #define APDS9960_CHIPID_2 0x9C
#define APDS9930_CHIPID_1 0x12 // we will check, if someone got an incorrect sensor
#define APDS9930_CHIPID_2 0x39 // there are case reports about "accidentially bought" 9930's
/* Gesture parameters */ /* Gesture parameters */
#define GESTURE_THRESHOLD_OUT 10 #define GESTURE_THRESHOLD_OUT 10
#define GESTURE_SENSITIVITY_1 50 #define GESTURE_SENSITIVITY_1 50
@ -75,7 +78,9 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "%s"
"{s}" "Red" "{m}%s{e}" "{s}" "Red" "{m}%s{e}"
"{s}" "Green" "{m}%s{e}" "{s}" "Green" "{m}%s{e}"
"{s}" "Blue" "{m}%s{e}" "{s}" "Blue" "{m}%s{e}"
"{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" "{s}" "Ambient" "{m}%s{e}"
"{s}" "Illuminance" "{m}%s " D_UNIT_LUX "{e}"
"{s}" "CCT" "{m}%s " "K" "{e}" // calculated color temperature in Kelvin
"{s}" "Proximity" "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr> "{s}" "Proximity" "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
@ -207,7 +212,7 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "%s"
#define DEFAULT_ATIME 219 // 103ms #define DEFAULT_ATIME 219 // 103ms
#define DEFAULT_WTIME 246 // 27ms #define DEFAULT_WTIME 246 // 27ms
#define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses #define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses
#define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses #define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses ---89
#define DEFAULT_POFFSET_UR 0 // 0 offset #define DEFAULT_POFFSET_UR 0 // 0 offset
#define DEFAULT_POFFSET_DL 0 // 0 offset #define DEFAULT_POFFSET_DL 0 // 0 offset
#define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor #define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor
@ -225,8 +230,8 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "%s"
#define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode #define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode
#define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit #define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit
#define DEFAULT_GGAIN GGAIN_4X #define DEFAULT_GGAIN GGAIN_4X
#define DEFAULT_GLDRIVE LED_DRIVE_100MA #define DEFAULT_GLDRIVE LED_DRIVE_100MA // default 100ma
#define DEFAULT_GWTIME GWTIME_2_8MS #define DEFAULT_GWTIME GWTIME_2_8MS // default 2_8MS
#define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode #define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode
#define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses #define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses
#define DEFAULT_GCONF3 0 // All photodiodes active during gesture #define DEFAULT_GCONF3 0 // All photodiodes active during gesture
@ -271,6 +276,19 @@ typedef struct gesture_data_type {
int16_t gesture_state_ = 0; int16_t gesture_state_ = 0;
int16_t gesture_motion_ = DIR_NONE; int16_t gesture_motion_ = DIR_NONE;
typedef struct color_data_type {
uint16_t a; // measured ambient
uint16_t r;
uint16_t g;
uint16_t b;
uint8_t p; // proximity
uint16_t cct; // calculated color temperature
uint16_t lux; // calculated illuminance - atm only from rgb
} color_data_type;
color_data_type color_data;
/******************************************************************************* /*******************************************************************************
* Helper functions * Helper functions
******************************************************************************/ ******************************************************************************/
@ -299,6 +317,7 @@ typedef struct gesture_data_type {
* @param[in] len number of bytes to read * @param[in] len number of bytes to read
* @return Number of bytes read. -1 on read error. * @return Number of bytes read. -1 on read error.
*/ */
int8_t wireReadDataBlock( uint8_t reg, int8_t wireReadDataBlock( uint8_t reg,
uint8_t *val, uint8_t *val,
uint16_t len) uint16_t len)
@ -323,6 +342,51 @@ int8_t wireReadDataBlock( uint8_t reg,
return i; return i;
} }
/**
* Taken from the Adafruit-library
* @brief Converts the raw R/G/B values to color temperature in degrees
* Kelvin
*/
void calculateColorTemperature()
{
float X, Y, Z; /* RGB to XYZ correlation */
float xc, yc; /* Chromaticity co-ordinates */
float n; /* McCamy's formula */
float cct;
/* 1. Map RGB values to their XYZ counterparts. */
/* Based on 6500K fluorescent, 3000K fluorescent */
/* and 60W incandescent values for a wide range. */
/* Note: Y = Illuminance or lux */
X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b);
Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); // this is Lux
Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b);
/* 2. Calculate the chromaticity co-ordinates */
xc = (X) / (X + Y + Z);
yc = (Y) / (X + Y + Z);
/* 3. Use McCamy's formula to determine the CCT */
n = (xc - 0.3320F) / (0.1858F - yc);
/* Calculate the final CCT */
color_data.cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F;
color_data.lux = Y; // according to Adafruit code comments this seems to be not a perfect solution
return;
}
/**
* Taken from the Adafruit-Library
* @brief Implements missing powf function
*/
float powf(const float x, const float y)
{
return (float)(pow((double)x, (double)y));
}
/******************************************************************************* /*******************************************************************************
* Getters and setters for register values * Getters and setters for register values
******************************************************************************/ ******************************************************************************/
@ -1260,6 +1324,8 @@ bool APDS9960_init()
setGestureIntEnable(DEFAULT_GIEN); setGestureIntEnable(DEFAULT_GIEN);
disablePower(); // go to sleep
return true; return true;
} }
/******************************************************************************* /*******************************************************************************
@ -1318,20 +1384,13 @@ void setMode(uint8_t mode, uint8_t enable)
/** /**
* @brief Starts the light (R/G/B/Ambient) sensor on the APDS-9960 * @brief Starts the light (R/G/B/Ambient) sensor on the APDS-9960
* *
* @param[in] interrupts true to enable hardware interrupt on high or low light * no interrupts
*/ */
void enableLightSensor(bool interrupts) void enableLightSensor()
{ {
/* Set default gain, interrupts, enable power, and enable sensor */ /* Set default gain, interrupts, enable power, and enable sensor */
setAmbientLightGain(DEFAULT_AGAIN); setAmbientLightGain(DEFAULT_AGAIN);
if( interrupts ) {
setAmbientLightIntEnable(1) ;
}
else {
setAmbientLightIntEnable(0); setAmbientLightIntEnable(0);
}
enablePower() ; enablePower() ;
setMode(AMBIENT_LIGHT, 1) ; setMode(AMBIENT_LIGHT, 1) ;
} }
@ -1349,18 +1408,14 @@ void disableLightSensor()
/** /**
* @brief Starts the proximity sensor on the APDS-9960 * @brief Starts the proximity sensor on the APDS-9960
* *
* @param[in] interrupts true to enable hardware external interrupt on proximity * no interrupts
*/ */
void enableProximitySensor(bool interrupts) void enableProximitySensor()
{ {
/* Set default gain, LED, interrupts, enable power, and enable sensor */ /* Set default gain, LED, interrupts, enable power, and enable sensor */
setProximityGain(DEFAULT_PGAIN); setProximityGain(DEFAULT_PGAIN);
setLEDDrive(DEFAULT_LDRIVE) ; setLEDDrive(DEFAULT_LDRIVE) ;
if( interrupts ) {
setProximityIntEnable(1) ;
} else {
setProximityIntEnable(0) ; setProximityIntEnable(0) ;
}
enablePower(); enablePower();
setMode(PROXIMITY, 1) ; setMode(PROXIMITY, 1) ;
} }
@ -1378,26 +1433,22 @@ void disableProximitySensor()
/** /**
* @brief Starts the gesture recognition engine on the APDS-9960 * @brief Starts the gesture recognition engine on the APDS-9960
* *
* @param[in] interrupts true to enable hardware external interrupt on gesture * no interrupts
*/ */
void enableGestureSensor(bool interrupts) void enableGestureSensor()
{ {
/* Enable gesture mode /* Enable gesture mode
Set ENABLE to 0 (power off) Set ENABLE to 0 (power off)
Set WTIME to 0xFF Set WTIME to 0xFF
Set AUX to LED_BOOST_300 Set AUX to LED_BOOST_300
Enable PON, WEN, PEN, GEN in ENABLE Enable PON, WEN, PEN, GEN in ENABLE
*/ */
resetGestureParameters(); resetGestureParameters();
I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ;
I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ;
setLEDBoost(LED_BOOST_100); // tip from jonn26 - 100 for 300 setLEDBoost(LED_BOOST_100); // tip from jonn26 - 100 for 300 ---- 200 from Adafruit
if( interrupts ) {
setGestureIntEnable(1) ;
} else {
setGestureIntEnable(0) ; setGestureIntEnable(0) ;
}
setGestureMode(1); setGestureMode(1);
enablePower() ; enablePower() ;
setMode(WAIT, 1) ; setMode(WAIT, 1) ;
@ -1482,11 +1533,6 @@ int16_t readGesture()
/* Read the current FIFO level */ /* Read the current FIFO level */
fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ;
#if DEBUG
Serial.print("FIFO Level: ");
Serial.println(fifo_level);
#endif
/* If there's stuff in the FIFO, read it into our data block */ /* If there's stuff in the FIFO, read it into our data block */
if( fifo_level > 0) { if( fifo_level > 0) {
bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, bytes_read = wireReadDataBlock( APDS9960_GFIFO_U,
@ -1495,14 +1541,6 @@ int16_t readGesture()
if( bytes_read == -1 ) { if( bytes_read == -1 ) {
return ERROR; return ERROR;
} }
#if DEBUG
Serial.print("FIFO Dump: ");
for ( i = 0; i < bytes_read; i++ ) {
Serial.print(fifo_data[i]);
Serial.print(" ");
}
Serial.println();
#endif
/* If at least 1 set of data, sort the data into U/D/L/R */ /* If at least 1 set of data, sort the data into U/D/L/R */
if( bytes_read >= 4 ) { if( bytes_read >= 4 ) {
@ -1518,26 +1556,12 @@ int16_t readGesture()
gesture_data_.index++; gesture_data_.index++;
gesture_data_.total_gestures++; gesture_data_.total_gestures++;
} }
#if DEBUG
Serial.print("Up Data: ");
for ( i = 0; i < gesture_data_.total_gestures; i++ ) {
Serial.print(gesture_data_.u_data[i]);
Serial.print(" ");
}
Serial.println();
#endif
/* Filter and process gesture data. Decode near/far state */ /* Filter and process gesture data. Decode near/far state */
if( processGestureData() ) { if( processGestureData() ) {
if( decodeGesture() ) { if( decodeGesture() ) {
//***TODO: U-Turn Gestures //***TODO: U-Turn Gestures
#if DEBUG
//Serial.println(gesture_motion_);
#endif
} }
} }
/* Reset data */ /* Reset data */
gesture_data_.index = 0; gesture_data_.index = 0;
gesture_data_.total_gestures = 0; gesture_data_.total_gestures = 0;
@ -1549,10 +1573,6 @@ int16_t readGesture()
delay(FIFO_PAUSE_TIME); delay(FIFO_PAUSE_TIME);
decodeGesture(); decodeGesture();
motion = gesture_motion_; motion = gesture_motion_;
#if DEBUG
Serial.print("END: ");
Serial.println(gesture_motion_);
#endif
resetGestureParameters(); resetGestureParameters();
return motion; return motion;
} }
@ -1581,97 +1601,18 @@ void disablePower()
* Ambient light and color sensor controls * Ambient light and color sensor controls
******************************************************************************/ ******************************************************************************/
/** /**
* @brief Reads the ambient (clear) light level as a 16-bit value * @brief Reads the ARGB-Data and fills color_data
* *
* @param[out] val value of the light sensor.
*/ */
void readAmbientLight(uint16_t &val)
void readAllColorAndProximityData()
{ {
uint8_t val_byte; if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9))
val = 0; {
// not absolutely shure, if this is a correct way to do this, but it is very short
/* Read value from clear channel, low byte register */ // we fill the struct byte by byte
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CDATAL); }
val = val_byte;
/* Read value from clear channel, high byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CDATAH);
val = val + ((uint16_t)val_byte << 8);
}
/**
* @brief Reads the red light level as a 16-bit value
*
* @param[out] val value of the light sensor.
*/
void readRedLight(uint16_t &val)
{
uint8_t val_byte;
val = 0;
/* Read value from clear channel, low byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_RDATAL) ;
val = val_byte;
/* Read value from clear channel, high byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_RDATAH) ;
val = val + ((uint16_t)val_byte << 8);
}
/**
* @brief Reads the green light level as a 16-bit value
*
* @param[out] val value of the light sensor.
*/
void readGreenLight(uint16_t &val)
{
uint8_t val_byte;
val = 0;
/* Read value from clear channel, low byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GDATAL) ;
val = val_byte;
/* Read value from clear channel, high byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GDATAH) ;
val = val + ((uint16_t)val_byte << 8);
}
/**
* @brief Reads the red light level as a 16-bit value
*
* @param[out] val value of the light sensor.
*/
void readBlueLight(uint16_t &val)
{
uint8_t val_byte;
val = 0;
/* Read value from clear channel, low byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_BDATAL) ;
val = val_byte;
/* Read value from clear channel, high byte register */
val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_BDATAH) ;
val = val + ((uint16_t)val_byte << 8);
}
/*******************************************************************************
* Proximity sensor controls
******************************************************************************/
/**
* @brief Reads the proximity level as an 8-bit value
*
* @param[out] val value of the proximity sensor.
*/
void readProximity(uint8_t &val)
{
val = 0;
/* Read value from proximity data register */
val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PDATA) ;
} }
/******************************************************************************* /*******************************************************************************
@ -1751,17 +1692,7 @@ bool processGestureData()
} }
/* Find the last value in U/D/L/R above the threshold */ /* Find the last value in U/D/L/R above the threshold */
for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) {
#if DEBUG
Serial.print(F("Finding last: "));
Serial.print(F("U:"));
Serial.print(gesture_data_.u_data[i]);
Serial.print(F(" D:"));
Serial.print(gesture_data_.d_data[i]);
Serial.print(F(" L:"));
Serial.print(gesture_data_.l_data[i]);
Serial.print(F(" R:"));
Serial.println(gesture_data_.r_data[i]);
#endif
if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
(gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
(gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
@ -1782,52 +1713,14 @@ bool processGestureData()
ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last);
lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last);
#if DEBUG
Serial.print(F("Last Values: "));
Serial.print(F("U:"));
Serial.print(u_last);
Serial.print(F(" D:"));
Serial.print(d_last);
Serial.print(F(" L:"));
Serial.print(l_last);
Serial.print(F(" R:"));
Serial.println(r_last);
Serial.print(F("Ratios: "));
Serial.print(F("UD Fi: "));
Serial.print(ud_ratio_first);
Serial.print(F(" UD La: "));
Serial.print(ud_ratio_last);
Serial.print(F(" LR Fi: "));
Serial.print(lr_ratio_first);
Serial.print(F(" LR La: "));
Serial.println(lr_ratio_last);
#endif
/* Determine the difference between the first and last ratios */ /* Determine the difference between the first and last ratios */
ud_delta = ud_ratio_last - ud_ratio_first; ud_delta = ud_ratio_last - ud_ratio_first;
lr_delta = lr_ratio_last - lr_ratio_first; lr_delta = lr_ratio_last - lr_ratio_first;
#if DEBUG
Serial.print("Deltas: ");
Serial.print("UD: ");
Serial.print(ud_delta);
Serial.print(" LR: ");
Serial.println(lr_delta);
#endif
/* Accumulate the UD and LR delta values */ /* Accumulate the UD and LR delta values */
gesture_ud_delta_ += ud_delta; gesture_ud_delta_ += ud_delta;
gesture_lr_delta_ += lr_delta; gesture_lr_delta_ += lr_delta;
#if DEBUG
Serial.print("Accumulations: ");
Serial.print("UD: ");
Serial.print(gesture_ud_delta_);
Serial.print(" LR: ");
Serial.println(gesture_lr_delta_);
#endif
/* Determine U/D gesture */ /* Determine U/D gesture */
if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) {
gesture_ud_count_ = 1; gesture_ud_count_ = 1;
@ -1845,15 +1738,6 @@ bool processGestureData()
} else { } else {
gesture_lr_count_ = 0; gesture_lr_count_ = 0;
} }
#if DEBUG
Serial.print("UD_CT: ");
Serial.print(gesture_ud_count_);
Serial.print(" LR_CT: ");
Serial.print(gesture_lr_count_);
Serial.println("----------");
#endif
return false; return false;
} }
@ -1955,7 +1839,7 @@ void APDS9960_loop()
recovery_loop_counter -= 1; recovery_loop_counter -= 1;
} }
if (recovery_loop_counter == 1 && APDS9960_overload){ //restart sensor just before the end of recovery from long press if (recovery_loop_counter == 1 && APDS9960_overload){ //restart sensor just before the end of recovery from long press
enableGestureSensor(false); enableGestureSensor();
APDS9960_overload = false; APDS9960_overload = false;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Gesture\":\"On\"}")); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Gesture\":\"On\"}"));
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again
@ -1994,12 +1878,20 @@ bool APDS9960_detect(void)
if (APDS9960_init()) { if (APDS9960_init()) {
success = true; success = true;
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "APDS9960 initialized")); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "APDS9960 initialized"));
enableGestureSensor(false); enableProximitySensor();
enableGestureSensor();
} }
} else { }
else {
if (APDS9960type == APDS9930_CHIPID_1 || APDS9960type == APDS9930_CHIPID_2) {
snprintf_P(log_data, sizeof(log_data), PSTR("APDS9930 found at address 0x%x, unsupported chip"), APDS9960_I2C_ADDR);
AddLog(LOG_LEVEL_DEBUG);
}
else{
snprintf_P(log_data, sizeof(log_data), PSTR("APDS9960 not found at address 0x%x"), APDS9960_I2C_ADDR); snprintf_P(log_data, sizeof(log_data), PSTR("APDS9960 not found at address 0x%x"), APDS9960_I2C_ADDR);
AddLog(LOG_LEVEL_DEBUG); AddLog(LOG_LEVEL_DEBUG);
} }
}
currentGesture[0] = '\0'; currentGesture[0] = '\0';
return success; return success;
} }
@ -2013,33 +1905,34 @@ void APDS9960_show(boolean json)
if (!APDS9960type) { if (!APDS9960type) {
return; return;
} }
if (!gesture_mode) { if (!gesture_mode && !APDS9960_overload) {
char red_chr[10]; char red_chr[10];
char green_chr[10]; char green_chr[10];
char blue_chr[10]; char blue_chr[10];
char ambient_chr[10]; char ambient_chr[10];
char illuminance_chr[10];
char cct_chr[10];
char prox_chr[10]; char prox_chr[10];
uint16_t val;
uint8_t val_prox;
readRedLight(val); readAllColorAndProximityData();
sprintf (red_chr, "%u", val); sprintf (ambient_chr, "%u", color_data.a);
readGreenLight(val); sprintf (red_chr, "%u", color_data.r);
sprintf (green_chr, "%u", val); sprintf (green_chr, "%u", color_data.g);
readBlueLight(val); sprintf (blue_chr, "%u", color_data.b );
sprintf (blue_chr, "%u", val ); sprintf (prox_chr, "%u", color_data.p );
readAmbientLight(val);
sprintf (ambient_chr, "%u", val); calculateColorTemperature(); // and calculate Lux
sprintf (cct_chr, "%u", color_data.cct);
sprintf (illuminance_chr, "%u", color_data.lux);
readProximity(val_prox);
sprintf (prox_chr, "%u", val_prox );
if (json) { if (json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"Proximity\":%s}"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"Illuminance\":%s,\"CCT\":%s,\"Proximity\":%s}"),
mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, prox_chr); mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, illuminance_chr, cct_chr, prox_chr);
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} else { } else {
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_APDS_9960_SNS, mqtt_data, red_chr, green_chr, blue_chr, ambient_chr, prox_chr ); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_APDS_9960_SNS, mqtt_data, red_chr, green_chr, blue_chr, ambient_chr, illuminance_chr, cct_chr, prox_chr );
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
} }
} }
@ -2069,14 +1962,23 @@ bool APDS9960CommandSensor()
case 0: // Off case 0: // Off
disableGestureSensor(); disableGestureSensor();
gesture_mode = 0; gesture_mode = 0;
enableLightSensor(false); enableLightSensor();
enableProximitySensor(false); APDS9960_overload = false; // prevent unwanted re-enabling
break; break;
case 1: // On case 1: // On with default gain of 4x
if (APDS9960type) { if (APDS9960type) {
setGestureGain(DEFAULT_GGAIN);
setProximityGain(DEFAULT_PGAIN);
disableLightSensor(); disableLightSensor();
disableProximitySensor(); enableGestureSensor();
enableGestureSensor(false); gesture_mode = 1;
}
case 2:
if (APDS9960type) {
setGestureGain(GGAIN_2X);
setProximityGain(PGAIN_2X);
disableLightSensor();
enableGestureSensor();
gesture_mode = 1; gesture_mode = 1;
} }
} }