Merge branch 'arendst/development' into development

This commit is contained in:
reloxx13 2018-06-28 20:43:52 +02:00
commit 6b1bfb3774
31 changed files with 2553 additions and 83 deletions

View File

@ -182,7 +182,7 @@ People helping to keep the show on the road:
- Pete Ba for more user friendly energy monitor calibration - Pete Ba for more user friendly energy monitor calibration
- Lobradov providing compile optimization tips - Lobradov providing compile optimization tips
- Flexiti for his initial timer implementation - Flexiti for his initial timer implementation
- reloxx13 for his [SonWeb](https://github.com/reloxx13/SonWEB) management tool - reloxx13 for his [TasmoAdmin](https://github.com/reloxx13/TasmoAdmin) management tool
- Joachim Banzhaf for his TSL2561 library and driver - Joachim Banzhaf for his TSL2561 library and driver
- Gijs Noorlander for his MHZ19 and SenseAir drivers - Gijs Noorlander for his MHZ19 and SenseAir drivers
- Emontnemery for his HomeAssistant Discovery concept and many code tuning tips - Emontnemery for his HomeAssistant Discovery concept and many code tuning tips

View File

@ -1,4 +1,10 @@
/* 6.0.0a /* 6.0.0b
* Add experimental (untested) TM1638 switch support (#2226)
* Change number of switches from 4 to 8 (#2885, #3086)
*
* 6.0.0a
* Add support for APDS9960 proximity sensor (#3051)
* Add increment and decrement value to command Counter (#2838)
* Add option 0 to command Timers disarming all timers (#2962) * Add option 0 to command Timers disarming all timers (#2962)
* Add time in minutes to rule Time#Initialized, Time#set and Time#Minute (#2669) * Add time in minutes to rule Time#Initialized, Time#set and Time#Minute (#2669)
* Add rule variables %time% for minutes since midnight, %uptime%, %sunrise% and %sunset% giving time in minutes (#2669) * Add rule variables %time% for minutes since midnight, %uptime%, %sunrise% and %sunset% giving time in minutes (#2669)
@ -17,6 +23,7 @@
* Fix Pzem004T checksum error * Fix Pzem004T checksum error
* Fix KNX bug when doing reply of sensors values * Fix KNX bug when doing reply of sensors values
* Fix rules induced LWT message * Fix rules induced LWT message
* Fix possible wifi connection problem (#1366)
* *
* 5.14.0b * 5.14.0b
* Add Console Commands to send KNX Commands * Add Console Commands to send KNX Commands

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -321,10 +321,10 @@
#define D_UPLOAD_ERR_7 "Upload abgebrochen" #define D_UPLOAD_ERR_7 "Upload abgebrochen"
#define D_UPLOAD_ERR_8 "Datei ungültig" #define D_UPLOAD_ERR_8 "Datei ungültig"
#define D_UPLOAD_ERR_9 "Datei zu groß" #define D_UPLOAD_ERR_9 "Datei zu groß"
#define D_UPLOAD_ERR_10 "Failed to init RF chip" #define D_UPLOAD_ERR_10 "RF Chip init fehlgeschlagen"
#define D_UPLOAD_ERR_11 "Failed to erase RF chip" #define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip" #define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERR_13 "RF Firmware ungültig"
#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" #define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer"
#define D_ENTER_COMMAND "Befehl eingeben" #define D_ENTER_COMMAND "Befehl eingeben"
@ -387,25 +387,25 @@
#define D_TIMER_ACTION "Aktion" #define D_TIMER_ACTION "Aktion"
// xdrv_10_knx.ino // xdrv_10_knx.ino
#define D_CONFIGURE_KNX "Configure KNX" #define D_CONFIGURE_KNX "KNX konfigurieren"
#define D_KNX_PARAMETERS "KNX Parameters" #define D_KNX_PARAMETERS "KNX-Parameter"
#define D_KNX_GENERAL_CONFIG "General" #define D_KNX_GENERAL_CONFIG "Allgemein"
#define D_KNX_PHYSICAL_ADDRESS "Physical Address" #define D_KNX_PHYSICAL_ADDRESS "Physikalische Adresse"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" #define D_KNX_PHYSICAL_ADDRESS_NOTE "( Muss einmalig im KNX-Netzwerk sein )"
#define D_KNX_ENABLE "Enable KNX" #define D_KNX_ENABLE "KNX aktivieren"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" #define D_KNX_GROUP_ADDRESS_TO_WRITE "Daten zum Senden an Gruppenadresse"
#define D_ADD "Add" #define D_ADD "Hinzufügen"
#define D_DELETE "Delete" #define D_DELETE "Löschen"
#define D_REPLY "Reply" #define D_REPLY "Antworten"
#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" #define D_KNX_GROUP_ADDRESS_TO_READ "Gruppenadresse zum Emfang von Daten"
#define D_LOG_KNX "KNX: " #define D_LOG_KNX "KNX: "
#define D_RECEIVED_FROM "Received from" #define D_RECEIVED_FROM "Empfangen von"
#define D_KNX_COMMAND_WRITE "Write" #define D_KNX_COMMAND_WRITE "Schreiben"
#define D_KNX_COMMAND_READ "Read" #define D_KNX_COMMAND_READ "Lesen"
#define D_KNX_COMMAND_OTHER "Other" #define D_KNX_COMMAND_OTHER "Andere"
#define D_SENT_TO "sent to" #define D_SENT_TO "gesendet an"
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." #define D_KNX_WARNING "Die Gruppenadresse ( 0 / 0 / 0 ) ist reserviert und kann nicht verwendet werden."
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Erweiterte Kommunikation"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "A" #define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "А" #define D_UNIT_AMPERE "А"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "А" #define D_UNIT_AMPERE "А"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "安" #define D_UNIT_AMPERE "安"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx" #define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx" #define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx" #define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units // Units
#define D_UNIT_AMPERE "安" #define D_UNIT_AMPERE "安"

View File

@ -216,8 +216,9 @@ struct SYSCFG {
uint16_t blinkcount; // 39C uint16_t blinkcount; // 39C
uint16_t light_rotation; // 39E uint16_t light_rotation; // 39E
byte free_3A0[12]; // 3A9 byte free_3A0[4]; // 3A0
uint8_t switchmode[MAX_SWITCHES]; // 3A4 (6.0.0b - moved from 0x4CA)
char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC
char switch_topic[33]; // 430 char switch_topic[33]; // 430
char serial_delimiter; // 451 char serial_delimiter; // 451
@ -243,7 +244,9 @@ struct SYSCFG {
uint16_t light_wakeup; // 4A6 uint16_t light_wakeup; // 4A6
byte knx_CB_registered; // 4A8 Number of Group Address to write byte knx_CB_registered; // 4A8 Number of Group Address to write
char web_password[33]; // 4A9 char web_password[33]; // 4A9
uint8_t switchmode[MAX_SWITCHES]; // 4CA
uint8_t ex_switchmode[4]; // 4CA Free since 6.0.0a
char ntp_server[3][33]; // 4CE char ntp_server[3][33]; // 4CE
byte ina219_mode; // 531 byte ina219_mode; // 531
uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532

View File

@ -763,6 +763,20 @@ void SettingsDelta()
Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_size = sizeof(SYSCFG);
Settings.cfg_crc = GetSettingsCrc(); Settings.cfg_crc = GetSettingsCrc();
} }
if (Settings.version < 0x06000002) {
for (byte i = 0; i < MAX_SWITCHES; i++) {
if (i < 4) {
Settings.switchmode[i] = Settings.ex_switchmode[i];
} else {
Settings.switchmode[i] = SWITCH_MODE;
}
}
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (Settings.my_gp.io[i] >= GPIO_SWT5) { // Move up from GPIO_SWT5 to GPIO_KEY1
Settings.my_gp.io[i] += 4;
}
}
}
Settings.version = VERSION; Settings.version = VERSION;
SettingsSave(1); SettingsSave(1);

View File

@ -37,10 +37,10 @@ typedef unsigned long power_t; // Power (Relay) type
\*********************************************************************************************/ \*********************************************************************************************/
// Changes to the following MAX_ defines will impact settings layout // Changes to the following MAX_ defines will impact settings layout
#define MAX_SWITCHES 8 // Max number of switches
#define MAX_RELAYS 8 // Max number of relays #define MAX_RELAYS 8 // Max number of relays
#define MAX_LEDS 4 // Max number of leds #define MAX_LEDS 4 // Max number of leds
#define MAX_KEYS 4 // Max number of keys or buttons #define MAX_KEYS 4 // Max number of keys or buttons
#define MAX_SWITCHES 4 // Max number of switches
#define MAX_PWMS 5 // Max number of PWM channels #define MAX_PWMS 5 // Max number of PWM channels
#define MAX_COUNTERS 4 // Max number of counter sensors #define MAX_COUNTERS 4 // Max number of counter sensors
#define MAX_TIMERS 16 // Max number of Timers #define MAX_TIMERS 16 // Max number of Timers

View File

@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)" - Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/ ====================================================*/
#define VERSION 0x06000001 // 6.0.0a #define VERSION 0x06000002 // 6.0.0b
// Location specific includes // Location specific includes
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
@ -167,6 +167,7 @@ uint8_t multiwindow[MAX_KEYS] = { 0 }; // Max time between button presses t
uint8_t multipress[MAX_KEYS] = { 0 }; // Number of button presses within multiwindow uint8_t multipress[MAX_KEYS] = { 0 }; // Number of button presses within multiwindow
uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states
uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold
uint8_t virtualswitch[MAX_SWITCHES] = { 0 }; // Virtual switch states
mytmplt my_module; // Active copy of Module name and GPIOs mytmplt my_module; // Active copy of Module name and GPIOs
uint8_t pin[GPIO_MAX]; // Possible pin configurations uint8_t pin[GPIO_MAX]; // Possible pin configurations
@ -797,8 +798,13 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
} }
else if ((CMND_COUNTER == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { else if ((CMND_COUNTER == command_code) && (index > 0) && (index <= MAX_COUNTERS)) {
if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) { if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) {
RtcSettings.pulse_counter[index -1] = payload16; if ((dataBuf[0] == '-') || (dataBuf[0] == '+')) {
Settings.pulse_counter[index -1] = payload16; RtcSettings.pulse_counter[index -1] += payload32;
Settings.pulse_counter[index -1] += payload32;
} else {
RtcSettings.pulse_counter[index -1] = payload32;
Settings.pulse_counter[index -1] = payload32;
}
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_LVALUE, command, index, RtcSettings.pulse_counter[index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_LVALUE, command, index, RtcSettings.pulse_counter[index -1]);
} }
@ -1141,8 +1147,8 @@ boolean SendKey(byte key, byte device, byte state)
char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; char *tmp = (key) ? Settings.switch_topic : Settings.button_topic;
Format(key_topic, tmp, sizeof(key_topic)); Format(key_topic, tmp, sizeof(key_topic));
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
if (!key && (device > devices_present)) device = 1; if (!key && (device > devices_present)) device = 1; // Only allow number of buttons up to number of devices
GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key)); // cmnd/switchtopic/POWERx
if (9 == state) { if (9 == state) {
mqtt_data[0] = '\0'; mqtt_data[0] = '\0';
} else { } else {
@ -1426,7 +1432,11 @@ boolean MqttShowSensor()
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str()); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str());
int json_data_start = strlen(mqtt_data); int json_data_start = strlen(mqtt_data);
for (byte i = 0; i < MAX_SWITCHES; i++) { for (byte i = 0; i < MAX_SWITCHES; i++) {
#ifdef USE_TM1638
if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) {
#else
if (pin[GPIO_SWT1 +i] < 99) { if (pin[GPIO_SWT1 +i] < 99) {
#endif // USE_TM1638
boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i]));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i])); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i]));
} }
@ -1659,7 +1669,7 @@ void ButtonHandler()
* Switch handler * Switch handler
\*********************************************************************************************/ \*********************************************************************************************/
void SwitchHandler() void SwitchHandler(byte mode)
{ {
uint8_t button = NOT_PRESSED; uint8_t button = NOT_PRESSED;
uint8_t switchflag; uint8_t switchflag;
@ -1674,7 +1684,12 @@ void SwitchHandler()
} }
} }
if (mode) {
button = virtualswitch[i];
} else {
button = digitalRead(pin[GPIO_SWT1 +i]); button = digitalRead(pin[GPIO_SWT1 +i]);
}
if (button != lastwallswitch[i]) { if (button != lastwallswitch[i]) {
switchflag = 3; switchflag = 3;
switch (Settings.switchmode[i]) { switch (Settings.switchmode[i]) {
@ -1808,7 +1823,7 @@ void StateLoop()
\*-------------------------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------------------------*/
ButtonHandler(); ButtonHandler();
SwitchHandler(); SwitchHandler(0);
XdrvCall(FUNC_EVERY_50_MSECOND); XdrvCall(FUNC_EVERY_50_MSECOND);
XsnsCall(FUNC_EVERY_50_MSECOND); XsnsCall(FUNC_EVERY_50_MSECOND);

View File

@ -35,6 +35,10 @@ enum UserSelectablePins {
GPIO_SWT2, GPIO_SWT2,
GPIO_SWT3, GPIO_SWT3,
GPIO_SWT4, GPIO_SWT4,
GPIO_SWT5,
GPIO_SWT6,
GPIO_SWT7,
GPIO_SWT8,
GPIO_KEY1, // Button usually connected to GPIO0 GPIO_KEY1, // Button usually connected to GPIO0
GPIO_KEY2, GPIO_KEY2,
GPIO_KEY3, GPIO_KEY3,
@ -97,6 +101,9 @@ enum UserSelectablePins {
GPIO_SDM120_RX, // SDM120 Serial interface GPIO_SDM120_RX, // SDM120 Serial interface
GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_TX, // SDM630 Serial interface
GPIO_SDM630_RX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface
GPIO_TM16CLK, // TM1638 Clock
GPIO_TM16DIO, // TM1638 Data I/O
GPIO_TM16STB, // TM1638 Strobe
GPIO_SENSOR_END }; GPIO_SENSOR_END };
// Programmer selectable GPIO functionality offset by user selectable GPIOs // Programmer selectable GPIO functionality offset by user selectable GPIOs
@ -124,7 +131,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_I2C_SCL "|" D_SENSOR_I2C_SDA "|" D_SENSOR_I2C_SCL "|" D_SENSOR_I2C_SDA "|"
D_SENSOR_WS2812 "|" D_SENSOR_WS2812 "|"
D_SENSOR_IRSEND "|" D_SENSOR_IRSEND "|"
D_SENSOR_SWITCH "1|" D_SENSOR_SWITCH "2|" D_SENSOR_SWITCH "3|" D_SENSOR_SWITCH "4|" D_SENSOR_SWITCH "1|" D_SENSOR_SWITCH "2|" D_SENSOR_SWITCH "3|" D_SENSOR_SWITCH "4|" D_SENSOR_SWITCH "5|" D_SENSOR_SWITCH "6|" D_SENSOR_SWITCH "7|" D_SENSOR_SWITCH "8|"
D_SENSOR_BUTTON "1|" D_SENSOR_BUTTON "2|" D_SENSOR_BUTTON "3|" D_SENSOR_BUTTON "4|" D_SENSOR_BUTTON "1|" D_SENSOR_BUTTON "2|" D_SENSOR_BUTTON "3|" D_SENSOR_BUTTON "4|"
D_SENSOR_RELAY "1|" D_SENSOR_RELAY "2|" D_SENSOR_RELAY "3|" D_SENSOR_RELAY "4|" D_SENSOR_RELAY "5|" D_SENSOR_RELAY "6|" D_SENSOR_RELAY "7|" D_SENSOR_RELAY "8|" D_SENSOR_RELAY "1|" D_SENSOR_RELAY "2|" D_SENSOR_RELAY "3|" D_SENSOR_RELAY "4|" D_SENSOR_RELAY "5|" D_SENSOR_RELAY "6|" D_SENSOR_RELAY "7|" D_SENSOR_RELAY "8|"
D_SENSOR_RELAY "1i|" D_SENSOR_RELAY "2i|" D_SENSOR_RELAY "3i|" D_SENSOR_RELAY "4i|" D_SENSOR_RELAY "5i|" D_SENSOR_RELAY "6i|" D_SENSOR_RELAY "7i|" D_SENSOR_RELAY "8i|" D_SENSOR_RELAY "1i|" D_SENSOR_RELAY "2i|" D_SENSOR_RELAY "3i|" D_SENSOR_RELAY "4i|" D_SENSOR_RELAY "5i|" D_SENSOR_RELAY "6i|" D_SENSOR_RELAY "7i|" D_SENSOR_RELAY "8i|"
@ -142,7 +149,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|" D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|"
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|" D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|" D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|"
D_SENSOR_SDM630_TX "|" D_SENSOR_SDM630_RX; D_SENSOR_SDM630_TX "|" D_SENSOR_SDM630_RX "|"
D_SENSOR_TM1638_CLK "|" D_SENSOR_TM1638_DIO "|" D_SENSOR_TM1638_STB;
/********************************************************************************************/ /********************************************************************************************/

View File

@ -368,10 +368,10 @@ char* GetPowerDevice(char* dest, uint8_t idx, size_t size, uint8_t option)
{ {
char sidx[8]; char sidx[8];
strncpy_P(dest, S_RSLT_POWER, size); strncpy_P(dest, S_RSLT_POWER, size); // POWER
if ((devices_present + option) > 1) { if ((devices_present + option) > 1) {
snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); // x
strncat(dest, sidx, size); strncat(dest, sidx, size); // POWERx
} }
return dest; return dest;
} }
@ -567,6 +567,11 @@ boolean GetUsedInModule(byte val, uint8_t *arr)
#ifndef USE_SDM630 #ifndef USE_SDM630
if (GPIO_SDM630_TX == val) { return true; } if (GPIO_SDM630_TX == val) { return true; }
if (GPIO_SDM630_RX == val) { return true; } if (GPIO_SDM630_RX == val) { return true; }
#endif
#ifndef USE_TM1638
if (GPIO_TM16CLK == val) { return true; }
if (GPIO_TM16DIO == val) { return true; }
if (GPIO_TM16STB == val) { return true; }
#endif #endif
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
offset = (GPIO_REL1_INV - GPIO_REL1); offset = (GPIO_REL1_INV - GPIO_REL1);
@ -1009,7 +1014,6 @@ void WifiBegin(uint8_t flag)
WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186 WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186
#endif #endif
WiFi.persistent(false); // Solve possible wifi init errors
WiFi.disconnect(true); // Delete SDK wifi config WiFi.disconnect(true); // Delete SDK wifi config
delay(200); delay(200);
WiFi.mode(WIFI_STA); // Disable AP mode WiFi.mode(WIFI_STA); // Disable AP mode

View File

@ -276,6 +276,7 @@
// #define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code) // #define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code)
// #define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) // #define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code)
#define MGS_SENSOR_ADDR 0x04 // Default Mutichannel Gas sensor i2c address #define MGS_SENSOR_ADDR 0x04 // Default Mutichannel Gas sensor i2c address
// #define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code)
#endif // USE_I2C #endif // USE_I2C
// -- SPI sensors --------------------------------- // -- SPI sensors ---------------------------------
@ -311,6 +312,8 @@
#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) #define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code)
//#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code)
#define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB
/*********************************************************************************************\ /*********************************************************************************************\

View File

@ -488,6 +488,9 @@ void ShowPage(String &page, bool auth)
page += FPSTR(HTTP_END); page += FPSTR(HTTP_END);
page.replace(F("{mv"), my_version); page.replace(F("{mv"), my_version);
SetHeader(); SetHeader();
ShowFreeMem(PSTR("ShowPage"));
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page); WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page);
} }

View File

@ -357,6 +357,9 @@ bool RulesProcessEvent(char *json_event)
String event_saved = json_event; String event_saved = json_event;
event_saved.toUpperCase(); event_saved.toUpperCase();
//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event %s"), event_saved.c_str());
//AddLog(LOG_LEVEL_DEBUG);
for (byte i = 0; i < MAX_RULE_SETS; i++) { for (byte i = 0; i < MAX_RULE_SETS; i++) {
if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) { if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) {
if (RuleSetProcess(i, event_saved)) { serviced = true; } if (RuleSetProcess(i, event_saved)) { serviced = true; }
@ -554,55 +557,44 @@ boolean RulesCommand()
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]);
} }
else if ((CMND_ADD == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { else if ((CMND_ADD == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
if ( (XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= 0) ){ if ( XdrvMailbox.data_len > 0 ) {
int16_t tempvar = atol(vars[index -1]) + XdrvMailbox.payload; double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data);
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), tempvar ); dtostrfd(tempvar,2,vars[index -1]);
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
} }
else if ((CMND_SUB == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { else if ((CMND_SUB == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
if ( (XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= 0) ){ if ( XdrvMailbox.data_len > 0 ){
int16_t tempvar = atol(vars[index -1]) - XdrvMailbox.payload; double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data);
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), tempvar ); dtostrfd(tempvar,2,vars[index -1]);
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
} }
else if ((CMND_MULT == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { else if ((CMND_MULT == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
if ( (XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= 0) ){ if ( XdrvMailbox.data_len > 0 ){
int16_t tempvar = atol(vars[index -1]) * XdrvMailbox.payload; double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data);
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), tempvar ); dtostrfd(tempvar,2,vars[index -1]);
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
} }
else if ((CMND_SCALE == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) { else if ((CMND_SCALE == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
if ( XdrvMailbox.data_len > 0 ) { if ( XdrvMailbox.data_len > 0 ) {
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
uint8_t tpos = 0; // Parameter index double value = 0;
int16_t value = 0; double valueIN = 0;
int16_t valueIN = 0; double fromLow = 0;
int16_t fromLow = 0; double fromHigh = 0;
int16_t fromHigh = 0; double toLow = 0;
int16_t toLow = 0; double toHigh = 0;
int16_t toHigh = 0;
char *p = XdrvMailbox.data; // Parameters like "1, 2, 3, 4" valueIN = CharToDouble(subStr(XdrvMailbox.data, ",", 1));
char *q = p; // Value entered flag fromLow = CharToDouble(subStr(XdrvMailbox.data, ",", 2));
while (p && (tpos < 6)) { fromHigh = CharToDouble(subStr(XdrvMailbox.data, ",", 3));
if (p > q) { // Any value entered toLow = CharToDouble(subStr(XdrvMailbox.data, ",", 4));
if (1 == tpos) { valueIN = value; } toHigh = CharToDouble(subStr(XdrvMailbox.data, ",", 5));
if (2 == tpos) { fromLow = value; }
if (3 == tpos) { fromHigh = value; } value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
if (4 == tpos) { toLow = value; } dtostrfd(value,2,vars[index -1]);
if (5 == tpos) { toHigh = value; }
}
p = LTrim(p); // Skip spaces
if (tpos && (*p == ',')) { p++; } // Skip separator
p = LTrim(p); // Skip spaces
q = p; // Reset any value entered flag
value = strtol(p, &p, 10);
tpos++; // Next parameter
}
value = map(valueIN, fromLow, fromHigh, toLow, toHigh);
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), value );
} }
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
@ -612,6 +604,30 @@ boolean RulesCommand()
return serviced; return serviced;
} }
double map_double(double x, double in_min, double in_max, double out_min, double out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// Function to return a substring defined by a delimiter at an index
char* subStr (char* str, const char *delim, int index) {
char *act, *sub, *ptr;
static char copy[10];
int i;
// Since strtok consumes the first arg, make a copy
strcpy(copy, str);
for (i = 1, act = copy; i <= index; i++, act = NULL) {
sub = strtok_r(act, delim, &ptr);
if (sub == NULL) break;
}
sub = LTrim(sub);
sub = RTrim(sub);
return sub;
}
/*********************************************************************************************\ /*********************************************************************************************\
* Interface * Interface
\*********************************************************************************************/ \*********************************************************************************************/

View File

@ -1045,14 +1045,18 @@ boolean KnxCommand()
byte i = KNX_GA_Search(index + KNX_SLOT1 -1); byte i = KNX_GA_Search(index + KNX_SLOT1 -1);
while ( i != KNX_Empty ) { while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i]; KNX_addr.value = Settings.knx_GA_addr[i];
knx.write_2byte_float(KNX_addr, XdrvMailbox.payload);
float tempvar = CharToDouble(XdrvMailbox.data);
dtostrfd(tempvar,2,XdrvMailbox.data);
knx.write_2byte_float(KNX_addr, tempvar);
if (Settings.flag.knx_enable_enhancement) { if (Settings.flag.knx_enable_enhancement) {
knx.write_2byte_float(KNX_addr, XdrvMailbox.payload); knx.write_2byte_float(KNX_addr, tempvar);
knx.write_2byte_float(KNX_addr, XdrvMailbox.payload); knx.write_2byte_float(KNX_addr, tempvar);
} }
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"),
device_param_ga[index + KNX_SLOT1 -2], XdrvMailbox.payload, device_param_ga[index + KNX_SLOT1 -2], XdrvMailbox.data,
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member);
AddLog(LOG_LEVEL_INFO); AddLog(LOG_LEVEL_INFO);
@ -1062,8 +1066,8 @@ boolean KnxCommand()
else { return false; } // Incomplete command else { return false; } // Incomplete command
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%d\"}"), snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
command, index, XdrvMailbox.payload ); command, index, XdrvMailbox.data );
return true; return true;
} }

