mirror of https://github.com/arendst/Tasmota.git
Add ESP32 support for eigth energy phases/channels
- ESP32 support for eigth energy phases/channels - ESP32 command ``EnergyCols 1..8`` to change number of GUI columns - ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation - support for SEN5X gas and air quality sensor by Tyeth Gundry (#17736)
This commit is contained in:
parent
664b60332a
commit
db3fdc5118
|
@ -5,7 +5,10 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [12.3.1.5]
|
## [12.3.1.5]
|
||||||
### Added
|
### Added
|
||||||
- ESP32 Prep support for eigth energy phases/channels
|
- ESP32 support for eigth energy phases/channels
|
||||||
|
- ESP32 command ``EnergyCols 1..8`` to change number of GUI columns
|
||||||
|
- ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation
|
||||||
|
- support for SEN5X gas and air quality sensor by Tyeth Gundry (#17736)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
- Berry energy_ctypes changed with new energy driver
|
- Berry energy_ctypes changed with new energy driver
|
||||||
|
|
|
@ -117,11 +117,15 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
||||||
- Support for IPv6 only networks on Ethernet (not yet Wifi)
|
- Support for IPv6 only networks on Ethernet (not yet Wifi)
|
||||||
- Support for TM1650 display as used in some clocks by Stefan Oskamp [#17594](https://github.com/arendst/Tasmota/issues/17594)
|
- Support for TM1650 display as used in some clocks by Stefan Oskamp [#17594](https://github.com/arendst/Tasmota/issues/17594)
|
||||||
- Support for PCA9632 4-channel 8-bit PWM driver as light driver by Pascal Heinrich [#17557](https://github.com/arendst/Tasmota/issues/17557)
|
- Support for PCA9632 4-channel 8-bit PWM driver as light driver by Pascal Heinrich [#17557](https://github.com/arendst/Tasmota/issues/17557)
|
||||||
|
- support for SEN5X gas and air quality sensor by Tyeth Gundry [#17736](https://github.com/arendst/Tasmota/issues/17736)
|
||||||
- Berry support for ``crypto.SHA256`` [#17430](https://github.com/arendst/Tasmota/issues/17430)
|
- Berry support for ``crypto.SHA256`` [#17430](https://github.com/arendst/Tasmota/issues/17430)
|
||||||
- Berry crypto add ``EC_P256`` and ``PBKDF2_HMAC_SHA256`` algorithms required by Matter protocol [#17473](https://github.com/arendst/Tasmota/issues/17473)
|
- Berry crypto add ``EC_P256`` and ``PBKDF2_HMAC_SHA256`` algorithms required by Matter protocol [#17473](https://github.com/arendst/Tasmota/issues/17473)
|
||||||
- Berry crypto add ``random`` to generate series of random bytes
|
- Berry crypto add ``random`` to generate series of random bytes
|
||||||
- Berry crypto add ``HKDF_HMAC_SHA256``
|
- Berry crypto add ``HKDF_HMAC_SHA256``
|
||||||
- Berry crypto add ``SPAKE2P_Matter`` for Matter support
|
- Berry crypto add ``SPAKE2P_Matter`` for Matter support
|
||||||
|
- ESP32 command ``EnergyCols 1..8`` to change number of GUI columns
|
||||||
|
- ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation
|
||||||
|
- ESP32 support for eigth energy phases/channels
|
||||||
- ESP32 support for BMPxxx sensors on two I2C busses [#17643](https://github.com/arendst/Tasmota/issues/17643)
|
- ESP32 support for BMPxxx sensors on two I2C busses [#17643](https://github.com/arendst/Tasmota/issues/17643)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
|
@ -454,6 +454,8 @@
|
||||||
#define D_CMND_VOLTAGEHIGH "VoltageHigh"
|
#define D_CMND_VOLTAGEHIGH "VoltageHigh"
|
||||||
#define D_CMND_CURRENTLOW "CurrentLow"
|
#define D_CMND_CURRENTLOW "CurrentLow"
|
||||||
#define D_CMND_CURRENTHIGH "CurrentHigh"
|
#define D_CMND_CURRENTHIGH "CurrentHigh"
|
||||||
|
#define D_CMND_ENERGYDISPLAY "EnergyDisplay"
|
||||||
|
#define D_CMND_ENERGYCOLS "EnergyCols"
|
||||||
#define D_CMND_ENERGYTODAY "EnergyToday"
|
#define D_CMND_ENERGYTODAY "EnergyToday"
|
||||||
#define D_CMND_ENERGYYESTERDAY "EnergyYesterday"
|
#define D_CMND_ENERGYYESTERDAY "EnergyYesterday"
|
||||||
#define D_CMND_ENERGYTOTAL "EnergyTotal"
|
#define D_CMND_ENERGYTOTAL "EnergyTotal"
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
#undef ENERGY_MAX_PHASES
|
#undef ENERGY_MAX_PHASES
|
||||||
#define ENERGY_MAX_PHASES 8 // Support max eight phases/channels
|
#define ENERGY_MAX_PHASES 8 // Support max eight phases/channels
|
||||||
|
|
||||||
|
#define ENERGY_GUI_MAX_COLS 4 // [EnergyCols] Number of GUI data columns - Preffered 4
|
||||||
|
#define ENERGY_GUI_DISPLAY_MODE 3 // [EnergyDisplay] 1 = Rotate if over EnergyCols, 2 = Rotate only powered on if over EnergyCols, 3 = Use tabs if over EnergyCols
|
||||||
|
|
||||||
#include <Ticker.h>
|
#include <Ticker.h>
|
||||||
|
|
||||||
#define D_CMND_POWERCAL "PowerCal"
|
#define D_CMND_POWERCAL "PowerCal"
|
||||||
|
@ -47,6 +50,11 @@
|
||||||
#define D_CMND_TARIFF "Tariff"
|
#define D_CMND_TARIFF "Tariff"
|
||||||
#define D_CMND_MODULEADDRESS "ModuleAddress"
|
#define D_CMND_MODULEADDRESS "ModuleAddress"
|
||||||
|
|
||||||
|
enum EnergyDisplayModes {
|
||||||
|
ENERGY_DISPLAY_MIN_OPTION,
|
||||||
|
ENERGY_DISPLAY_ROTATE, ENERGY_DISPLAY_ROTATE_POWERED_ON, ENERGY_DISPLAY_TABS,
|
||||||
|
ENERGY_DISPLAY_MAX_OPTION };
|
||||||
|
|
||||||
enum EnergyCalibration {
|
enum EnergyCalibration {
|
||||||
ENERGY_POWER_CALIBRATION, ENERGY_VOLTAGE_CALIBRATION, ENERGY_CURRENT_CALIBRATION, ENERGY_FREQUENCY_CALIBRATION };
|
ENERGY_POWER_CALIBRATION, ENERGY_VOLTAGE_CALIBRATION, ENERGY_CURRENT_CALIBRATION, ENERGY_FREQUENCY_CALIBRATION };
|
||||||
|
|
||||||
|
@ -61,7 +69,8 @@ const char kEnergyCommands[] PROGMEM = "|" // No prefix
|
||||||
D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|"
|
D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|"
|
||||||
D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|"
|
D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|"
|
||||||
D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|"
|
D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|"
|
||||||
D_CMND_ENERGYTODAY "|" D_CMND_ENERGYYESTERDAY "|" D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYEXPORTACTIVE "|" D_CMND_ENERGYUSAGE "|" D_CMND_ENERGYEXPORT "|" D_CMND_TARIFF;
|
D_CMND_ENERGYTODAY "|" D_CMND_ENERGYYESTERDAY "|" D_CMND_ENERGYTOTAL "|" D_CMND_ENERGYEXPORTACTIVE "|" D_CMND_ENERGYUSAGE "|" D_CMND_ENERGYEXPORT "|"
|
||||||
|
D_CMND_TARIFF "|" D_CMND_ENERGYDISPLAY "|" D_CMND_ENERGYCOLS ;
|
||||||
|
|
||||||
void (* const EnergyCommand[])(void) PROGMEM = {
|
void (* const EnergyCommand[])(void) PROGMEM = {
|
||||||
&CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, &CmndFrequencyCal,
|
&CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, &CmndFrequencyCal,
|
||||||
|
@ -70,7 +79,8 @@ void (* const EnergyCommand[])(void) PROGMEM = {
|
||||||
&CmndMaxEnergy, &CmndMaxEnergyStart,
|
&CmndMaxEnergy, &CmndMaxEnergyStart,
|
||||||
&CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow,
|
&CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow,
|
||||||
&CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow,
|
&CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow,
|
||||||
&CmndEnergyToday, &CmndEnergyYesterday, &CmndEnergyTotal, &CmndEnergyExportActive, &CmndEnergyUsage, &CmndEnergyExport, &CmndTariff};
|
&CmndEnergyToday, &CmndEnergyYesterday, &CmndEnergyTotal, &CmndEnergyExportActive, &CmndEnergyUsage, &CmndEnergyExport,
|
||||||
|
&CmndTariff, &CmndEnergyDisplay, &CmndEnergyCols };
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
@ -81,16 +91,40 @@ typedef struct {
|
||||||
float last_usage_total_kWh;
|
float last_usage_total_kWh;
|
||||||
} tEnergyUsage;
|
} tEnergyUsage;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint16_t data;
|
||||||
|
struct {
|
||||||
|
uint16_t spare00 : 1; // bit 0
|
||||||
|
uint16_t spare01 : 1; // bit 1
|
||||||
|
uint16_t spare02 : 1; // bit 2
|
||||||
|
uint16_t spare03 : 1; // bit 3
|
||||||
|
uint16_t spare04 : 1; // bit 4
|
||||||
|
uint16_t spare05 : 1; // bit 5
|
||||||
|
uint16_t spare06 : 1; // bit 6
|
||||||
|
uint16_t spare07 : 1; // bit 7
|
||||||
|
uint16_t spare08 : 1; // bit 8
|
||||||
|
uint16_t spare09 : 1; // bit 9
|
||||||
|
uint16_t spare10 : 1; // bit 10
|
||||||
|
uint16_t spare11 : 1; // bit 11
|
||||||
|
uint16_t spare12 : 1; // bit 12
|
||||||
|
uint16_t spare13 : 1; // bit 13
|
||||||
|
uint16_t spare14 : 1; // bit 14
|
||||||
|
uint16_t spare15 : 1; // bit 15
|
||||||
|
};
|
||||||
|
} tEnergyBitfield;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t crc32; // To detect file changes
|
uint32_t crc32; // To detect file changes
|
||||||
uint16_t version; // To detect driver function changes
|
uint16_t version; // To detect driver function changes
|
||||||
uint16_t energy_kWhdoy;
|
uint16_t energy_kWhdoy;
|
||||||
uint32_t energy_kWhtotal_time;
|
uint32_t energy_kWhtotal_time;
|
||||||
uint32_t spare1;
|
tEnergyBitfield flag;
|
||||||
uint32_t spare2;
|
uint8_t gui_display; // EnergyDisplay - GUI display all relays (0), only powered on relays (1) or user selected relays (2)
|
||||||
uint32_t spare3;
|
uint8_t gui_cols; // EnergyCols
|
||||||
uint32_t spare4;
|
uint32_t spare32_1;
|
||||||
uint32_t spare5;
|
uint32_t spare32_2;
|
||||||
|
uint32_t spare32_3;
|
||||||
|
uint32_t spare32_4;
|
||||||
|
|
||||||
uint32_t power_calibration[ENERGY_MAX_PHASES];
|
uint32_t power_calibration[ENERGY_MAX_PHASES];
|
||||||
uint32_t voltage_calibration[ENERGY_MAX_PHASES];
|
uint32_t voltage_calibration[ENERGY_MAX_PHASES];
|
||||||
|
@ -137,36 +171,39 @@ typedef struct {
|
||||||
float daily_sum_import_balanced; // 123.123 kWh
|
float daily_sum_import_balanced; // 123.123 kWh
|
||||||
float daily_sum_export_balanced; // 123.123 kWh
|
float daily_sum_export_balanced; // 123.123 kWh
|
||||||
|
|
||||||
|
uint16_t power_history[ENERGY_MAX_PHASES][3];
|
||||||
|
uint16_t mplh_counter;
|
||||||
|
uint16_t mplw_counter;
|
||||||
|
|
||||||
|
uint8_t data_valid[ENERGY_MAX_PHASES];
|
||||||
|
uint8_t phase_count; // Number of phases active
|
||||||
uint8_t fifth_second;
|
uint8_t fifth_second;
|
||||||
uint8_t command_code;
|
uint8_t command_code;
|
||||||
uint8_t data_valid[ENERGY_MAX_PHASES];
|
uint8_t power_steady_counter; // Allow for power on stabilization
|
||||||
|
uint8_t mplr_counter;
|
||||||
|
uint8_t max_energy_state;
|
||||||
|
|
||||||
|
uint8_t gui_indirect[ENERGY_MAX_PHASES];
|
||||||
|
uint8_t gui_rotate;
|
||||||
|
uint8_t gui_count;
|
||||||
|
uint8_t gui_offset;
|
||||||
|
|
||||||
uint8_t phase_count; // Number of phases active
|
|
||||||
bool voltage_common; // Use common voltage
|
bool voltage_common; // Use common voltage
|
||||||
bool frequency_common; // Use common frequency
|
bool frequency_common; // Use common frequency
|
||||||
bool use_overtemp; // Use global temperature as overtemp trigger on internal energy monitor hardware
|
bool use_overtemp; // Use global temperature as overtemp trigger on internal energy monitor hardware
|
||||||
bool kWhtoday_offset_init;
|
bool kWhtoday_offset_init;
|
||||||
|
|
||||||
bool voltage_available; // Enable if voltage is measured
|
bool voltage_available; // Enable if voltage is measured
|
||||||
bool current_available; // Enable if current is measured
|
bool current_available; // Enable if current is measured
|
||||||
bool local_energy_active_export; // Enable if support for storing energy_active
|
bool local_energy_active_export; // Enable if support for storing energy_active
|
||||||
|
|
||||||
bool type_dc;
|
bool type_dc;
|
||||||
bool power_on;
|
bool power_on;
|
||||||
|
|
||||||
uint16_t power_history[ENERGY_MAX_PHASES][3];
|
|
||||||
uint8_t power_steady_counter; // Allow for power on stabilization
|
|
||||||
bool min_power_flag;
|
bool min_power_flag;
|
||||||
bool max_power_flag;
|
bool max_power_flag;
|
||||||
bool min_voltage_flag;
|
bool min_voltage_flag;
|
||||||
bool max_voltage_flag;
|
bool max_voltage_flag;
|
||||||
bool min_current_flag;
|
bool min_current_flag;
|
||||||
bool max_current_flag;
|
bool max_current_flag;
|
||||||
|
|
||||||
uint16_t mplh_counter;
|
|
||||||
uint16_t mplw_counter;
|
|
||||||
uint8_t mplr_counter;
|
|
||||||
uint8_t max_energy_state;
|
|
||||||
} tEnergy;
|
} tEnergy;
|
||||||
|
|
||||||
tEnergy *Energy = nullptr;
|
tEnergy *Energy = nullptr;
|
||||||
|
@ -240,7 +277,7 @@ bool EnergyRtcSettingsValid(void) {
|
||||||
* Driver Settings load and save using filesystem
|
* Driver Settings load and save using filesystem
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
const uint32_t XDRV_03_VERSION = 0x0101; // Latest driver version (See settings deltas below)
|
const uint32_t XDRV_03_VERSION = 0x0102; // Latest driver version (See settings deltas below)
|
||||||
|
|
||||||
void EnergySettingsLoad(void) {
|
void EnergySettingsLoad(void) {
|
||||||
// *** Start init default values in case file is not found ***
|
// *** Start init default values in case file is not found ***
|
||||||
|
@ -270,6 +307,11 @@ void EnergySettingsLoad(void) {
|
||||||
|
|
||||||
Energy->Settings.power_delta[i] = (float)(Settings->energy_power_delta[i]);
|
Energy->Settings.power_delta[i] = (float)(Settings->energy_power_delta[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v0102 additions
|
||||||
|
Energy->Settings.gui_display = ENERGY_GUI_DISPLAY_MODE;
|
||||||
|
Energy->Settings.gui_cols = ENERGY_GUI_MAX_COLS;
|
||||||
|
|
||||||
// *** End Init default values ***
|
// *** End Init default values ***
|
||||||
|
|
||||||
#ifndef USE_UFILESYS
|
#ifndef USE_UFILESYS
|
||||||
|
@ -283,6 +325,10 @@ void EnergySettingsLoad(void) {
|
||||||
if (Energy->Settings.version != XDRV_03_VERSION) { // Fix version dependent changes
|
if (Energy->Settings.version != XDRV_03_VERSION) { // Fix version dependent changes
|
||||||
|
|
||||||
// *** Start fix possible setting deltas ***
|
// *** Start fix possible setting deltas ***
|
||||||
|
if (Energy->Settings.version < 0x0102) {
|
||||||
|
Energy->Settings.gui_display = ENERGY_GUI_DISPLAY_MODE;
|
||||||
|
Energy->Settings.gui_cols = ENERGY_GUI_MAX_COLS;
|
||||||
|
}
|
||||||
|
|
||||||
// *** End setting deltas ***
|
// *** End setting deltas ***
|
||||||
|
|
||||||
|
@ -346,7 +392,7 @@ char* EnergyFormat(char* result, float* input, uint32_t resolution, uint32_t sin
|
||||||
}
|
}
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
for (uint32_t i = 0; i < index; i++) {
|
for (uint32_t i = 0; i < index; i++) {
|
||||||
ext_snprintf_P(result, TOPSZ, PSTR("%s%s%*_f%s"), result, (0==i)?(1==index)?"":"[":",", resolution, &input[i], (index-1==i)?(1==index)?"":"]":"");
|
ext_snprintf_P(result, GUISZ, PSTR("%s%s%*_f%s"), result, (0==i)?(1==index)?"":"[":",", resolution, &input[i], (index-1==i)?(1==index)?"":"]":"");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -372,20 +418,20 @@ char* WebEnergyFormat(char* result, float* input, uint32_t resolution, uint32_t
|
||||||
}
|
}
|
||||||
#ifdef USE_ENERGY_COLUMN_GUI
|
#ifdef USE_ENERGY_COLUMN_GUI
|
||||||
ext_snprintf_P(result, GUISZ, PSTR("</td>")); // Skip first column
|
ext_snprintf_P(result, GUISZ, PSTR("</td>")); // Skip first column
|
||||||
if ((Energy->phase_count > 1) && single) { // Need to set colspan so need new columns
|
if ((Energy->gui_count > 1) && single) { // Need to set colspan so need new columns
|
||||||
// </td><td colspan='3' style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td colspan='3' style='text-align:right'>1.23</td><td> </td><td>
|
||||||
// </td><td colspan='5' style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td colspan='5' style='text-align:right'>1.23</td><td> </td><td>
|
||||||
// </td><td colspan='7' style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td colspan='7' style='text-align:right'>1.23</td><td> </td><td>
|
||||||
ext_snprintf_P(result, GUISZ, PSTR("%s<td colspan='%d' style='text-align:%s'>%*_f</td><td> </td>"),
|
ext_snprintf_P(result, GUISZ, PSTR("%s<td colspan='%d' style='text-align:%s'>%*_f</td><td> </td>"),
|
||||||
result, (Energy->phase_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[0]);
|
result, (Energy->gui_count *2) -1, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), resolution, &input[Energy->gui_indirect[0]]);
|
||||||
} else {
|
} else {
|
||||||
// </td><td style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td style='text-align:right'>1.23</td><td> </td><td>
|
||||||
// </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td>
|
||||||
// </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td>
|
||||||
// </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td>
|
// </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td style='text-align:right'>1.23</td><td> </td><td>
|
||||||
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
for (uint32_t i = 0; i < Energy->gui_count; i++) {
|
||||||
ext_snprintf_P(result, GUISZ, PSTR("%s<td style='text-align:%s'>%*_f</td><td> </td>"),
|
ext_snprintf_P(result, GUISZ, PSTR("%s<td style='text-align:%s'>%*_f</td><td> </td>"),
|
||||||
result, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[i]);
|
result, (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("left"), resolution, &input[Energy->gui_indirect[Energy->gui_offset +i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ext_snprintf_P(result, GUISZ, PSTR("%s<td>"), result);
|
ext_snprintf_P(result, GUISZ, PSTR("%s<td>"), result);
|
||||||
|
@ -665,7 +711,7 @@ void EnergyMarginCheck(void) {
|
||||||
for (uint32_t phase = 0; phase < Energy->phase_count; phase++) {
|
for (uint32_t phase = 0; phase < Energy->phase_count; phase++) {
|
||||||
power_diff_f[phase] = power_diff[phase];
|
power_diff_f[phase] = power_diff[phase];
|
||||||
}
|
}
|
||||||
char value_chr[TOPSZ];
|
char value_chr[GUISZ];
|
||||||
ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFormat(value_chr, power_diff_f, 0));
|
ResponseAppend_P(PSTR("\"" D_CMND_POWERDELTA "\":%s"), EnergyFormat(value_chr, power_diff_f, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,9 +879,9 @@ void EnergyEverySecond(void) {
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void ResponseCmndEnergyTotalYesterdayToday(void) {
|
void ResponseCmndEnergyTotalYesterdayToday(void) {
|
||||||
char value_chr[TOPSZ]; // Used by EnergyFormatIndex
|
char value_chr[GUISZ]; // Used by EnergyFormatIndex
|
||||||
char value2_chr[TOPSZ];
|
char value2_chr[GUISZ];
|
||||||
char value3_chr[TOPSZ];
|
char value3_chr[GUISZ];
|
||||||
|
|
||||||
float energy_yesterday_kWh[3];
|
float energy_yesterday_kWh[3];
|
||||||
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
||||||
|
@ -858,6 +904,26 @@ void ResponseCmndEnergyTotalYesterdayToday(void) {
|
||||||
ResponseJsonEndEnd();
|
ResponseJsonEndEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CmndEnergyDisplay(void) {
|
||||||
|
// Select either all relays, only powered on relays or user selected relay group
|
||||||
|
// EnergyDisplay 1, EnergyDisplay 2 or EnergyDisplay 3
|
||||||
|
if ((XdrvMailbox.payload > ENERGY_DISPLAY_MIN_OPTION) && (XdrvMailbox.payload < ENERGY_DISPLAY_MAX_OPTION)) {
|
||||||
|
Energy->Settings.gui_display = XdrvMailbox.payload;
|
||||||
|
Energy->gui_rotate = 0;
|
||||||
|
}
|
||||||
|
ResponseCmndNumber(Energy->Settings.gui_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CmndEnergyCols(void) {
|
||||||
|
// Select number of columns
|
||||||
|
// EnergyCols 1..8
|
||||||
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= ENERGY_MAX_PHASES)) {
|
||||||
|
Energy->Settings.gui_cols = XdrvMailbox.payload;
|
||||||
|
Energy->gui_rotate = 0;
|
||||||
|
}
|
||||||
|
ResponseCmndNumber(Energy->Settings.gui_cols);
|
||||||
|
}
|
||||||
|
|
||||||
void CmndEnergyTotal(void) {
|
void CmndEnergyTotal(void) {
|
||||||
uint32_t values[2] = { 0 };
|
uint32_t values[2] = { 0 };
|
||||||
uint32_t params = ParseParameters(2, values);
|
uint32_t params = ParseParameters(2, values);
|
||||||
|
@ -1536,55 +1602,114 @@ void EnergyShow(bool json) {
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_ENERGY_COLUMN_GUI
|
#ifdef USE_ENERGY_COLUMN_GUI
|
||||||
// Need a new table supporting more columns using empty columns (with in data rows) as easy column spacing
|
uint8_t relays[ENERGY_MAX_PHASES];
|
||||||
// {s}</th><th></th><th>Head1</th><th></th><td>{e}
|
uint32_t relay_show = 0;
|
||||||
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><td>{e}
|
power_t power = TasmotaGlobal.power;
|
||||||
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><td>{e}
|
for (uint32_t i = 0; i < Energy->phase_count; i++) { // Init relays and gui_indirect tables based on EnergyDisplay
|
||||||
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><th>Head4</th><th></th><td>{e}
|
if ((ENERGY_DISPLAY_ROTATE == Energy->Settings.gui_display) ||
|
||||||
WSContentSend_P(PSTR("</table><hr/>{t}{s}</th><th></th>")); // First column is empty ({t} = <table style='width:100%'>, {s} = <tr><th>)
|
((ENERGY_DISPLAY_ROTATE_POWERED_ON == Energy->Settings.gui_display) && (power >> i) &1) ||
|
||||||
bool label_o = Energy->voltage_common;
|
(ENERGY_DISPLAY_TABS == Energy->Settings.gui_display)) {
|
||||||
bool no_label = (1 == Energy->phase_count);
|
relays[relay_show] = i +1;
|
||||||
for (uint32_t i = 0; i < Energy->phase_count; i++) {
|
Energy->gui_indirect[relay_show] = i;
|
||||||
WSContentSend_P(PSTR("<th style='text-align:center'>%s%s<th></th>"), (no_label)?"":(label_o)?"O":"L", (no_label)?"":itoa(i +1, value_chr, 10));
|
relay_show++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WSContentSend_P(PSTR("<td>{e}")); // Last column is units ({e} = </td></tr>)
|
|
||||||
|
if (relay_show) {
|
||||||
|
if (Energy->Settings.gui_display != ENERGY_DISPLAY_TABS) {
|
||||||
|
if (relay_show > Energy->Settings.gui_cols) {
|
||||||
|
Energy->gui_rotate++;
|
||||||
|
} else {
|
||||||
|
Energy->gui_rotate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Energy->gui_rotate >= relay_show) {
|
||||||
|
Energy->gui_rotate = 0;
|
||||||
|
}
|
||||||
|
Energy->gui_offset = (Energy->gui_rotate / Energy->Settings.gui_cols) * Energy->Settings.gui_cols;
|
||||||
|
Energy->gui_count = relay_show - Energy->gui_offset;
|
||||||
|
if (Energy->gui_count > Energy->Settings.gui_cols) { Energy->gui_count = Energy->Settings.gui_cols; }
|
||||||
|
|
||||||
|
WSContentSend_P(PSTR("</table><hr/>")); // Close current table as we will use different column count
|
||||||
|
bool label_o = Energy->voltage_common;
|
||||||
|
if (ENERGY_DISPLAY_TABS == Energy->Settings.gui_display) {
|
||||||
|
uint32_t tabs = (relay_show -1 + Energy->Settings.gui_cols) / Energy->Settings.gui_cols;
|
||||||
|
if (tabs > 1) {
|
||||||
|
WSContentSend_P(PSTR("{t}<tr>")); // {t} = <table style='width:100%'>
|
||||||
|
uint32_t cols_width = 100 / tabs;
|
||||||
|
uint32_t current_tab = Energy->gui_rotate / Energy->Settings.gui_cols;
|
||||||
|
for (uint32_t idx = 0; idx < tabs; idx++) {
|
||||||
|
WSContentSend_P(PSTR("<td style='width:%d%%'><button style='border-radius:0;background:#%06X;font-weight:%s' onclick='la(\"&k03=%d\");'>%s%d</button></td>"), // &k03 is related to WebGetArg("k", tmp, sizeof(tmp));
|
||||||
|
cols_width,
|
||||||
|
(current_tab == idx) ? WebColor(COL_BACKGROUND) : WebColor(COL_FORM),
|
||||||
|
(current_tab == idx) ? "bold" : "normal",
|
||||||
|
idx,
|
||||||
|
(label_o) ? "O" : "L", (idx *Energy->Settings.gui_cols) +1);
|
||||||
|
}
|
||||||
|
WSContentSend_P(PSTR("</tr></table>")); // Close current table as we will use different column count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// {s}</th><th></th><th>Head1</th><th></th><td>{e}
|
||||||
|
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><td>{e}
|
||||||
|
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><td>{e}
|
||||||
|
// {s}</th><th></th><th>Head1</th><th></th><th>Head2</th><th></th><th>Head3</th><th></th><th>Head4</th><th></th><td>{e}
|
||||||
|
WSContentSend_P(PSTR("{t}{s}</th><th></th>")); // First column is empty ({t} = <table style='width:100%'>, {s} = <tr><th>)
|
||||||
|
bool no_label = (1 == Energy->phase_count);
|
||||||
|
for (uint32_t i = 0; i < Energy->gui_count; i++) {
|
||||||
|
WSContentSend_P(PSTR("<th style='text-align:center'>%s%s<th></th>"),
|
||||||
|
(no_label) ? "" : (label_o) ? "O" : "L",
|
||||||
|
(no_label) ? "" : itoa(relays[Energy->gui_offset +i], value_chr, 10));
|
||||||
|
}
|
||||||
|
WSContentSend_P(PSTR("<td>{e}")); // Last column is units ({e} = </td></tr>)
|
||||||
#endif // USE_ENERGY_COLUMN_GUI
|
#endif // USE_ENERGY_COLUMN_GUI
|
||||||
if (Energy->voltage_available) {
|
if (Energy->voltage_available) {
|
||||||
WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFormat(value_chr, Energy->voltage, Settings->flag2.voltage_resolution, Energy->voltage_common));
|
WSContentSend_PD(HTTP_SNS_VOLTAGE, WebEnergyFormat(value_chr, Energy->voltage, Settings->flag2.voltage_resolution, Energy->voltage_common));
|
||||||
}
|
|
||||||
if (!Energy->type_dc) {
|
|
||||||
if (!isnan(Energy->frequency[0])) {
|
|
||||||
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"),
|
|
||||||
WebEnergyFormat(value_chr, Energy->frequency, Settings->flag2.frequency_resolution, Energy->frequency_common));
|
|
||||||
}
|
}
|
||||||
}
|
if (!Energy->type_dc) {
|
||||||
if (Energy->current_available) {
|
if (!isnan(Energy->frequency[0])) {
|
||||||
WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFormat(value_chr, Energy->current, Settings->flag2.current_resolution));
|
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"),
|
||||||
}
|
WebEnergyFormat(value_chr, Energy->frequency, Settings->flag2.frequency_resolution, Energy->frequency_common));
|
||||||
WSContentSend_PD(HTTP_SNS_POWER, WebEnergyFormat(value_chr, Energy->active_power, Settings->flag2.wattage_resolution));
|
}
|
||||||
if (!Energy->type_dc) {
|
|
||||||
if (Energy->current_available && Energy->voltage_available) {
|
|
||||||
WSContentSend_PD(HTTP_ENERGY_SNS1, WebEnergyFormat(value_chr, apparent_power, Settings->flag2.wattage_resolution),
|
|
||||||
WebEnergyFormat(value2_chr, reactive_power, Settings->flag2.wattage_resolution),
|
|
||||||
WebEnergyFormat(value3_chr, power_factor, 2));
|
|
||||||
}
|
}
|
||||||
}
|
if (Energy->current_available) {
|
||||||
WSContentSend_PD(HTTP_ENERGY_SNS2, WebEnergyFormat(value_chr, Energy->daily_kWh, Settings->flag2.energy_resolution, 2),
|
WSContentSend_PD(HTTP_SNS_CURRENT, WebEnergyFormat(value_chr, Energy->current, Settings->flag2.current_resolution));
|
||||||
WebEnergyFormat(value2_chr, energy_yesterday_kWh, Settings->flag2.energy_resolution, 2),
|
}
|
||||||
WebEnergyFormat(value3_chr, Energy->total, Settings->flag2.energy_resolution, 2));
|
WSContentSend_PD(HTTP_SNS_POWER, WebEnergyFormat(value_chr, Energy->active_power, Settings->flag2.wattage_resolution));
|
||||||
if (!isnan(Energy->export_active[0])) {
|
if (!Energy->type_dc) {
|
||||||
uint32_t single = (!isnan(Energy->export_active[1]) && !isnan(Energy->export_active[2])) ? 2 : 1;
|
if (Energy->current_available && Energy->voltage_available) {
|
||||||
WSContentSend_PD(HTTP_ENERGY_SNS3, WebEnergyFormat(value_chr, Energy->export_active, Settings->flag2.energy_resolution, single));
|
WSContentSend_PD(HTTP_ENERGY_SNS1, WebEnergyFormat(value_chr, apparent_power, Settings->flag2.wattage_resolution),
|
||||||
}
|
WebEnergyFormat(value2_chr, reactive_power, Settings->flag2.wattage_resolution),
|
||||||
|
WebEnergyFormat(value3_chr, power_factor, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WSContentSend_PD(HTTP_ENERGY_SNS2, WebEnergyFormat(value_chr, Energy->daily_kWh, Settings->flag2.energy_resolution, 2),
|
||||||
|
WebEnergyFormat(value2_chr, energy_yesterday_kWh, Settings->flag2.energy_resolution, 2),
|
||||||
|
WebEnergyFormat(value3_chr, Energy->total, Settings->flag2.energy_resolution, 2));
|
||||||
|
if (!isnan(Energy->export_active[0])) {
|
||||||
|
uint32_t single = (!isnan(Energy->export_active[1]) && !isnan(Energy->export_active[2])) ? 2 : 1;
|
||||||
|
WSContentSend_PD(HTTP_ENERGY_SNS3, WebEnergyFormat(value_chr, Energy->export_active, Settings->flag2.energy_resolution, single));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_ENERGY_COLUMN_GUI
|
#ifdef USE_ENERGY_COLUMN_GUI
|
||||||
XnrgCall(FUNC_WEB_COL_SENSOR);
|
XnrgCall(FUNC_WEB_COL_SENSOR);
|
||||||
WSContentSend_P(PSTR("</table><hr/>{t}")); // {t} = <table style='width:100%'> - Define for next FUNC_WEB_SENSOR
|
WSContentSend_P(PSTR("</table><hr/>{t}")); // {t} = <table style='width:100%'> - Define for next FUNC_WEB_SENSOR
|
||||||
#endif // USE_ENERGY_COLUMN_GUI
|
#endif // USE_ENERGY_COLUMN_GUI
|
||||||
XnrgCall(FUNC_WEB_SENSOR);
|
XnrgCall(FUNC_WEB_SENSOR);
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
|
||||||
|
void EnergyWebGetArg(void) {
|
||||||
|
char tmp[8]; // WebGetArg numbers only
|
||||||
|
WebGetArg(PSTR("k03"), tmp, sizeof(tmp)); // relay gtoups
|
||||||
|
if (strlen(tmp)) { Energy->gui_rotate = atoi(tmp) * Energy->Settings.gui_cols; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
@ -1650,6 +1775,9 @@ bool Xsns03(uint32_t function)
|
||||||
case FUNC_WEB_SENSOR:
|
case FUNC_WEB_SENSOR:
|
||||||
EnergyShow(false);
|
EnergyShow(false);
|
||||||
break;
|
break;
|
||||||
|
case FUNC_WEB_GET_ARG:
|
||||||
|
EnergyWebGetArg();
|
||||||
|
break;
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
case FUNC_SAVE_BEFORE_RESTART:
|
case FUNC_SAVE_BEFORE_RESTART:
|
||||||
EnergySaveState();
|
EnergySaveState();
|
||||||
|
|
|
@ -660,7 +660,7 @@ void Ade7953DrvInit(void) {
|
||||||
if (PinUsed(GPIO_ADE7953_IRQ, GPIO_ANY)) { // Irq is not supported...
|
if (PinUsed(GPIO_ADE7953_IRQ, GPIO_ANY)) { // Irq is not supported...
|
||||||
uint32_t pin_irq = Pin(GPIO_ADE7953_IRQ, GPIO_ANY);
|
uint32_t pin_irq = Pin(GPIO_ADE7953_IRQ, GPIO_ANY);
|
||||||
pinMode(pin_irq, INPUT); // Related to resetPins() - Must be set to input
|
pinMode(pin_irq, INPUT); // Related to resetPins() - Must be set to input
|
||||||
// 0 (1 = Shelly 2.5), 1 (2 = Shelly EM), 2 (3 = Shelly Plus 2PM), 3 (4 = Shelly Pro 1PM), 4 (5 = Shelly Pro 2PM)
|
// 0 (1 = Shelly 2.5), 1 (2 = Shelly EM), 2 (3 = Shelly Plus 2PM), 3 (4 = Shelly Pro 1PM), 4 (5 = Shelly Pro 2PM), 5 (6 = Shelly Pro 4PM)
|
||||||
Ade7953.model = GetPin(pin_irq) - AGPIO(GPIO_ADE7953_IRQ);
|
Ade7953.model = GetPin(pin_irq) - AGPIO(GPIO_ADE7953_IRQ);
|
||||||
|
|
||||||
int pin_reset = Pin(GPIO_ADE7953_RST); // -1 if not defined
|
int pin_reset = Pin(GPIO_ADE7953_RST); // -1 if not defined
|
||||||
|
|
Loading…
Reference in New Issue