Add global interlock

Use command SetOption14 1 to enable interlock mode
This commit is contained in:
arendst 2017-08-18 12:55:08 +02:00
parent e0f759a318
commit 06d0c62dfa
4 changed files with 38 additions and 5 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota ## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **5.5.2j** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. Current version is **5.5.2k** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions ### ATTENTION All versions

View File

@ -1,4 +1,4 @@
/* 5.5.2j /* 5.5.2k
* Fix Sonoff Pow intermittent exception 0 * Fix Sonoff Pow intermittent exception 0
* Change Sonoff Pow sending Domoticz telemetry data only * Change Sonoff Pow sending Domoticz telemetry data only
* Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676)
@ -11,6 +11,7 @@
* Fix Mitsubishi HVAC IR power controll (#740) * Fix Mitsubishi HVAC IR power controll (#740)
* Add Sonoff T1 support (#582) * Add Sonoff T1 support (#582)
* Change Sonoff T1 command Ledstate functionality by turning led on if power is off * Change Sonoff T1 command Ledstate functionality by turning led on if power is off
* Add command SetOption14 0|1 to enable interlock mode (#719, #721)
* *
* 5.5.2 20170808 * 5.5.2 20170808
* Extent max number of WS2812 pixels from 256 to 512 (#667) * Extent max number of WS2812 pixels from 256 to 512 (#667)

View File

@ -36,7 +36,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t button_swap : 1; // bit 11 (v5.1.6) uint32_t button_swap : 1; // bit 11 (v5.1.6)
uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0) uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0)
uint32_t button_single : 1; // bit 13 (v5.4.0) uint32_t button_single : 1; // bit 13 (v5.4.0)
uint32_t spare14 : 1; uint32_t interlock : 1; // bit 14 (v5.5.2k)
uint32_t spare15 : 1; uint32_t spare15 : 1;
uint32_t spare16 : 1; uint32_t spare16 : 1;
uint32_t spare17 : 1; uint32_t spare17 : 1;

View File

@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)" - Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/ ====================================================*/
#define VERSION 0x0505020A // 5.5.2j #define VERSION 0x0505020B // 5.5.2k
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
enum week_t {Last, First, Second, Third, Fourth}; enum week_t {Last, First, Second, Third, Fourth};
@ -266,6 +266,7 @@ uint8_t blogidx = 0; // Command backlog index
uint8_t blogptr = 0; // Command backlog pointer uint8_t blogptr = 0; // Command backlog pointer
uint8_t blogmutex = 0; // Command backlog pending uint8_t blogmutex = 0; // Command backlog pending
uint16_t blogdelay = 0; // Command backlog delay uint16_t blogdelay = 0; // Command backlog delay
uint8_t interlockmutex = 0; // Interlock power command pending
#ifdef USE_MQTT_TLS #ifdef USE_MQTT_TLS
WiFiClientSecure espClient; // Wifi Secure Client WiFiClientSecure espClient; // Wifi Secure Client
@ -403,6 +404,20 @@ void setRelay(uint8_t rpower)
power = (1 << Maxdevice) -1; power = (1 << Maxdevice) -1;
rpower = power; rpower = power;
} }
if (sysCfg.flag.interlock) { // Allow only one or no relay set
uint8_t mask = 0x01;
uint8_t count = 0;
for (byte i = 0; i < Maxdevice; i++) {
if (rpower & mask) {
count++;
}
mask <<= 1;
}
if (count > 1) {
power = 0;
rpower = 0;
}
}
if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) { if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) {
Serial.write(0xA0); Serial.write(0xA0);
Serial.write(0x04); Serial.write(0x04);
@ -1010,6 +1025,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
return; return;
} }
else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) { else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) {
/* 0 = Keep relays off after power on
* 1 = Turn relays on after power on
* 2 = Toggle relays after power on
* 3 = Set relays to last saved state after power on
* 4 = Turn relays on and disable any relay control (used for Sonoff Pow to always measure power)
*/
if ((payload >= 0) && (payload <= 4)) { if ((payload >= 0) && (payload <= 4)) {
sysCfg.poweronstate = payload; sysCfg.poweronstate = payload;
if (4 == sysCfg.poweronstate) { if (4 == sysCfg.poweronstate) {
@ -1062,7 +1083,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
} }
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveData\":\"%s\"}"), (sysCfg.savedata > 1) ? stemp1 : getStateText(sysCfg.savedata)); snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveData\":\"%s\"}"), (sysCfg.savedata > 1) ? stemp1 : getStateText(sysCfg.savedata));
} }
else if (!strcmp_P(type,PSTR("SETOPTION")) && ((index >= 0) && (index <= 13)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) { else if (!strcmp_P(type,PSTR("SETOPTION")) && ((index >= 0) && (index <= 14)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
if (index <= 31) { if (index <= 31) {
ptype = 0; // SetOption0 .. 31 ptype = 0; // SetOption0 .. 31
} else { } else {
@ -1084,6 +1105,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
case 11: // button_swap case 11: // button_swap
case 12: // stop_flash_rotate case 12: // stop_flash_rotate
case 13: // button_single case 13: // button_single
case 14: // interlock
bitWrite(sysCfg.flag.data, index, payload); bitWrite(sysCfg.flag.data, index, payload);
} }
if (12 == index) { // stop_flash_rotate if (12 == index) { // stop_flash_rotate
@ -1650,6 +1672,16 @@ void do_cmnd_power(byte device, byte state)
blink_mask &= (0xFF ^ mask); // Clear device mask blink_mask &= (0xFF ^ mask); // Clear device mask
mqtt_publishPowerBlinkState(device); mqtt_publishPowerBlinkState(device);
} }
if (sysCfg.flag.interlock && !interlockmutex) { // Clear all but masked relay
interlockmutex = 1;
for (byte i = 0; i < Maxdevice; i++) {
byte imask = 0x01 << i;
if ((power & imask) && (mask != imask)) {
do_cmnd_power(i +1, 0);
}
}
interlockmutex = 0;
}
switch (state) { switch (state) {
case 0: { // Off case 0: { // Off
power &= (0xFF ^ mask); power &= (0xFF ^ mask);