2123
sonoff/xsns_27_apds9960.ino Normal file

File diff suppressed because it is too large Load Diff

219
sonoff/xsns_28_tm1638.ino Normal file
View File

@ -0,0 +1,219 @@
/*
xsns_28_tm1638.ino - TM1638 8 switch, led and 7 segment unit support for Sonoff-Tasmota
Copyright (C) 2018 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_TM1638
/*********************************************************************************************\
* TM1638 8 switch, led and 7 segment
*
* Uses GPIO TM16 DIO, TM16 CLK and TM16 STB
\*********************************************************************************************/
#define TM1638_COLOR_NONE 0
#define TM1638_COLOR_RED 1
#define TM1638_COLOR_GREEN 2
uint8_t tm1638_type = 1;
uint8_t tm1638_clock_pin = 0;
uint8_t tm1638_data_pin = 0;
uint8_t tm1638_strobe_pin = 0;
uint8_t tm1638_displays = 8;
uint8_t tm1638_active_display = 0;
uint8_t tm1638_intensity = 0;
/*********************************************************************************************\
* Pieces from library https://github.com/rjbatista/tm1638-library
\*********************************************************************************************/
void Tm16XXSend(byte data)
{
for (int i = 0; i < 8; i++) {
digitalWrite(tm1638_clock_pin, LOW);
digitalWrite(tm1638_data_pin, data & 1 ? HIGH : LOW);
data >>= 1;
digitalWrite(tm1638_clock_pin, HIGH);
}
}
void Tm16XXSendCommand(byte cmd)
{
digitalWrite(tm1638_strobe_pin, LOW);
Tm16XXSend(cmd);
digitalWrite(tm1638_strobe_pin, HIGH);
}
void TM16XXSendData(byte address, byte data)
{
Tm16XXSendCommand(0x44);
digitalWrite(tm1638_strobe_pin, LOW);
Tm16XXSend(0xC0 | address);
Tm16XXSend(data);
digitalWrite(tm1638_strobe_pin, HIGH);
}
byte Tm16XXReceive()
{
byte temp = 0;
// Pull-up on
pinMode(tm1638_data_pin, INPUT);
digitalWrite(tm1638_data_pin, HIGH);
for (int i = 0; i < 8; i++) {
temp >>= 1;
digitalWrite(tm1638_clock_pin, LOW);
if (digitalRead(tm1638_data_pin)) {
temp |= 0x80;
}
digitalWrite(tm1638_clock_pin, HIGH);
}
// Pull-up off
pinMode(tm1638_data_pin, OUTPUT);
digitalWrite(tm1638_data_pin, LOW);
return temp;
}
/*********************************************************************************************/
void Tm16XXClearDisplay()
{
for (int i = 0; i < tm1638_displays; i++) {
TM16XXSendData(i << 1, 0);
}
}
void Tm1638SetLED(byte color, byte pos)
{
TM16XXSendData((pos << 1) + 1, color);
}
void Tm1638SetLEDs(word leds)
{
for (int i = 0; i < tm1638_displays; i++) {
byte color = 0;
if ((leds & (1 << i)) != 0) {
color |= TM1638_COLOR_RED;
}
if ((leds & (1 << (i + 8))) != 0) {
color |= TM1638_COLOR_GREEN;
}
Tm1638SetLED(color, i);
}
}
byte Tm1638GetButtons()
{
byte keys = 0;
digitalWrite(tm1638_strobe_pin, LOW);
Tm16XXSend(0x42);
for (int i = 0; i < 4; i++) {
keys |= Tm16XXReceive() << i;
}
digitalWrite(tm1638_strobe_pin, HIGH);
return keys;
}
/*********************************************************************************************/
void TmInit()
{
tm1638_type = 0;
if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) {
tm1638_clock_pin = pin[GPIO_TM16CLK];
tm1638_data_pin = pin[GPIO_TM16DIO];
tm1638_strobe_pin = pin[GPIO_TM16STB];
pinMode(tm1638_data_pin, OUTPUT);
pinMode(tm1638_clock_pin, OUTPUT);
pinMode(tm1638_strobe_pin, OUTPUT);
digitalWrite(tm1638_strobe_pin, HIGH);
digitalWrite(tm1638_clock_pin, HIGH);
Tm16XXSendCommand(0x40);
Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | min(7, tm1638_intensity));
digitalWrite(tm1638_strobe_pin, LOW);
Tm16XXSend(0xC0);
for (int i = 0; i < 16; i++) {
Tm16XXSend(0x00);
}
digitalWrite(tm1638_strobe_pin, HIGH);
tm1638_type = 1;
}
}
void TmLoop()
{
byte buttons = Tm1638GetButtons();
for (byte i = 0; i < 8; i++) {
virtualswitch[i] = buttons &1;
byte color = virtualswitch[i] ? TM1638_COLOR_RED : TM1638_COLOR_NONE;
Tm1638SetLED(color, i);
buttons >>= 1;
}
SwitchHandler(1);
}
void TmShow(boolean json)
{
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
#define XSNS_28
boolean Xsns28(byte function)
{
boolean result = false;
if (tm1638_type) {
switch (function) {
case FUNC_INIT:
TmInit();
break;
case FUNC_EVERY_50_MSECOND:
TmLoop();
break;
/*
case FUNC_JSON_APPEND:
TmShow(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_APPEND:
TmShow(0);
break;
#endif // USE_WEBSERVER
*/
}
}
return result;
}
#endif // USE_TM1638