From 3a92189c44eb61a9b8c1c3ced875451a221a5b0a Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Sat, 4 Dec 2021 12:26:19 +0100
Subject: [PATCH] Add command SspmDisplay
Add command ``SspmDisplay 0/1`` to change GUI display to powered on relays only.
---
tasmota/xdrv_86_esp32_sonoff_spm.ino | 106 +++++++++++++++++----------
1 file changed, 68 insertions(+), 38 deletions(-)
diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino
index 9f858691b..afe70b115 100644
--- a/tasmota/xdrv_86_esp32_sonoff_spm.ino
+++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino
@@ -175,6 +175,7 @@ typedef struct {
uint8_t command_sequence;
uint8_t mstate;
uint8_t last_button;
+ uint8_t gui_display;
bool discovery_triggered;
} TSspm;
@@ -1082,29 +1083,30 @@ bool SSPMButton(void) {
/*********************************************************************************************/
const uint16_t SSPM_SIZE = 128;
-const char kSSPMEnergyPhases[] PROGMEM = "%*_f
%*_f | %*_f | %*_f | |[%*_f,%*_f,%*_f,%*_f]";
-char* SSPMEnergyFormat(char* result, float* input, uint32_t resolution, bool json) {
- char layout[100];
- GetTextIndexed(layout, sizeof(layout), json, kSSPMEnergyPhases);
- ext_snprintf_P(result, SSPM_SIZE, layout, resolution, &input[0], resolution, &input[1], resolution, &input[2], resolution, &input[3]);
+char* SSPMEnergyFormat(char* result, float* input, uint32_t resolution, uint8_t* indirect, uint8_t offset, uint32_t count) {
+ result[0] = '\0';
+ for (uint32_t i = 0; i < count; i++) {
+ ext_snprintf_P(result, SSPM_SIZE, PSTR("%s | %*_f | "), result, resolution, &input[indirect[offset +i]]);
+ }
+ ext_snprintf_P(result, SSPM_SIZE, PSTR("%s"), result);
return result;
}
const char HTTP_SSPM_VOLTAGE[] PROGMEM =
- "{s}" D_VOLTAGE " | %s" D_UNIT_VOLT "{e}"; // {s} = | , {m} = | , {e} = |
+ "{s}" D_VOLTAGE "%s" D_UNIT_VOLT "{e}"; // {s} = , {m} = | , {e} = |
const char HTTP_SSPM_CURRENT[] PROGMEM =
- "{s}" D_CURRENT "%s" D_UNIT_AMPERE "{e}";
+ "{s}" D_CURRENT "%s" D_UNIT_AMPERE "{e}";
const char HTTP_SSPM_POWER[] PROGMEM =
- "{s}" D_POWERUSAGE_ACTIVE " | %s" D_UNIT_WATT "{e}";
+ "{s}" D_POWERUSAGE_ACTIVE "%s" D_UNIT_WATT "{e}";
const char HTTP_SSPM_POWER2[] PROGMEM =
- "{s}" D_POWERUSAGE_APPARENT " | %s" D_UNIT_VA "{e}"
- "{s}" D_POWERUSAGE_REACTIVE " | %s" D_UNIT_VAR "{e}"
- "{s}" D_POWER_FACTOR " | %s{e}";
+ "{s}" D_POWERUSAGE_APPARENT "%s" D_UNIT_VA "{e}"
+ "{s}" D_POWERUSAGE_REACTIVE "%s" D_UNIT_VAR "{e}"
+ "{s}" D_POWER_FACTOR "%s{e}";
const char HTTP_SSPM_ENERGY[] PROGMEM =
- "{s}" D_ENERGY_TODAY " | %s" D_UNIT_KILOWATTHOUR "{e}"
- "{s}" D_ENERGY_YESTERDAY " | %s" D_UNIT_KILOWATTHOUR "{e}"
- "{s}" D_ENERGY_TOTAL " | %s" D_UNIT_KILOWATTHOUR "{e}";
+ "{s}" D_ENERGY_TODAY "%s" D_UNIT_KILOWATTHOUR "{e}"
+ "{s}" D_ENERGY_YESTERDAY "%s" D_UNIT_KILOWATTHOUR "{e}"
+ "{s}" D_ENERGY_TOTAL "%s" D_UNIT_KILOWATTHOUR "{e}";
void SSPMEnergyShow(bool json) {
if (!TasmotaGlobal.devices_present) { return; } // Not ready yet
@@ -1152,30 +1154,50 @@ void SSPMEnergyShow(bool json) {
}
ResponseAppend_P(PSTR("]}"));
} else {
- Sspm->rotate++;
- if (Sspm->rotate >= TasmotaGlobal.devices_present) {
- Sspm->rotate = 0;
+ uint8_t relay[SSPM_MAX_MODULES * 4];
+ uint8_t indirect[SSPM_MAX_MODULES * 4];
+
+ uint32_t index = 0;
+ power_t power = TasmotaGlobal.power;
+ for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) {
+ if ((0 == Sspm->gui_display) ||
+ ((1 == Sspm->gui_display) && (power >> i) &1)) {
+ relay[index] = i +1;
+ indirect[index] = i;
+ index++;
+ }
}
- uint32_t module = Sspm->rotate >> 2;
- uint32_t relay_base = module * 4;
- WSContentSend_P(PSTR("{t}{s}")); // First column is empty ({t} = , {s} = )
- for (uint32_t i = 1; i < 5; i++) {
- WSContentSend_P(PSTR(" | L%d"), relay_base +i);
+
+ if (index) {
+ uint32_t offset = 0;
+ if (index > 4) {
+ Sspm->rotate++;
+ if (Sspm->rotate >= ((index -1) >> 2) << 3) {
+ Sspm->rotate = 0;
+ }
+ offset = (Sspm->rotate >> 2) * 4;
+ }
+ uint32_t count = index - offset;
+ if (count > 4) { count = 4; }
+ WSContentSend_P(PSTR(" |
---|
{t}{s}")); // First column is empty ({t} = , {s} = )
+ for (uint32_t i = 0; i < count; i++) {
+ WSContentSend_P(PSTR(" | L%d"), relay[offset +i]);
+ }
+ WSContentSend_P(PSTR(" | {e}")); // Last column is units ({e} = | )
+ char value_chr[SSPM_SIZE];
+ WSContentSend_PD(HTTP_SSPM_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[0], Settings->flag2.voltage_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_SSPM_CURRENT, SSPMEnergyFormat(value_chr, Sspm->current[0], Settings->flag2.current_resolution, indirect, offset, count));
+ WSContentSend_PD(HTTP_SSPM_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[0], Settings->flag2.wattage_resolution, indirect, offset, count));
+ char valu2_chr[SSPM_SIZE];
+ char valu3_chr[SSPM_SIZE];
+ WSContentSend_PD(HTTP_SSPM_POWER2, SSPMEnergyFormat(value_chr, Sspm->apparent_power[0], Settings->flag2.wattage_resolution, indirect, offset, count),
+ SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[0], Settings->flag2.wattage_resolution, indirect, offset, count),
+ SSPMEnergyFormat(valu3_chr, Sspm->power_factor[0], 2, indirect, offset, count));
+ WSContentSend_PD(HTTP_SSPM_ENERGY, SSPMEnergyFormat(value_chr, Sspm->energy_today[0], Settings->flag2.energy_resolution, indirect, offset, count),
+ SSPMEnergyFormat(valu2_chr, Sspm->energy_yesterday[0], Settings->flag2.energy_resolution, indirect, offset, count),
+ SSPMEnergyFormat(valu3_chr, Sspm->energy_total[0], Settings->flag2.energy_resolution, indirect, offset, count));
+ WSContentSend_P(PSTR(" {t}")); // {t} = - Define for next FUNC_WEB_SENSOR
}
- WSContentSend_P(PSTR("{e}")); // Last column is units ({e} = | )
- char value_chr[SSPM_SIZE];
- WSContentSend_PD(HTTP_SSPM_VOLTAGE, SSPMEnergyFormat(value_chr, Sspm->voltage[module], Settings->flag2.voltage_resolution, json));
- WSContentSend_PD(HTTP_SSPM_CURRENT, SSPMEnergyFormat(value_chr, Sspm->current[module], Settings->flag2.current_resolution, json));
- WSContentSend_PD(HTTP_SSPM_POWER, SSPMEnergyFormat(value_chr, Sspm->active_power[module], Settings->flag2.wattage_resolution, json));
- char valu2_chr[SSPM_SIZE];
- char valu3_chr[SSPM_SIZE];
- WSContentSend_PD(HTTP_SSPM_POWER2, SSPMEnergyFormat(value_chr, Sspm->apparent_power[module], Settings->flag2.wattage_resolution, json),
- SSPMEnergyFormat(valu2_chr, Sspm->reactive_power[module], Settings->flag2.wattage_resolution, json),
- SSPMEnergyFormat(valu3_chr, Sspm->power_factor[module], 2, json));
- WSContentSend_PD(HTTP_SSPM_ENERGY, SSPMEnergyFormat(value_chr, Sspm->energy_today[module], Settings->flag2.energy_resolution, json),
- SSPMEnergyFormat(valu2_chr, Sspm->energy_yesterday[module], Settings->flag2.energy_resolution, json),
- SSPMEnergyFormat(valu3_chr, Sspm->energy_total[module], Settings->flag2.energy_resolution, json));
- WSContentSend_P(PSTR(" {t}")); // {t} = - Define for next FUNC_WEB_SENSOR
}
}
@@ -1184,10 +1206,10 @@ void SSPMEnergyShow(bool json) {
\*********************************************************************************************/
const char kSSPMCommands[] PROGMEM = "SSPM|" // Prefix
- "Log|Energy|History|Scan|IamHere" ;
+ "Log|Energy|History|Scan|IamHere|Display" ;
void (* const SSPMCommand[])(void) PROGMEM = {
- &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMEnergyHistory, &CmndSSPMScan, &CmndSSPMIamHere };
+ &CmndSSPMLog, &CmndSSPMEnergy, &CmndSSPMEnergyHistory, &CmndSSPMScan, &CmndSSPMIamHere, &CmndSSPMDisplay };
void CmndSSPMLog(void) {
// Report 29 log entries
@@ -1222,6 +1244,14 @@ void CmndSSPMIamHere(void) {
ResponseCmndDone();
}
+void CmndSSPMDisplay(void) {
+ // Select either all relays or only powered on relays
+ if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
+ Sspm->gui_display = XdrvMailbox.payload;
+ }
+ ResponseCmndNumber(Sspm->gui_display);
+}
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
|