mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-29 13:46:37 +00:00
Add command `SspmLog<relay> [x]
`
Add command ``SspmLog<relay> [x]`` to retrieve relay power state change and cause logging
This commit is contained in:
parent
dcfdb78935
commit
bb5cf22d0a
@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only
|
- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only
|
||||||
- Command ``SspmHistory<relay>`` to retrieve daily energy of last six month (as defined by ARM firmware)
|
- Command ``SspmHistory<relay>`` to retrieve daily energy of last six month (as defined by ARM firmware)
|
||||||
- Command ``SspmIAmHere<relay>`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay
|
- Command ``SspmIAmHere<relay>`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay
|
||||||
|
- Command ``SspmLog<relay> [x]`` to retrieve relay power state change and cause logging
|
||||||
- Command ``SspmScan`` to rescan Sonoff SPM modbus
|
- Command ``SspmScan`` to rescan Sonoff SPM modbus
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -107,6 +107,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
|
|||||||
- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only
|
- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only
|
||||||
- Command ``SspmHistory<relay>`` to retrieve daily energy of last six month (as defined by ARM firmware)
|
- Command ``SspmHistory<relay>`` to retrieve daily energy of last six month (as defined by ARM firmware)
|
||||||
- Command ``SspmIAmHere<relay>`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay
|
- Command ``SspmIAmHere<relay>`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay
|
||||||
|
- Command ``SspmLog<relay> [x]`` to retrieve relay power state change and cause logging
|
||||||
- Command ``SspmMap 2,1,..`` to map Sonoff SPM scanned module to physical module [#14281](https://github.com/arendst/Tasmota/issues/14281)
|
- Command ``SspmMap 2,1,..`` to map Sonoff SPM scanned module to physical module [#14281](https://github.com/arendst/Tasmota/issues/14281)
|
||||||
- Command ``SspmScan`` to rescan Sonoff SPM modbus
|
- Command ``SspmScan`` to rescan Sonoff SPM modbus
|
||||||
- Command ``SetOption44 1..100`` to set base tolerance percentage for matching incoming IR messages (default 25, max 100) [#14555](https://github.com/arendst/Tasmota/issues/14555)
|
- Command ``SetOption44 1..100`` to set base tolerance percentage for matching incoming IR messages (default 25, max 100) [#14555](https://github.com/arendst/Tasmota/issues/14555)
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#ifdef USE_SONOFF_SPM
|
#ifdef USE_SONOFF_SPM
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Sonoff Stackable Power Manager (Current state: PROOF OF CONCEPT)
|
* Sonoff Stackable Power Manager
|
||||||
|
*
|
||||||
|
* {"NAME":"Sonoff SPM","GPIO":[0,0,0,0,3200,5536,0,0,0,0,0,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,0,0,32,0,0,0,0],"FLAG":0,"BASE":1}
|
||||||
*
|
*
|
||||||
* Initial POC template:
|
* Initial POC template:
|
||||||
* {"NAME":"Sonoff SPM (POC1)","GPIO":[1,1,1,1,3200,1,1,1,1,1,1,1,3232,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1}
|
* {"NAME":"Sonoff SPM (POC1)","GPIO":[1,1,1,1,3200,1,1,1,1,1,1,1,3232,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1}
|
||||||
* Add ethernet support:
|
* Add ethernet support:
|
||||||
* {"NAME":"Sonoff SPM (POC2)","GPIO":[1,0,1,0,3200,5536,0,0,1,1,1,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,1,1,32,1,0,0,1],"FLAG":0,"BASE":1}
|
|
||||||
* Remove all user selectable GPIOs:
|
|
||||||
* {"NAME":"Sonoff SPM (POC2)","GPIO":[0,0,0,0,3200,5536,0,0,0,0,0,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,0,0,32,0,0,0,0],"FLAG":0,"BASE":1}
|
* {"NAME":"Sonoff SPM (POC2)","GPIO":[0,0,0,0,3200,5536,0,0,0,0,0,0,3232,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,544,0,0,32,0,0,0,0],"FLAG":0,"BASE":1}
|
||||||
*
|
*
|
||||||
* Things to know:
|
* Things to know:
|
||||||
@ -37,6 +37,8 @@
|
|||||||
* Green led is controlled by ARM processor indicating SD-Card access.
|
* Green led is controlled by ARM processor indicating SD-Card access.
|
||||||
* ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol.
|
* ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol.
|
||||||
* Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B
|
* Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B
|
||||||
|
* Up to six months of daily energy are stored onthe SD-Card. Previous data is lost.
|
||||||
|
* Tasmota support is based on Sonoff SPM v1.0.0 ARM firmware.
|
||||||
*
|
*
|
||||||
* Tasmota POC1:
|
* Tasmota POC1:
|
||||||
* Up to 7 SPM-4Relay units supporting up to 28 relays.
|
* Up to 7 SPM-4Relay units supporting up to 28 relays.
|
||||||
@ -51,9 +53,11 @@
|
|||||||
* Yellow led blinks 2 seconds if an ARM-ESP comms CRC error is detected.
|
* Yellow led blinks 2 seconds if an ARM-ESP comms CRC error is detected.
|
||||||
* Persistence for module mapping
|
* Persistence for module mapping
|
||||||
* Supported commands:
|
* Supported commands:
|
||||||
* SspmMap 2,3,1,.. - Map scanned module number to physical module number using positional numbering
|
|
||||||
* SspmDisplay 0|1 - Select alternative GUI rotating display either all or powered on only
|
* SspmDisplay 0|1 - Select alternative GUI rotating display either all or powered on only
|
||||||
|
* SspmHistory<relay> - Retrieve daily energy of last six month (as defined by ARM firmware)
|
||||||
* SspmIAmHere<relay> - Blink ERROR in SPM-4Relay where relay resides
|
* SspmIAmHere<relay> - Blink ERROR in SPM-4Relay where relay resides
|
||||||
|
* SspmLog<relay> [x] - Retrieve relay power state change and cause logging
|
||||||
|
* SspmMap 2,3,1,.. - Map scanned module number to physical module number using positional numbering
|
||||||
* SspmScan - Rescan ARM modbus taking around 20 seconds
|
* SspmScan - Rescan ARM modbus taking around 20 seconds
|
||||||
* SspmReset 1 - Reset ARM and restart ESP
|
* SspmReset 1 - Reset ARM and restart ESP
|
||||||
*
|
*
|
||||||
@ -159,6 +163,8 @@ enum SspmMachineStates { SPM_NONE, // Do nothing
|
|||||||
SPM_UPDATE_CHANNELS // Update Energy for powered on channels
|
SPM_UPDATE_CHANNELS // Update Energy for powered on channels
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char kSSPMTriggers[] PROGMEM = "Tasmota|Device|Overload|Overtemp";
|
||||||
|
|
||||||
#include <TasmotaSerial.h>
|
#include <TasmotaSerial.h>
|
||||||
TasmotaSerial *SspmSerial;
|
TasmotaSerial *SspmSerial;
|
||||||
|
|
||||||
@ -200,8 +206,8 @@ typedef struct {
|
|||||||
uint8_t mstate;
|
uint8_t mstate;
|
||||||
uint8_t last_button;
|
uint8_t last_button;
|
||||||
uint8_t error_led_blinks;
|
uint8_t error_led_blinks;
|
||||||
uint8_t history_module;
|
uint8_t history_relay;
|
||||||
uint8_t history_channel;
|
uint8_t log_relay;
|
||||||
bool map_change;
|
bool map_change;
|
||||||
bool discovery_triggered;
|
bool discovery_triggered;
|
||||||
} TSspm;
|
} TSspm;
|
||||||
@ -851,18 +857,24 @@ void SSPMHandleReceivedData(void) {
|
|||||||
uint32_t channel = SspmBuffer[32];
|
uint32_t channel = SspmBuffer[32];
|
||||||
uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[20] << 8 | SspmBuffer[21]);
|
uint32_t module = SSPMGetModuleNumberFromMap(SspmBuffer[20] << 8 | SspmBuffer[21]);
|
||||||
|
|
||||||
if ((Sspm->history_channel == channel) && (Sspm->history_module == module)) {
|
if (Sspm->history_relay < 255) {
|
||||||
// uint32_t now = SspmBuffer[33] << 8 | SspmBuffer[34];
|
uint32_t history_module = Sspm->history_relay >> 2;
|
||||||
uint32_t start = SspmBuffer[37] << 8 | SspmBuffer[38];
|
uint32_t history_channel = Sspm->history_relay & 0x03; // Channel relays are NOT bit masked this time
|
||||||
Response_P(PSTR("{\"SSPMHistory\":{\"From\":\"%d-%02d-%02d\",\"DailyEnergy\":["),
|
if ((history_channel == channel) && (history_module == module)) {
|
||||||
start, SspmBuffer[39], SspmBuffer[40]);
|
// uint32_t now = SspmBuffer[33] << 8 | SspmBuffer[34];
|
||||||
|
uint32_t start = SspmBuffer[37] << 8 | SspmBuffer[38];
|
||||||
|
Response_P(PSTR("{\"SSPMHistory%d\":{\"From\":\"%d-%02d-%02d\",\"DailyEnergy\":["),
|
||||||
|
Sspm->history_relay +1, start, SspmBuffer[39], SspmBuffer[40]);
|
||||||
|
} else {
|
||||||
|
Sspm->history_relay = 255;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < entries; i++) {
|
for (uint32_t i = 0; i < entries; i++) {
|
||||||
float today_energy = SspmBuffer[41 + (i*2)] + (float)SspmBuffer[42 + (i*2)] / 100; // x.xxkWh
|
float today_energy = SspmBuffer[41 + (i*2)] + (float)SspmBuffer[42 + (i*2)] / 100; // x.xxkWh
|
||||||
if (112.30 == today_energy) { today_energy = 0; } // Unknown why sometimes 0x701E (=112.30kWh) pops up
|
if (112.30 == today_energy) { today_energy = 0; } // Unknown why sometimes 0x701E (=112.30kWh) pops up
|
||||||
|
|
||||||
if ((Sspm->history_channel == channel) && (Sspm->history_module == module)) {
|
if (Sspm->history_relay < 255) {
|
||||||
ResponseAppend_P(PSTR("%s%*_f"), (i)?",":"", Settings->flag2.energy_resolution, &today_energy);
|
ResponseAppend_P(PSTR("%s%*_f"), (i)?",":"", Settings->flag2.energy_resolution, &today_energy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,10 +887,10 @@ void SSPMHandleReceivedData(void) {
|
|||||||
Sspm->energy_yesterday[module][channel] = energy_yesterday;
|
Sspm->energy_yesterday[module][channel] = energy_yesterday;
|
||||||
Sspm->energy_total[module][channel] = energy_total; // x.xxkWh
|
Sspm->energy_total[module][channel] = energy_total; // x.xxkWh
|
||||||
|
|
||||||
if ((Sspm->history_channel == channel) && (Sspm->history_module == module)) {
|
if (Sspm->history_relay < 255) {
|
||||||
ResponseAppend_P(PSTR("]}}"));
|
ResponseAppend_P(PSTR("]}}"));
|
||||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("SSPMHistory"));
|
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("SSPMHistory"));
|
||||||
Sspm->history_channel = 5; // Disable display energy history
|
Sspm->history_relay = 255; // Disable display energy history
|
||||||
}
|
}
|
||||||
|
|
||||||
Sspm->allow_updates = 1;
|
Sspm->allow_updates = 1;
|
||||||
@ -900,14 +912,9 @@ void SSPMHandleReceivedData(void) {
|
|||||||
|----------------------- Month = 11 = November
|
|----------------------- Month = 11 = November
|
||||||
----------------------------- Year 07 e5 = 2021
|
----------------------------- Year 07 e5 = 2021
|
||||||
07 e5 0b 06 0f 1f 08 00 00 01
|
07 e5 0b 06 0f 1f 08 00 00 01
|
||||||
07 e5 0b 06 0f 1f 04 02 00 01
|
|
||||||
07 e5 0b 06 0f 1e 32 01 00 01
|
|
||||||
07 e5 0b 06 0f 1e 1e 01 01 01
|
07 e5 0b 06 0f 1e 1e 01 01 01
|
||||||
07 e5 0b 06 0f 18 38 02 01 01
|
|
||||||
07 e5 0b 06 0f 12 38 00 01 01
|
|
||||||
07 e5 0b 06 0e 37 36 03 00 00
|
07 e5 0b 06 0e 37 36 03 00 00
|
||||||
07 e5 0b 06 0e 37 36 01 00 00
|
07 e5 0b 06 0e 37 36 01 00 00
|
||||||
07 e5 0b 06 0e 37 1e 03 01 00
|
|
||||||
07 e5 0b 06 0e 36 37 01 01 00
|
07 e5 0b 06 0e 36 37 01 01 00
|
||||||
...
|
...
|
||||||
07 e5 0b 06 0d 30 2d 03 00 01 09 89 fe
|
07 e5 0b 06 0d 30 2d 03 00 01 09 89 fe
|
||||||
@ -916,7 +923,40 @@ void SSPMHandleReceivedData(void) {
|
|||||||
AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 1A 00 01 03 E5 45 EB
|
AA 55 01 00 00 00 00 00 00 00 00 00 00 00 00 80 1A 00 01 03 E5 45 EB
|
||||||
| |
|
| |
|
||||||
*/
|
*/
|
||||||
|
if (Sspm->log_relay < 255) {
|
||||||
|
uint32_t module = Sspm->log_relay >> 2;
|
||||||
|
uint32_t channel = Sspm->log_relay & 0x03; // Channel relays are NOT bit masked this time
|
||||||
|
Response_P(PSTR("{\"SSPMLog%d\":"), Sspm->log_relay +1);
|
||||||
|
if (Sspm->expected_bytes < 15) {
|
||||||
|
ResponseAppend_P(PSTR("\"Error%d\"}"), SspmBuffer[19]);
|
||||||
|
} else if (module != SSPMGetModuleNumberFromMap(SspmBuffer[20] << 8 | SspmBuffer[21])) {
|
||||||
|
ResponseAppend_P(PSTR("\"Wrong module\"}"));
|
||||||
|
} else {
|
||||||
|
uint32_t entries = SspmBuffer[32];
|
||||||
|
uint32_t offset = 33;
|
||||||
|
bool more = false;
|
||||||
|
for (uint32_t i = 0; i < entries; i++) {
|
||||||
|
if (SspmBuffer[offset +7] == channel) {
|
||||||
|
uint32_t year = SspmBuffer[offset] << 8 | SspmBuffer[offset +1];
|
||||||
|
char stemp[10]; // One of "App|Device|Overload|Overtemp"
|
||||||
|
ResponseAppend_P(PSTR("%s{\"Time\":\"%d-%02d-%02dT%02d:%02d:%02d\",\"Trigger\":\"%s\",\"State\":\"%s\"}"),
|
||||||
|
(more)?",":"[", year, SspmBuffer[offset +2], SspmBuffer[offset +3],
|
||||||
|
SspmBuffer[offset +4], SspmBuffer[offset +5], SspmBuffer[offset +6],
|
||||||
|
GetTextIndexed(stemp, sizeof(stemp), SspmBuffer[offset +9] & 0x03, kSSPMTriggers),
|
||||||
|
GetStateText(SspmBuffer[offset +8]));
|
||||||
|
more = true;
|
||||||
|
}
|
||||||
|
offset += 10;
|
||||||
|
}
|
||||||
|
if (more) {
|
||||||
|
ResponseAppend_P(PSTR("]}"));
|
||||||
|
}else {
|
||||||
|
ResponseAppend_P(PSTR("\"None\"}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("SSPMLog"));
|
||||||
|
Sspm->log_relay = 255; // Disable display energy history
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SSPM_FUNC_ENERGY_PERIOD:
|
case SSPM_FUNC_ENERGY_PERIOD:
|
||||||
/* 0x1B
|
/* 0x1B
|
||||||
@ -1146,9 +1186,7 @@ void SSPMSerialInput(void) {
|
|||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
void SSPMInit(void) {
|
void SSPMInit(void) {
|
||||||
if (!ValidTemplate(PSTR("Sonoff SPM (POC1)")) &&
|
if (!ValidTemplate(PSTR("Sonoff SPM")) || !PinUsed(GPIO_RXD) || !PinUsed(GPIO_TXD)) { return; }
|
||||||
!ValidTemplate(PSTR("Sonoff SPM (POC2)"))) { return; }
|
|
||||||
if (!PinUsed(GPIO_RXD) || !PinUsed(GPIO_TXD)) { return; }
|
|
||||||
|
|
||||||
Sspm = (TSspm*)calloc(sizeof(TSspm), 1); // Need calloc to reset registers to 0/false
|
Sspm = (TSspm*)calloc(sizeof(TSspm), 1); // Need calloc to reset registers to 0/false
|
||||||
if (!Sspm) { return; }
|
if (!Sspm) { return; }
|
||||||
@ -1187,7 +1225,8 @@ void SSPMInit(void) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Sspm->history_channel = 5; // Disable display energy history
|
Sspm->history_relay = 255; // Disable display energy history
|
||||||
|
Sspm->log_relay = 255; // Disable display logging
|
||||||
Sspm->old_power = TasmotaGlobal.power;
|
Sspm->old_power = TasmotaGlobal.power;
|
||||||
Sspm->mstate = SPM_WAIT; // Start init sequence
|
Sspm->mstate = SPM_WAIT; // Start init sequence
|
||||||
}
|
}
|
||||||
@ -1485,11 +1524,14 @@ void (* const SSPMCommand[])(void) PROGMEM = {
|
|||||||
&CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMHistory, &CmndSSPMScan, &CmndSSPMIamHere, &CmndSSPMDisplay, &CmndSSPMReset, &CmndSSPMMap };
|
&CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMHistory, &CmndSSPMScan, &CmndSSPMIamHere, &CmndSSPMDisplay, &CmndSSPMReset, &CmndSSPMMap };
|
||||||
|
|
||||||
void CmndSSPMLog(void) {
|
void CmndSSPMLog(void) {
|
||||||
// Report 29 log entries
|
// SspmLog<relay> - Report from up to 29 latest log entries
|
||||||
|
// SspmLog<relay> 10 - Report from up to 10 latest log entries
|
||||||
|
// SspmLog<relay> 100 - Report from up to 29 log entries
|
||||||
if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; }
|
if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; }
|
||||||
XdrvMailbox.payload &= 0xFFFF; // Max 65000 entries
|
if ((XdrvMailbox.payload < 1) || (XdrvMailbox.payload > 65000)) { XdrvMailbox.payload = 28; }
|
||||||
SSPMSendGetLog(XdrvMailbox.index -1, XdrvMailbox.payload +1);
|
Sspm->log_relay = XdrvMailbox.index -1;
|
||||||
ResponseCmndDone();
|
SSPMSendGetLog(Sspm->log_relay, XdrvMailbox.payload +1);
|
||||||
|
ResponseClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSSPMEnergy(void) {
|
void CmndSSPMEnergy(void) {
|
||||||
@ -1499,11 +1541,11 @@ void CmndSSPMEnergy(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CmndSSPMHistory(void) {
|
void CmndSSPMHistory(void) {
|
||||||
|
// Retreive daily history of one relay up to six month
|
||||||
|
// SspmHistory<relay>
|
||||||
if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; }
|
if ((XdrvMailbox.index < 1) || (XdrvMailbox.index > TasmotaGlobal.devices_present)) { XdrvMailbox.index = 1; }
|
||||||
uint32_t relay = XdrvMailbox.index -1;
|
Sspm->history_relay = XdrvMailbox.index -1;
|
||||||
Sspm->history_module = relay >> 2;
|
SSPMSendGetEnergyTotal(Sspm->history_relay);
|
||||||
Sspm->history_channel = relay & 0x03; // Channel relays are NOT bit masked this time
|
|
||||||
SSPMSendGetEnergyTotal(XdrvMailbox.index -1);
|
|
||||||
ResponseClear();
|
ResponseClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user