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
- Lobradov providing compile optimization tips
- 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
- Gijs Noorlander for his MHZ19 and SenseAir drivers
- 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 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)
@ -17,6 +23,7 @@
* Fix Pzem004T checksum error
* Fix KNX bug when doing reply of sensors values
* Fix rules induced LWT message
* Fix possible wifi connection problem (#1366)
*
* 5.14.0b
* Add Console Commands to send KNX Commands

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

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

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "A"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "А"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "А"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "安"

View File

@ -471,6 +471,9 @@
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#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
#define D_UNIT_AMPERE "安"

View File

@ -216,8 +216,9 @@ struct SYSCFG {
uint16_t blinkcount; // 39C
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 switch_topic[33]; // 430
char serial_delimiter; // 451
@ -243,7 +244,9 @@ struct SYSCFG {
uint16_t light_wakeup; // 4A6
byte knx_CB_registered; // 4A8 Number of Group Address to write
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
byte ina219_mode; // 531
uint16_t pulse_timer[MAX_PULSETIMERS]; // 532

View File

@ -763,6 +763,20 @@ void SettingsDelta()
Settings.cfg_size = sizeof(SYSCFG);
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;
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
#define MAX_SWITCHES 8 // Max number of switches
#define MAX_RELAYS 8 // Max number of relays
#define MAX_LEDS 4 // Max number of leds
#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_COUNTERS 4 // Max number of counter sensors
#define MAX_TIMERS 16 // Max number of Timers

View File

@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
#define VERSION 0x06000001 // 6.0.0a
#define VERSION 0x06000002 // 6.0.0b
// Location specific includes
#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 lastwallswitch[MAX_SWITCHES]; // Last wall switch states
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
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)) {
if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) {
RtcSettings.pulse_counter[index -1] = payload16;
Settings.pulse_counter[index -1] = payload16;
if ((dataBuf[0] == '-') || (dataBuf[0] == '+')) {
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]);
}
@ -1141,8 +1147,8 @@ boolean SendKey(byte key, byte device, byte state)
char *tmp = (key) ? Settings.switch_topic : Settings.button_topic;
Format(key_topic, tmp, sizeof(key_topic));
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
if (!key && (device > devices_present)) device = 1;
GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), key));
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)); // cmnd/switchtopic/POWERx
if (9 == state) {
mqtt_data[0] = '\0';
} 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());
int json_data_start = strlen(mqtt_data);
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) {
#endif // USE_TM1638
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]));
}
@ -1659,7 +1669,7 @@ void ButtonHandler()
* Switch handler
\*********************************************************************************************/
void SwitchHandler()
void SwitchHandler(byte mode)
{
uint8_t button = NOT_PRESSED;
uint8_t switchflag;
@ -1674,7 +1684,12 @@ void SwitchHandler()
}
}
if (mode) {
button = virtualswitch[i];
} else {
button = digitalRead(pin[GPIO_SWT1 +i]);
}
if (button != lastwallswitch[i]) {
switchflag = 3;
switch (Settings.switchmode[i]) {
@ -1808,7 +1823,7 @@ void StateLoop()
\*-------------------------------------------------------------------------------------------*/
ButtonHandler();
SwitchHandler();
SwitchHandler(0);
XdrvCall(FUNC_EVERY_50_MSECOND);
XsnsCall(FUNC_EVERY_50_MSECOND);

View File

@ -35,6 +35,10 @@ enum UserSelectablePins {
GPIO_SWT2,
GPIO_SWT3,
GPIO_SWT4,
GPIO_SWT5,
GPIO_SWT6,
GPIO_SWT7,
GPIO_SWT8,
GPIO_KEY1, // Button usually connected to GPIO0
GPIO_KEY2,
GPIO_KEY3,
@ -97,6 +101,9 @@ enum UserSelectablePins {
GPIO_SDM120_RX, // SDM120 Serial interface
GPIO_SDM630_TX, // 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 };
// 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_WS2812 "|"
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_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|"
@ -142,7 +149,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|"
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
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];
strncpy_P(dest, S_RSLT_POWER, size);
strncpy_P(dest, S_RSLT_POWER, size); // POWER
if ((devices_present + option) > 1) {
snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx);
strncat(dest, sidx, size);
snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); // x
strncat(dest, sidx, size); // POWERx
}
return dest;
}
@ -567,6 +567,11 @@ boolean GetUsedInModule(byte val, uint8_t *arr)
#ifndef USE_SDM630
if (GPIO_SDM630_TX == 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
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
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
#endif
WiFi.persistent(false); // Solve possible wifi init errors
WiFi.disconnect(true); // Delete SDK wifi config
delay(200);
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_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 USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code)
#endif // USE_I2C
// -- SPI sensors ---------------------------------
@ -311,6 +312,8 @@
#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
/*********************************************************************************************\

View File

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

View File

@ -357,6 +357,9 @@ bool RulesProcessEvent(char *json_event)
String event_saved = json_event;
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++) {
if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) {
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]);
}
else if ((CMND_ADD == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
if ( (XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= 0) ){
int16_t tempvar = atol(vars[index -1]) + XdrvMailbox.payload;
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), tempvar );
if ( XdrvMailbox.data_len > 0 ) {
double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data);
dtostrfd(tempvar,2,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)) {
if ( (XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= 0) ){
int16_t tempvar = atol(vars[index -1]) - XdrvMailbox.payload;
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), tempvar );
if ( XdrvMailbox.data_len > 0 ){
double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data);
dtostrfd(tempvar,2,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)) {
if ( (XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= 0) ){
int16_t tempvar = atol(vars[index -1]) * XdrvMailbox.payload;
snprintf_P(vars[index -1], sizeof(vars[index -1]), PSTR("%d"), tempvar );
if ( XdrvMailbox.data_len > 0 ){
double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data);
dtostrfd(tempvar,2,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)) {
if ( XdrvMailbox.data_len > 0 ) {
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
uint8_t tpos = 0; // Parameter index
int16_t value = 0;
int16_t valueIN = 0;
int16_t fromLow = 0;
int16_t fromHigh = 0;
int16_t toLow = 0;
int16_t toHigh = 0;
char *p = XdrvMailbox.data; // Parameters like "1, 2, 3, 4"
char *q = p; // Value entered flag
while (p && (tpos < 6)) {
if (p > q) { // Any value entered
if (1 == tpos) { valueIN = value; }
if (2 == tpos) { fromLow = value; }
if (3 == tpos) { fromHigh = value; }
if (4 == tpos) { toLow = value; }
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 );
double value = 0;
double valueIN = 0;
double fromLow = 0;
double fromHigh = 0;
double toLow = 0;
double toHigh = 0;
valueIN = CharToDouble(subStr(XdrvMailbox.data, ",", 1));
fromLow = CharToDouble(subStr(XdrvMailbox.data, ",", 2));
fromHigh = CharToDouble(subStr(XdrvMailbox.data, ",", 3));
toLow = CharToDouble(subStr(XdrvMailbox.data, ",", 4));
toHigh = CharToDouble(subStr(XdrvMailbox.data, ",", 5));
value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
dtostrfd(value,2,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;
}
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
\*********************************************************************************************/

View File

@ -1045,14 +1045,18 @@ boolean KnxCommand()
byte i = KNX_GA_Search(index + KNX_SLOT1 -1);
while ( i != KNX_Empty ) {
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) {
knx.write_2byte_float(KNX_addr, XdrvMailbox.payload);
knx.write_2byte_float(KNX_addr, XdrvMailbox.payload);
knx.write_2byte_float(KNX_addr, tempvar);
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"),
device_param_ga[index + KNX_SLOT1 -2], XdrvMailbox.payload,
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.data,
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member);
AddLog(LOG_LEVEL_INFO);
@ -1062,8 +1066,8 @@ boolean KnxCommand()
else { return false; } // Incomplete command
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%d\"}"),
command, index, XdrvMailbox.payload );
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
command, index, XdrvMailbox.data );
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