mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-24 14:57:16 +00:00
Merge remote-tracking branch 'Tasmota/development' into development
This commit is contained in:
commit
374c25bb45
@ -52,10 +52,13 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||
|
||||
## Changelog
|
||||
|
||||
### Version 8.3.1.1
|
||||
### Version 8.3.1.2
|
||||
|
||||
- Change IRremoteESP8266 library updated to v2.7.7
|
||||
- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]``
|
||||
- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]``
|
||||
- Add command ``Rule0`` to change global rule parameters
|
||||
- Add more functionality to ``Switchmode`` 11 and 12 (#8450)
|
||||
- Add support for VEML6075 UVA/UVB/UVINDEX Sensor by device111 (#8432)
|
||||
- Add support for VEML7700 Ambient light intensity Sensor by device111 (#8432)
|
||||
- Add Three Phase Export Active Energy to SDM630 driver
|
||||
|
@ -388,9 +388,9 @@ uint32_t Unishox::getNextBit(void) {
|
||||
in_eof = true;
|
||||
return 1; // return only 1s, which appends 'r' in worst case
|
||||
}
|
||||
byte_in = in[byte_no++];
|
||||
byte_in = pgm_read_byte(&in[byte_no++]);
|
||||
if (ESCAPE_MARKER == byte_in) {
|
||||
byte_in = in[byte_no++] - 1; // we shouldn't need to test if byte_no >= len, because it should not be possible to end with ESCAPE_MARKER
|
||||
byte_in = pgm_read_byte(&in[byte_no++]) - 1; // we shouldn't need to test if byte_no >= len, because it should not be possible to end with ESCAPE_MARKER
|
||||
}
|
||||
bit_no = 0;
|
||||
}
|
||||
@ -479,6 +479,9 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
|
||||
out[ol] = 0;
|
||||
// while ((byte_no << 3) + bit_no - 8 < len) {
|
||||
while (!in_eof) {
|
||||
if (ol >= len_out) {
|
||||
break;
|
||||
}
|
||||
int32_t h, v;
|
||||
char c = 0;
|
||||
byte is_upper = is_all_upper;
|
||||
@ -564,11 +567,11 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out,
|
||||
}
|
||||
}
|
||||
out[ol++] = c;
|
||||
|
||||
if (ol >= len_out) {
|
||||
return -1; // overflow
|
||||
}
|
||||
}
|
||||
|
||||
return ol;
|
||||
if (ol > len_out) {
|
||||
return -1; // overflow
|
||||
} else {
|
||||
return ol;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
## Unreleased (development)
|
||||
|
||||
### 8.3.1.2 20200522
|
||||
|
||||
- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]``
|
||||
- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]``
|
||||
- Add Three Phase Export Active Energy to SDM630 driver
|
||||
|
||||
### 8.3.1.1 20200518
|
||||
|
||||
- Change IRremoteESP8266 library updated to v2.7.7
|
||||
|
@ -65,6 +65,7 @@
|
||||
#define D_JSON_ERROR "Error"
|
||||
#define D_JSON_EVENT "Event"
|
||||
#define D_JSON_EVERY "Every"
|
||||
#define D_JSON_EXPORT "Export"
|
||||
#define D_JSON_EXPORT_ACTIVE "ExportActive"
|
||||
#define D_JSON_EXPORT_REACTIVE "ExportReactive"
|
||||
#define D_JSON_FAILED "Failed"
|
||||
@ -294,6 +295,9 @@
|
||||
#define D_CMND_LEDPOWER "LedPower"
|
||||
#define D_CMND_LEDSTATE "LedState"
|
||||
#define D_CMND_LEDMASK "LedMask"
|
||||
#define D_CMND_LEDPWMOFF "LedPwmOff"
|
||||
#define D_CMND_LEDPWMON "LedPwmOn"
|
||||
#define D_CMND_LEDPWMMODE "LedPwmMode"
|
||||
#define D_CMND_WIFIPOWER "WifiPower"
|
||||
#define D_CMND_SPEEDUNIT "SpeedUnit"
|
||||
#define D_CMND_I2CSCAN "I2CScan"
|
||||
|
@ -515,9 +515,7 @@ struct {
|
||||
uint8_t ot_hot_water_setpoint; // E8C
|
||||
uint8_t ot_boiler_setpoint; // E8D
|
||||
uint8_t ot_flags; // E8E
|
||||
|
||||
uint8_t free_e8f[1]; // E8F
|
||||
|
||||
uint8_t ledpwm_mask; // F8F
|
||||
uint16_t dimmer_hw_min; // E90
|
||||
uint16_t dimmer_hw_max; // E92
|
||||
uint32_t deepsleep; // E94
|
||||
@ -569,8 +567,10 @@ struct {
|
||||
uint16_t windmeter_pulse_debounce; // F3A
|
||||
int16_t windmeter_speed_factor; // F3C
|
||||
uint8_t windmeter_tele_pchange; // F3E
|
||||
uint8_t ledpwm_on; // F3F
|
||||
uint8_t ledpwm_off; // F40
|
||||
|
||||
uint8_t free_f3f[121]; // F3F - Decrement if adding new Setting variables just above and below
|
||||
uint8_t free_f42[119]; // F41 - Decrement if adding new Setting variables just above and below
|
||||
|
||||
// Only 32 bit boundary variables below
|
||||
uint16_t pulse_counter_debounce_low; // FB8
|
||||
|
@ -765,6 +765,9 @@ void SettingsDefaultSet2(void)
|
||||
Settings.blinkcount = APP_BLINKCOUNT;
|
||||
Settings.ledstate = APP_LEDSTATE;
|
||||
Settings.ledmask = APP_LEDMASK;
|
||||
// Settings.ledpwm_off = 0;
|
||||
Settings.ledpwm_on = 255;
|
||||
// Settings.ledpwm_mask = 0;
|
||||
Settings.pulse_timer[0] = APP_PULSETIME;
|
||||
// for (uint32_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; }
|
||||
|
||||
@ -1400,7 +1403,6 @@ void SettingsDelta(void)
|
||||
Settings.config_version = 1; // ESP32
|
||||
#endif // ESP32
|
||||
}
|
||||
|
||||
if (Settings.version < 0x08020006) {
|
||||
#ifdef ESP32
|
||||
Settings.module = WEMOS;
|
||||
@ -1411,12 +1413,15 @@ void SettingsDelta(void)
|
||||
if (Settings.rules[1][0] == 0) { Settings.rules[1][1] = 0; }
|
||||
if (Settings.rules[2][0] == 0) { Settings.rules[2][1] = 0; }
|
||||
}
|
||||
|
||||
if (Settings.version < 0x08030002) {
|
||||
SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1));
|
||||
Settings.ledpwm_off = 0;
|
||||
Settings.ledpwm_on = 255;
|
||||
Settings.ledpwm_mask = 0;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1931,4 +1931,36 @@ String escapeJSONString(const char *str) {
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Uncompress static PROGMEM strings
|
||||
\*********************************************************************************************/
|
||||
|
||||
#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
||||
|
||||
#include <unishox.h>
|
||||
|
||||
Unishox compressor;
|
||||
|
||||
String Decompress(const char * compressed, size_t uncompressed_size) {
|
||||
String content("");
|
||||
|
||||
uncompressed_size += 2; // take a security margin
|
||||
|
||||
// We use a nasty trick here. To avoid allocating twice the buffer,
|
||||
// we first extend the buffer of the String object to the target size (maybe overshooting by 7 bytes)
|
||||
// then we decompress in this buffer,
|
||||
// and finally assign the raw string to the String, which happens to work: String uses memmove(), so overlapping works
|
||||
content.reserve(uncompressed_size);
|
||||
char * buffer = content.begin();
|
||||
|
||||
int32_t len = compressor.unishox_decompress(compressed, strlen_P(compressed), buffer, uncompressed_size);
|
||||
if (len > 0) {
|
||||
buffer[len] = 0; // terminate string with NULL
|
||||
content = buffer; // copy in place
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
#endif // defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|"
|
||||
D_CMND_DEVICENAME "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|"
|
||||
D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|"
|
||||
D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|"
|
||||
D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_LEDPWMON "|" D_CMND_LEDPWMOFF "|" D_CMND_LEDPWMMODE "|"
|
||||
#ifdef USE_I2C
|
||||
D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|"
|
||||
#endif
|
||||
@ -50,7 +50,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
|
||||
&CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig,
|
||||
&CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd,
|
||||
&CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, &CmndHumOffset,
|
||||
&CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum,
|
||||
&CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode,
|
||||
#ifdef USE_I2C
|
||||
&CmndI2cScan, CmndI2cDriver,
|
||||
#endif
|
||||
@ -1890,3 +1890,59 @@ void CmndDriver(void)
|
||||
{
|
||||
XdrvCall(FUNC_COMMAND_DRIVER);
|
||||
}
|
||||
|
||||
void CmndLedPwmOff(void)
|
||||
{
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (XdrvMailbox.payload < 0) {
|
||||
Settings.ledpwm_off = 0;
|
||||
}
|
||||
else if (XdrvMailbox.payload > 255) {
|
||||
Settings.ledpwm_off = 255;
|
||||
} else {
|
||||
Settings.ledpwm_off = XdrvMailbox.payload;
|
||||
}
|
||||
UpdateLedPowerAll();
|
||||
}
|
||||
ResponseCmndNumber(Settings.ledpwm_off);
|
||||
}
|
||||
|
||||
void CmndLedPwmOn(void)
|
||||
{
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (XdrvMailbox.payload < 0) {
|
||||
Settings.ledpwm_on = 0;
|
||||
}
|
||||
else if (XdrvMailbox.payload > 255) {
|
||||
Settings.ledpwm_on = 255;
|
||||
} else {
|
||||
Settings.ledpwm_on = XdrvMailbox.payload;
|
||||
}
|
||||
UpdateLedPowerAll();
|
||||
}
|
||||
ResponseCmndNumber(Settings.ledpwm_on);
|
||||
}
|
||||
|
||||
void CmndLedPwmMode(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) {
|
||||
if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; }
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
|
||||
uint32_t mask = 1 << (XdrvMailbox.index -1); // Led to configure
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 0: // digital
|
||||
Settings.ledpwm_mask &= (0xFF ^ mask);
|
||||
break;
|
||||
case 1: // pwm
|
||||
Settings.ledpwm_mask |= mask;
|
||||
break;
|
||||
case 2: // toggle
|
||||
Settings.ledpwm_mask ^= mask;
|
||||
break;
|
||||
}
|
||||
UpdateLedPowerAll();
|
||||
}
|
||||
bool state = bitRead(Settings.ledpwm_mask, XdrvMailbox.index -1);
|
||||
ResponseCmndIdxChar(GetStateText(state));
|
||||
}
|
||||
}
|
||||
|
@ -336,6 +336,13 @@ void SetPowerOnState(void)
|
||||
blink_powersave = power;
|
||||
}
|
||||
|
||||
void UpdateLedPowerAll()
|
||||
{
|
||||
for (uint32_t i = 0; i < leds_present; i++) {
|
||||
SetLedPowerIdx(i, bitRead(led_power, i));
|
||||
}
|
||||
}
|
||||
|
||||
void SetLedPowerIdx(uint32_t led, uint32_t state)
|
||||
{
|
||||
if (!PinUsed(GPIO_LEDLNK) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present
|
||||
@ -351,7 +358,17 @@ void SetLedPowerIdx(uint32_t led, uint32_t state)
|
||||
} else {
|
||||
led_power &= (0xFF ^ mask);
|
||||
}
|
||||
DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state);
|
||||
uint16_t pwm = 0;
|
||||
if (bitRead(Settings.ledpwm_mask, led)) {
|
||||
#ifdef USE_LIGHT
|
||||
pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); // gamma corrected
|
||||
#else //USE_LIGHT
|
||||
pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear
|
||||
#endif //USE_LIGHT
|
||||
analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm);
|
||||
} else {
|
||||
DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state);
|
||||
}
|
||||
}
|
||||
#ifdef USE_BUZZER
|
||||
if (led == 0) {
|
||||
@ -386,10 +403,9 @@ void SetLedLink(uint32_t state)
|
||||
uint32_t led_pin = Pin(GPIO_LEDLNK);
|
||||
uint32_t led_inv = ledlnk_inverted;
|
||||
if (99 == led_pin) { // Legacy - LED1 is status
|
||||
led_pin = Pin(GPIO_LED1);
|
||||
led_inv = bitRead(led_inverted, 0);
|
||||
SetLedPowerIdx(0, state);
|
||||
}
|
||||
if (led_pin < 99) {
|
||||
else if (led_pin < 99) {
|
||||
if (state) { state = 1; }
|
||||
digitalWrite(led_pin, (led_inv) ? !state : state);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef _TASMOTA_VERSION_H_
|
||||
#define _TASMOTA_VERSION_H_
|
||||
|
||||
const uint32_t VERSION = 0x08030101;
|
||||
const uint32_t VERSION = 0x08030102;
|
||||
|
||||
// Lowest compatible version
|
||||
const uint32_t VERSION_COMPATIBLE = 0x07010006;
|
||||
|
@ -80,10 +80,12 @@ struct ENERGY {
|
||||
float power_factor[3] = { NAN, NAN, NAN }; // 0.12
|
||||
float frequency[3] = { NAN, NAN, NAN }; // 123.1 Hz
|
||||
|
||||
// float import_active[3] = { NAN, NAN, NAN }; // 123.123 kWh
|
||||
float export_active[3] = { NAN, NAN, NAN }; // 123.123 kWh
|
||||
|
||||
float start_energy = 0; // 12345.12345 kWh total previous
|
||||
float daily = 0; // 123.123 kWh
|
||||
float total = 0; // 12345.12345 kWh total energy
|
||||
float export_active = NAN; // 123.123 KWh
|
||||
|
||||
unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
|
||||
unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
||||
@ -95,7 +97,8 @@ struct ENERGY {
|
||||
uint8_t data_valid[3] = { 0, 0, 0 };
|
||||
|
||||
uint8_t phase_count = 1; // Number of phases active
|
||||
bool voltage_common = false; // Use single voltage and frequency
|
||||
bool voltage_common = false; // Use single voltage
|
||||
bool frequency_common = false; // Use single frequency
|
||||
bool kWhtoday_offset_init = false;
|
||||
|
||||
bool voltage_available = true; // Enable if voltage is measured
|
||||
@ -170,9 +173,18 @@ void EnergyUpdateToday(void)
|
||||
RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000);
|
||||
|
||||
uint32_t return_diff = 0;
|
||||
if (!isnan(Energy.export_active)) {
|
||||
return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal;
|
||||
RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000);
|
||||
if (!isnan(Energy.export_active[0])) {
|
||||
// return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal;
|
||||
// RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000);
|
||||
|
||||
float export_active = 0.0;
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
if (!isnan(Energy.export_active[i])) {
|
||||
export_active += Energy.export_active[i];
|
||||
}
|
||||
}
|
||||
return_diff = (uint32_t)(export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal;
|
||||
RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(export_active * 100000);
|
||||
}
|
||||
|
||||
if (EnergyTariff1Active()) { // Tarrif1 = Off-Peak
|
||||
@ -466,13 +478,13 @@ void EnergyEverySecond(void)
|
||||
if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; }
|
||||
if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; }
|
||||
if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; }
|
||||
if (!isnan(Energy.export_active[i])) { Energy.export_active[i] = 0; }
|
||||
|
||||
data_valid--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!data_valid) {
|
||||
if (!isnan(Energy.export_active)) { Energy.export_active = 0; }
|
||||
Energy.start_energy = 0;
|
||||
|
||||
XnrgCall(FUNC_ENERGY_RESET);
|
||||
@ -948,29 +960,31 @@ void EnergyShow(bool json)
|
||||
char voltage_chr[Energy.phase_count][FLOATSZ];
|
||||
char current_chr[Energy.phase_count][FLOATSZ];
|
||||
char active_power_chr[Energy.phase_count][FLOATSZ];
|
||||
char export_active_chr[Energy.phase_count][FLOATSZ];
|
||||
for (uint32_t i = 0; i < Energy.phase_count; i++) {
|
||||
dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]);
|
||||
dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]);
|
||||
dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]);
|
||||
dtostrfd(Energy.export_active[i], Settings.flag2.energy_resolution, export_active_chr[i]);
|
||||
}
|
||||
|
||||
char energy_total_chr[FLOATSZ];
|
||||
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr);
|
||||
char energy_daily_chr[FLOATSZ];
|
||||
dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr);
|
||||
char energy_yesterday_chr[FLOATSZ];
|
||||
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
|
||||
|
||||
char energy_total_chr[3][FLOATSZ];
|
||||
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]);
|
||||
char export_active_chr[3][FLOATSZ];
|
||||
dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]);
|
||||
uint8_t energy_total_fields = 1;
|
||||
|
||||
bool energy_tariff = false;
|
||||
char energy_usage_chr[2][FLOATSZ];
|
||||
char energy_return_chr[2][FLOATSZ];
|
||||
if (Settings.tariff[0][0] != Settings.tariff[1][0]) {
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); // Tariff1
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); // Tariff2
|
||||
dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); // Tariff1
|
||||
dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); // Tariff2
|
||||
energy_total_fields = 3;
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[0]); // Tariff1
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[1]); // Tariff2
|
||||
dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[0]); // Tariff1
|
||||
dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[1]); // Tariff2
|
||||
energy_tariff = true;
|
||||
}
|
||||
|
||||
char value_chr[FLOATSZ *3]; // Used by EnergyFormatIndex
|
||||
@ -980,15 +994,26 @@ void EnergyShow(bool json)
|
||||
if (json) {
|
||||
bool show_energy_period = (0 == tele_period);
|
||||
|
||||
ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"),
|
||||
ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s"),
|
||||
GetDateAndTime(DT_ENERGY).c_str(),
|
||||
EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields),
|
||||
energy_total_chr);
|
||||
|
||||
if (energy_tariff) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL D_CMND_TARIFF "\":%s"),
|
||||
EnergyFormatIndex(value_chr, energy_usage_chr[0], json, 2));
|
||||
}
|
||||
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"),
|
||||
energy_yesterday_chr,
|
||||
energy_daily_chr);
|
||||
|
||||
if (!isnan(Energy.export_active)) {
|
||||
if (!isnan(Energy.export_active[0])) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"),
|
||||
EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields));
|
||||
EnergyFormat(value_chr, export_active_chr[0], json));
|
||||
if (energy_tariff) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT D_CMND_TARIFF "\":%s"),
|
||||
EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2));
|
||||
}
|
||||
}
|
||||
|
||||
if (show_energy_period) {
|
||||
@ -1012,7 +1037,7 @@ void EnergyShow(bool json)
|
||||
}
|
||||
if (!isnan(Energy.frequency[0])) {
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"),
|
||||
EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common));
|
||||
EnergyFormat(value_chr, frequency_chr[0], json, Energy.frequency_common));
|
||||
}
|
||||
}
|
||||
if (Energy.voltage_available) {
|
||||
@ -1028,14 +1053,14 @@ void EnergyShow(bool json)
|
||||
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (show_energy_period) { // Only send if telemetry
|
||||
dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]);
|
||||
DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); // PowerUsage, EnergyToday
|
||||
dtostrfd(Energy.total * 1000, 1, energy_total_chr);
|
||||
DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr); // PowerUsage, EnergyToday
|
||||
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); // Tariff1
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); // Tariff2
|
||||
dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]);
|
||||
dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]);
|
||||
DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]);
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_usage_chr[0]); // Tariff1
|
||||
dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_usage_chr[1]); // Tariff2
|
||||
dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, energy_return_chr[0]);
|
||||
dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, energy_return_chr[1]);
|
||||
DomoticzSensorP1SmartMeter(energy_usage_chr[0], energy_usage_chr[1], energy_return_chr[0], energy_return_chr[1], (int)Energy.active_power[0]);
|
||||
|
||||
if (Energy.voltage_available) {
|
||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); // Voltage
|
||||
@ -1079,12 +1104,12 @@ void EnergyShow(bool json)
|
||||
}
|
||||
if (!isnan(Energy.frequency[0])) {
|
||||
WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"),
|
||||
EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common));
|
||||
EnergyFormat(value_chr, frequency_chr[0], json, Energy.frequency_common));
|
||||
}
|
||||
}
|
||||
WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]);
|
||||
if (!isnan(Energy.export_active)) {
|
||||
WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]);
|
||||
WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
|
||||
if (!isnan(Energy.export_active[0])) {
|
||||
WSContentSend_PD(HTTP_ENERGY_SNS3, EnergyFormat(value_chr, export_active_chr[0], json));
|
||||
}
|
||||
|
||||
XnrgCall(FUNC_WEB_SENSOR);
|
||||
|
@ -213,7 +213,7 @@ char rules_vars[MAX_RULE_VARS][33] = {{ 0 }};
|
||||
#ifdef USE_RULES_COMPRESSION
|
||||
// Statically allocate one String per rule
|
||||
String k_rules[MAX_RULE_SETS] = { String(), String(), String() }; // Strings are created empty
|
||||
Unishox compressor; // singleton
|
||||
// Unishox compressor; // singleton
|
||||
#endif // USE_RULES_COMPRESSION
|
||||
|
||||
// Returns whether the rule is uncompressed, which means the first byte is not NULL
|
||||
@ -263,18 +263,7 @@ void GetRule_decompress(String &rule, const char *rule_head) {
|
||||
size_t buf_len = 1 + *rule_head * 8; // the first byte contains size of buffer for uncompressed rule / 8, buf_len may overshoot by 7
|
||||
rule_head++; // advance to the actual compressed buffer
|
||||
|
||||
// We use a nasty trick here. To avoid allocating twice the buffer,
|
||||
// we first extend the buffer of the String object to the target size (maybe overshooting by 7 bytes)
|
||||
// then we decompress in this buffer,
|
||||
// and finally assign the raw string to the String, which happens to work: String uses memmove(), so overlapping works
|
||||
rule.reserve(buf_len);
|
||||
char* buf = rule.begin();
|
||||
|
||||
int32_t len_decompressed = compressor.unishox_decompress(rule_head, strlen(rule_head), buf, buf_len);
|
||||
buf[len_decompressed] = 0; // add NULL terminator
|
||||
|
||||
// AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Rawdecompressed: %d"), len_decompressed);
|
||||
rule = buf; // assign the raw string to the String object (in reality re-writing the same data in the same place)
|
||||
rule = Decompress(rule_head, buf_len);
|
||||
}
|
||||
#endif // USE_RULES_COMPRESSION
|
||||
|
||||
|
@ -71,7 +71,7 @@ uint32_t DecodeLightId(uint32_t hue_id);
|
||||
#ifdef USE_SCRIPT_COMPRESSION
|
||||
#include <unishox.h>
|
||||
|
||||
Unishox compressor; // singleton
|
||||
//Unishox compressor; // singleton
|
||||
#define SCRIPT_COMPRESS compressor.unishox_compress
|
||||
#define SCRIPT_DECOMPRESS compressor.unishox_decompress
|
||||
#ifndef UNISHOXRSIZE
|
||||
@ -1228,6 +1228,52 @@ chknext:
|
||||
fvar=UtcTime()-(uint32_t)EPOCH_OFFSET;
|
||||
goto exit;
|
||||
}
|
||||
#ifdef USE_ENERGY_SENSOR
|
||||
if (!strncmp(vname,"enrg[",5)) {
|
||||
lp+=5;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
while (*lp==' ') lp++;
|
||||
switch ((uint32_t)fvar) {
|
||||
case 0:
|
||||
fvar=Energy.total;
|
||||
break;
|
||||
case 1:
|
||||
fvar=Energy.voltage[0];
|
||||
break;
|
||||
case 2:
|
||||
fvar=Energy.voltage[1];
|
||||
break;
|
||||
case 3:
|
||||
fvar=Energy.voltage[2];
|
||||
break;
|
||||
case 4:
|
||||
fvar=Energy.current[0];
|
||||
break;
|
||||
case 5:
|
||||
fvar=Energy.current[1];
|
||||
break;
|
||||
case 6:
|
||||
fvar=Energy.current[2];
|
||||
break;
|
||||
case 7:
|
||||
fvar=Energy.active_power[0];
|
||||
break;
|
||||
case 8:
|
||||
fvar=Energy.active_power[1];
|
||||
break;
|
||||
case 9:
|
||||
fvar=Energy.active_power[2];
|
||||
break;
|
||||
|
||||
default:
|
||||
fvar=99999;
|
||||
break;
|
||||
}
|
||||
len=0;
|
||||
lp++;
|
||||
goto exit;
|
||||
}
|
||||
#endif //USE_ENERGY_SENSOR
|
||||
break;
|
||||
case 'f':
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
@ -1948,6 +1994,15 @@ chknext:
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD)
|
||||
if (!strncmp(vname,"sml[",4)) {
|
||||
lp+=4;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
fvar=SML_GetVal[fvar];
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
if (!strncmp(vname,"sml(",4)) {
|
||||
lp+=4;
|
||||
float fvar1;
|
||||
@ -3948,6 +4003,12 @@ void ScriptSaveSettings(void) {
|
||||
|
||||
strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size);
|
||||
|
||||
if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') {
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("script error: must start with >D"));
|
||||
bitWrite(Settings.rule_enabled, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
#if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)
|
||||
if (glob_script_mem.flags&1) {
|
||||
EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram);
|
||||
@ -3983,9 +4044,9 @@ void ScriptSaveSettings(void) {
|
||||
#ifndef ESP32_SCRIPT_SIZE
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram));
|
||||
uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram)+1, Settings.rules[0], MAX_SCRIPT_SIZE-1);
|
||||
Settings.rules[0][len_compressed] = 0;
|
||||
uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1);
|
||||
if (len_compressed > 0) {
|
||||
Settings.rules[0][len_compressed] = 0;
|
||||
AddLog_P2(LOG_LEVEL_INFO,PSTR("script compressed to %d %%"),len_compressed * 100 / strlen(glob_script_mem.script_ram));
|
||||
} else {
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed);
|
||||
@ -4899,12 +4960,20 @@ const char SCRIPT_MSG_TEXTINP[] PROGMEM =
|
||||
const char SCRIPT_MSG_NUMINP[] PROGMEM =
|
||||
"<div><center><label><b>%s</b><input min='%s' max='%s' step='%s' value='%s' type='number' style='width:200px' onfocusin='pr(0)' onfocusout='pr(1)' onchange='siva(value,\"%s\")'></label></div>";
|
||||
|
||||
|
||||
#ifdef USE_GOOGLE_CHARTS
|
||||
const char SCRIPT_MSG_GTABLE[] PROGMEM =
|
||||
"<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>"
|
||||
"<script type='text/javascript'>google.charts.load('current',{packages:['corechart']});</script>"
|
||||
"<script type='text/javascript'>google.charts.load('current',{packages:['table']});</script>"
|
||||
"<script type='text/javascript'>google.charts.load('current',{packages:['gauge']});</script>"
|
||||
"<style>.hRow{font-weight:bold;color:black;background-color:lightblue;}.hCol{font-weight:bold;color:black;background-color:lightblue;}.tCell{color:black}</style>";
|
||||
"<style>.hRow{font-weight:bold;color:black;background-color:lightblue;}.hCol{font-weight:bold;color:black;background-color:lightblue;}.tCell{color:black}</style>"
|
||||
"<style>#chart1{display: inline-block;margin: 0 auto;#timeline text{fill:magenta;}}</style>";
|
||||
|
||||
const char SCRIPT_MSG_TABLE[] PROGMEM =
|
||||
"<script type='text/javascript'>google.charts.load('current',{packages:['table']});</script>";
|
||||
const char SCRIPT_MSG_GAUGE[] PROGMEM =
|
||||
"<script type='text/javascript'>google.charts.load('current',{packages:['gauge']});</script>";
|
||||
const char SCRIPT_MSG_TIMELINE[] PROGMEM =
|
||||
"<script type='text/javascript'>google.charts.load('current',{packages:['timeline']});</script>";
|
||||
|
||||
|
||||
const char SCRIPT_MSG_GTABLEa[] PROGMEM =
|
||||
@ -4913,9 +4982,15 @@ const char SCRIPT_MSG_GTABLEa[] PROGMEM =
|
||||
"var data=google.visualization.arrayToDataTable([";
|
||||
|
||||
|
||||
const char SCRIPT_MSG_GTABLEd[] PROGMEM =
|
||||
"['Timeline','start','end'],";
|
||||
|
||||
//#define CHART_EXTRA_OPTIONS ",width:'640px',height:'480px'"
|
||||
#define CHART_EXTRA_OPTIONS
|
||||
|
||||
const char SCRIPT_MSG_GTABLEb[] PROGMEM =
|
||||
"]);"
|
||||
"var options={%s};"
|
||||
"var options={%s" CHART_EXTRA_OPTIONS "};"
|
||||
"var chart=new google.visualization.%s(document.getElementById('chart%1d'));"
|
||||
"chart.draw(data,options);}"
|
||||
"google.charts.setOnLoadCallback(drawChart);</script>";
|
||||
@ -4923,15 +4998,83 @@ const char SCRIPT_MSG_GTABLEb[] PROGMEM =
|
||||
const char SCRIPT_MSG_GOPT1[] PROGMEM =
|
||||
"title:'%s',isStacked:false";
|
||||
|
||||
const char SCRIPT_MSG_GOPT3[] PROGMEM =
|
||||
"title:'%s',vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}";
|
||||
|
||||
|
||||
const char SCRIPT_MSG_GOPT2[] PROGMEM =
|
||||
"showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc";
|
||||
|
||||
const char SCRIPT_MSG_GOPT3[] PROGMEM =
|
||||
"title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s";
|
||||
|
||||
const char SCRIPT_MSG_GOPT4[] PROGMEM =
|
||||
//"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'}";
|
||||
"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'},theme: 'maximized'";
|
||||
|
||||
const char SCRIPT_MSG_GOPT5[] PROGMEM =
|
||||
"new Date(0,1,1,%d,%d)";
|
||||
|
||||
const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'";
|
||||
|
||||
#define GLIBS_MAIN 1<<0
|
||||
#define GLIBS_TABLE 1<<1
|
||||
#define GLIBS_GAUGE 1<<2
|
||||
#define GLIBS_TIMELINE 1<<3
|
||||
|
||||
#define MAX_GARRAY 4
|
||||
|
||||
char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries) {
|
||||
struct T_INDEX ind;
|
||||
uint8_t vtype;
|
||||
uint8 entries=0;
|
||||
|
||||
uint8_t anum=0;
|
||||
while (anum<MAX_GARRAY) {
|
||||
if (*lp==')' || *lp==0) break;
|
||||
char *lp1=lp;
|
||||
lp=isvar(lp,&vtype,&ind,0,0,0);
|
||||
if (vtype!=VAR_NV) {
|
||||
SCRIPT_SKIP_SPACES
|
||||
uint8_t index=glob_script_mem.type[ind.index].index;
|
||||
if ((vtype&STYPE)==0) {
|
||||
// numeric result
|
||||
//Serial.printf("numeric %d - %d \n",ind.index,index);
|
||||
if (glob_script_mem.type[ind.index].bits.is_filter) {
|
||||
//Serial.printf("numeric array\n");
|
||||
uint8_t len=0;
|
||||
float *fa=Get_MFAddr(index,&len);
|
||||
//Serial.printf(">> 2 %d\n",(uint32_t)*fa);
|
||||
if (fa && len>=entries) {
|
||||
if (!entries) {entries = len;}
|
||||
// add array to list
|
||||
arrays[anum]=fa;
|
||||
anum++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lp=lp1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*ranum=anum;
|
||||
*rentries=entries;
|
||||
return lp;
|
||||
}
|
||||
|
||||
char *gc_send_labels(char *lp,uint32_t anum) {
|
||||
WSContentSend_PD("[");
|
||||
for (uint32_t cnt=0; cnt<anum+1; cnt++) {
|
||||
char label[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,label,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
WSContentSend_PD(SCRIPT_MSG_GTE1,label);
|
||||
//Serial.printf("labels %s\n",label);
|
||||
if (cnt<anum) { WSContentSend_PD(","); }
|
||||
}
|
||||
WSContentSend_PD("],");
|
||||
return lp;
|
||||
}
|
||||
|
||||
#endif // USE_GOOGLE_CHARTS
|
||||
|
||||
void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) {
|
||||
uint32_t cnt;
|
||||
for (cnt=0;cnt<blen-1;cnt++) {
|
||||
@ -5141,124 +5284,27 @@ void ScriptWebShow(char mc) {
|
||||
}
|
||||
} else {
|
||||
if (*lin==mc) {
|
||||
#ifdef USE_GOOGLE_CHARTS
|
||||
lin++;
|
||||
if (!strncmp(lin,"tb(",3)) {
|
||||
// get google table
|
||||
struct T_INDEX ind;
|
||||
uint8_t vtype;
|
||||
char *lp=lin+3;
|
||||
uint8 entries=0;
|
||||
#define MAX_GARRAY 4
|
||||
float *arrays[MAX_GARRAY];
|
||||
uint8_t anum=0;
|
||||
while (anum<MAX_GARRAY) {
|
||||
if (*lp==')' || *lp==0) break;
|
||||
char *lp1=lp;
|
||||
lp=isvar(lp,&vtype,&ind,0,0,0);
|
||||
if (vtype!=VAR_NV) {
|
||||
SCRIPT_SKIP_SPACES
|
||||
uint8_t index=glob_script_mem.type[ind.index].index;
|
||||
if ((vtype&STYPE)==0) {
|
||||
// numeric result
|
||||
//Serial.printf("numeric %d - %d \n",ind.index,index);
|
||||
if (glob_script_mem.type[ind.index].bits.is_filter) {
|
||||
//Serial.printf("numeric array\n");
|
||||
uint8_t len=0;
|
||||
float *fa=Get_MFAddr(index,&len);
|
||||
//Serial.printf(">> 2 %d\n",(uint32_t)*fa);
|
||||
if (fa && len>=entries) {
|
||||
if (!entries) {entries = len;}
|
||||
// add array to list
|
||||
arrays[anum]=fa;
|
||||
anum++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lp=lp1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Serial.printf("arrays %d\n",anum);
|
||||
//Serial.printf("entries %d\n",entries);
|
||||
|
||||
if (!google_libs) {
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLE);
|
||||
google_libs=1;
|
||||
}
|
||||
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLEa);
|
||||
|
||||
// we know how many arrays and the number of entries
|
||||
// we need to fetch the labels now
|
||||
WSContentSend_PD("[");
|
||||
for (uint32_t cnt=0; cnt<anum+1; cnt++) {
|
||||
char label[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,label,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
WSContentSend_PD(SCRIPT_MSG_GTE1,label);
|
||||
//Serial.printf("labels %s\n",label);
|
||||
if (cnt<anum) { WSContentSend_PD(","); }
|
||||
}
|
||||
WSContentSend_PD("],");
|
||||
|
||||
// now we have to export the values
|
||||
// fetch label part only once in combo string
|
||||
char label[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,label,0);
|
||||
if (!strncmp(lin,"gc(",3)) {
|
||||
// get google table
|
||||
lp=lin+3;
|
||||
SCRIPT_SKIP_SPACES
|
||||
char *lblp=label;
|
||||
|
||||
for (uint32_t cnt=0; cnt<entries; cnt++) {
|
||||
WSContentSend_PD("['");
|
||||
char lbl[16];
|
||||
strncpy(lbl,lblp,sizeof(lbl));
|
||||
for (uint32_t i=0; i<strlen(lblp); i++) {
|
||||
if (lblp[i]=='|') {
|
||||
lbl[i]=0;
|
||||
lblp+=i+1;
|
||||
break;
|
||||
}
|
||||
lbl[i]=lblp[i];
|
||||
}
|
||||
WSContentSend_PD(lbl);
|
||||
WSContentSend_PD("',");
|
||||
for (uint32_t ind=0; ind<anum; ind++) {
|
||||
char acbuff[32];
|
||||
float *fp=arrays[ind];
|
||||
dtostrfd(fp[cnt],glob_script_mem.script_dprec,acbuff);
|
||||
WSContentSend_PD("%s",acbuff);
|
||||
if (ind<anum-1) { WSContentSend_PD(","); }
|
||||
}
|
||||
WSContentSend_PD("]");
|
||||
if (cnt<entries-1) { WSContentSend_PD(","); }
|
||||
}
|
||||
|
||||
char header[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,header,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
|
||||
char options[256];
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT1,header);
|
||||
//uint32_t slen=sizeof(SCRIPT_MSG_GOPT1)+strlen(header);
|
||||
|
||||
const char *type;
|
||||
if (*lp!=')') {
|
||||
switch (*lp) {
|
||||
const char *func;
|
||||
char options[256];
|
||||
uint8_t nanum=MAX_GARRAY;
|
||||
uint8_t y2f=0;
|
||||
char ctype;
|
||||
ctype=*lp;
|
||||
lp++;
|
||||
if (!(google_libs&GLIBS_MAIN)) {
|
||||
google_libs|=GLIBS_MAIN;
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLE);
|
||||
}
|
||||
switch (ctype) {
|
||||
case 'l':
|
||||
type=PSTR("LineChart");
|
||||
if (*(lp+1)=='2') {
|
||||
// 2 y axes variant
|
||||
lp+=2;
|
||||
SCRIPT_SKIP_SPACES
|
||||
float max1;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&max1,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
float max2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&max2,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT3,header,(uint32_t)max1,(uint32_t)max2);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
type=PSTR("BarChart");
|
||||
@ -5268,32 +5314,174 @@ void ScriptWebShow(char mc) {
|
||||
break;
|
||||
case 'g':
|
||||
type=PSTR("Gauge");
|
||||
if (!(google_libs&GLIBS_GAUGE)) {
|
||||
google_libs|=GLIBS_GAUGE;
|
||||
WSContentSend_PD(SCRIPT_MSG_GAUGE);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
type=PSTR("Table");
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT2);
|
||||
if (!(google_libs&GLIBS_TABLE)) {
|
||||
google_libs|=GLIBS_TABLE;
|
||||
WSContentSend_PD(SCRIPT_MSG_TABLE);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
type=PSTR("Timeline");
|
||||
if (!(google_libs&GLIBS_TIMELINE)) {
|
||||
google_libs|=GLIBS_TIMELINE;
|
||||
WSContentSend_PD(SCRIPT_MSG_TIMELINE);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
type=PSTR("Histogram");
|
||||
break;
|
||||
default:
|
||||
type=PSTR("Histogram");
|
||||
break;
|
||||
case 'c':
|
||||
type=PSTR("ColumnChart");
|
||||
break;
|
||||
default:
|
||||
// error
|
||||
goto nextwebline;
|
||||
break;
|
||||
}
|
||||
if (ctype=='l' && *lp=='f') {
|
||||
lp++;
|
||||
func=PSTR(",curveType:'function'");
|
||||
} else {
|
||||
func="";
|
||||
}
|
||||
if (*lp=='2') {
|
||||
lp++;
|
||||
nanum=2;
|
||||
y2f=1;
|
||||
}
|
||||
SCRIPT_SKIP_SPACES
|
||||
|
||||
//Serial.printf("type %d\n",ctype);
|
||||
|
||||
float *arrays[MAX_GARRAY];
|
||||
uint8_t anum=0;
|
||||
uint8 entries=0;
|
||||
lp=gc_get_arrays(lp, &arrays[0], &anum, &entries);
|
||||
|
||||
if (anum>nanum) {
|
||||
goto nextwebline;
|
||||
}
|
||||
// we know how many arrays and the number of entries
|
||||
//Serial.printf("arrays %d\n",anum);
|
||||
//Serial.printf("entries %d\n",entries);
|
||||
if (ctype=='T') {
|
||||
if (anum && !(entries&1)) {
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLEa);
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLEd);
|
||||
char label[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,label,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
char *lblp=label;
|
||||
for (uint32_t ind=0; ind<anum; ind++) {
|
||||
char lbl[16];
|
||||
strncpy(lbl,lblp,sizeof(lbl));
|
||||
for (uint32_t i=0; i<strlen(lblp); i++) {
|
||||
if (lblp[i]=='|') {
|
||||
lbl[i]=0;
|
||||
lblp+=i+1;
|
||||
break;
|
||||
}
|
||||
lbl[i]=lblp[i];
|
||||
}
|
||||
for (uint32_t cnt=0; cnt<entries; cnt+=2) {
|
||||
WSContentSend_PD("['%s',",lbl);
|
||||
float *fp=arrays[ind];
|
||||
uint32_t time=fp[cnt];
|
||||
WSContentSend_PD(SCRIPT_MSG_GOPT5,time/60,time%60);
|
||||
WSContentSend_PD(",");
|
||||
time=fp[cnt+1];
|
||||
WSContentSend_PD(SCRIPT_MSG_GOPT5,time/60,time%60);
|
||||
WSContentSend_PD("]");
|
||||
if (cnt<entries-2) { WSContentSend_PD(","); }
|
||||
}
|
||||
if (ind<anum-1) { WSContentSend_PD(","); }
|
||||
}
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT4);
|
||||
}
|
||||
} else {
|
||||
type=PSTR("ColumnChart");
|
||||
}
|
||||
lp++;
|
||||
// we need to fetch the labels now
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLEa);
|
||||
lp=gc_send_labels(lp,anum);
|
||||
|
||||
// now we have to export the values
|
||||
// fetch label part only once in combo string
|
||||
char label[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,label,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
char *lblp=label;
|
||||
|
||||
for (uint32_t cnt=0; cnt<entries; cnt++) {
|
||||
WSContentSend_PD("['");
|
||||
char lbl[16];
|
||||
strncpy(lbl,lblp,sizeof(lbl));
|
||||
for (uint32_t i=0; i<strlen(lblp); i++) {
|
||||
if (lblp[i]=='|') {
|
||||
lbl[i]=0;
|
||||
lblp+=i+1;
|
||||
break;
|
||||
}
|
||||
lbl[i]=lblp[i];
|
||||
}
|
||||
WSContentSend_PD(lbl);
|
||||
WSContentSend_PD("',");
|
||||
for (uint32_t ind=0; ind<anum; ind++) {
|
||||
char acbuff[32];
|
||||
float *fp=arrays[ind];
|
||||
dtostrfd(fp[cnt],glob_script_mem.script_dprec,acbuff);
|
||||
WSContentSend_PD("%s",acbuff);
|
||||
if (ind<anum-1) { WSContentSend_PD(","); }
|
||||
}
|
||||
WSContentSend_PD("]");
|
||||
if (cnt<entries-1) { WSContentSend_PD(","); }
|
||||
}
|
||||
|
||||
// get header
|
||||
char header[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,header,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
|
||||
switch (ctype) {
|
||||
case 't':
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT2);
|
||||
break;
|
||||
default:
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT1,header);
|
||||
break;
|
||||
}
|
||||
// check for 2 axis option
|
||||
if (y2f) {
|
||||
// 2 y axes variant
|
||||
SCRIPT_SKIP_SPACES
|
||||
float max1;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&max1,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
float max2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&max2,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
snprintf_P(options,sizeof(options),SCRIPT_MSG_GOPT3,header,(uint32_t)max1,(uint32_t)max2,func);
|
||||
}
|
||||
}
|
||||
WSContentSend_PD(SCRIPT_MSG_GTABLEb,options,type,chartindex);
|
||||
chartindex++;
|
||||
} else {
|
||||
Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp));
|
||||
WSContentSend_PD(PSTR("%s"),tmp);
|
||||
}
|
||||
#else
|
||||
} else {
|
||||
Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp));
|
||||
WSContentSend_PD(PSTR("%s"),tmp);
|
||||
#endif //USE_GOOGLE_CHARTS
|
||||
}
|
||||
}
|
||||
}
|
||||
nextwebline:
|
||||
if (*lp==SCRIPT_EOL) {
|
||||
lp++;
|
||||
} else {
|
||||
@ -5474,7 +5662,7 @@ bool Xdrv10(uint8_t function)
|
||||
glob_script_mem.script_ram=sprt;
|
||||
glob_script_mem.script_size=UNISHOXRSIZE;
|
||||
len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size);
|
||||
glob_script_mem.script_ram[len_decompressed]=0;
|
||||
if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed]=0;
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed);
|
||||
#endif
|
||||
#endif
|
||||
@ -5568,6 +5756,14 @@ bool Xdrv10(uint8_t function)
|
||||
glob_script_mem.flags=1;
|
||||
#endif
|
||||
|
||||
// a valid script MUST start with >D
|
||||
if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') {
|
||||
// clr all
|
||||
memset(glob_script_mem.script_ram,0,glob_script_mem.script_size);
|
||||
strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D"));
|
||||
bitWrite(Settings.rule_enabled, 0, 0);
|
||||
}
|
||||
|
||||
// assure permanent memory is 4 byte aligned
|
||||
{ uint32_t ptr=(uint32_t)glob_script_mem.script_pram;
|
||||
ptr&=0xfffffffc;
|
||||
|
@ -114,6 +114,29 @@ void HueRespondToMSearch(void)
|
||||
* Hue web server additions
|
||||
\*********************************************************************************************/
|
||||
|
||||
//<?xml version="1.0"?><root xmlns="urn:schemas-upnp-org:device-1-0"><specVersion><major>1</major><minor>0</minor></specVersion><URLBase>http://{x1:80/</URLBase><device><deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType><friendlyName>Amazon-Echo-HA-Bridge ({x1)</friendlyName><manufacturer>Royal Philips Electronics</manufacturer><manufacturerURL>http://www.philips.com</manufacturerURL><modelDescription>Philips hue Personal Wireless Lighting</modelDescription><modelName>Philips hue bridge 2012</modelName><modelNumber>929000226503</modelNumber><serialNumber>{x3</serialNumber><UDN>uuid:{x2</UDN></device></root>\r\n\r\n
|
||||
//Successfully compressed from 625 to 391 bytes (-37.4%)
|
||||
// const size_t HUE_DESCRIPTION_XML_size = 625;
|
||||
// const char HUE_DESCRIPTION_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E"
|
||||
// "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\xF0\x62\x98\xDB\xF1\xD6\x2C"
|
||||
// "\x67\x0C\x3A\xF3\xE3\xC7\x98\x8C\xCF\x43\x67\x59\xC8\x75\xB3\xD8\x7E\x1E\x85\xE1"
|
||||
// "\x8C\x32\x33\x04\x1C\x78\xFC\x3D\x06\xD9\xAF\x3E\x7E\x1C\x87\xA1\xD8\x40\x83\x14"
|
||||
// "\xF4\x1B\xBD\x9F\x3F\x0E\x33\xD0\xEC\x20\x41\x8A\x7A\x1D\x80\x91\x85\x10\xB2\xF9"
|
||||
// "\x04\x43\xAF\xCC\xFC\x15\x54\x30\xF3\x3B\x0E\xC3\xDA\x6C\x39\x0F\x3F\xB3\xB0\xF4"
|
||||
// "\x3B\x08\x10\xEA\x1E\x80\x83\xA2\x82\x1C\x42\xA3\x21\x8C\xFC\x05\x6D\xB4\xF3\x21"
|
||||
// "\xD7\xED\x0C\xF3\x39\x0F\x43\xB0\x81\x1B\x0C\x3D\x0C\x7F\x5F\x08\x11\x91\x75\x8D"
|
||||
// "\x67\xE1\x58\xDB\x36\xE7\x1D\x64\xC3\x15\x87\x59\x0A\x2B\x3A\xC8\x77\xF4\x41\xE6"
|
||||
// "\x8E\xE9\xED\x36\x1C\x87\x78\xF4\x3B\x08\x12\x30\x63\xD0\x6D\xF0\xB3\x16\x1D\x0B"
|
||||
// "\xFB\xF9\xF8\x5F\xC3\x2B\x09\x10\xC1\x5A\x16\x8C\xF2\x26\x13\x0E\xBF\x9D\xA1\xF8"
|
||||
// "\xF4\x3B\x01\x23\x04\x04\x8C\x48\x85\x97\xC8\x20\x43\xE0\xDC\x7C\x7C\x7C\xE8\x30"
|
||||
// "\x10\x71\xA3\xA0\x78\x34\x12\x71\x22\x16\x5F\x20\x8F\xC3\xD0\x6E\x08\xC2\x21\x1F"
|
||||
// "\x83\xFE\x8C\xAD\xCE\x3F\x01\x0F\x49\x14\x2D\xA2\x18\xFF\xEC\xEB\x09\x10\xFE\xFD"
|
||||
// "\x84\xFD\xE4\x41\x68\xF0\xAA\xDE\x1E\x3D\x0E\xC0\x4C\xC5\x41\x07\x27\x2E\xB1\xAC"
|
||||
// "\x12\x32\x01\xC0\x83\xC2\x41\xCA\x72\x88\x10\xB1\x10\x42\xE1\x13\x04\x61\x17\x0B"
|
||||
// "\x1A\x39\xFC\xFC\x38\xA9\x36\xEA\xBB\x5D\x90\x21\xE0\x20\x83\x58\xF4\xF3\xFE\xD8"
|
||||
// "\x21\xCA\x3D\xA6\xC3\x96\x7A\x1D\x84\x09\x13\x8F\x42\x16\x42\x17\x1F\x82\xC5\xE8"
|
||||
// "\x87\x99\xED\x36\x1C\xA3\xD0\xEC\x22\x16\x42\x17\x1F\x80\x87\xC7\x19\xF8\x7A\x1D"
|
||||
// "\x9F\xCC\xA3\xF2\x70\xA4\x6E\x9C\x29\x1B\x8D";
|
||||
const char HUE_DESCRIPTION_XML[] PROGMEM =
|
||||
"<?xml version=\"1.0\"?>"
|
||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||
@ -137,22 +160,59 @@ const char HUE_DESCRIPTION_XML[] PROGMEM =
|
||||
"</device>"
|
||||
"</root>\r\n"
|
||||
"\r\n";
|
||||
|
||||
//%s"alert":"none","effect":"none","reachable":true}
|
||||
//Successfully compressed from 50 to 34 bytes (-32%)
|
||||
// const size_t HUE_LIGHTS_STATUS_JSON1_SUFFIX_size = 50;
|
||||
// const char HUE_LIGHTS_STATUS_JSON1_SUFFIX[] PROGMEM = "\x3E\xBC\x7B\x2C\x27\xFA\x3D\x87\x99\xEC\xEC\xE6\x7B\x0E\xA3\xD8\xCC\x18\x61\x82"
|
||||
// "\x34\xCF\xBB\x0C\x55\x8E\x09\x9E\xC3\xCE\xBE\x2D\x9E\xE3";
|
||||
const char HUE_LIGHTS_STATUS_JSON1_SUFFIX[] PROGMEM =
|
||||
"%s\"alert\":\"none\","
|
||||
"\"effect\":\"none\","
|
||||
"\"reachable\":true}";
|
||||
|
||||
//,"type":"Extended color light","name":"%s","modelid":"%s","manufacturername":"%s","uniqueid":"%s"}
|
||||
//Successfully compressed from 98 to 64 bytes (-34.7%)
|
||||
// const size_t HUE_LIGHTS_STATUS_JSON2_size = 98;
|
||||
// const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = "\x3A\x8F\x65\x19\x0C\x67\xB0\xF3\x3D\x84\xCD\x94\xF8\x46\x22\x0F\x02\xCF\xA0\xB4"
|
||||
// "\x78\x55\x1E\xC3\xA8\xF6\x75\x8D\x67\xB0\xF3\x3D\x87\xD7\x8F\x61\xD4\x7B\x06\xE0"
|
||||
// "\x8C\x2D\x10\x11\x25\xDF\x0B\x31\x61\xD0\xBF\xBF\x82\x3E\x06\x2F\xB4\xD4\x2D\x82"
|
||||
// "\x1E\x08\x7B\x8D";
|
||||
const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM =
|
||||
",\"type\":\"Extended color light\","
|
||||
"\"name\":\"%s\","
|
||||
"\"modelid\":\"%s\","
|
||||
"\"manufacturername\":\"%s\","
|
||||
"\"uniqueid\":\"%s\"}";
|
||||
|
||||
//{"name":"Group 0","lights":[{l1],"type":"LightGroup","action":
|
||||
//Successfully compressed from 62 to 61 bytes (-1.6%)
|
||||
const char HUE_GROUP0_STATUS_JSON[] PROGMEM =
|
||||
"{\"name\":\"Group 0\","
|
||||
"\"lights\":[{l1],"
|
||||
"\"type\":\"LightGroup\","
|
||||
"\"action\":";
|
||||
// "\"scene\":\"none\",";
|
||||
|
||||
//{"name":"Philips hue","mac":"{ma","dhcp":true,"ipaddress":"{ip","netmask":"{ms","gateway":"{gw","proxyaddress":"none","proxyport":0,"bridgeid":"{br","UTC":"{dt","whitelist":{"{id":{"last use date":"{dt","create date":"{dt","name":"Remote"}},"swversion":"01041302","apiversion":"1.17.0","swupdate":{"updatestate":0,"url":"","text":"","notify": false},"linkbutton":false,"portalservices":false}
|
||||
//Successfully compressed from 392 to 302 bytes (-23%)
|
||||
// const size_t HueConfigResponse_JSON_size = 392;
|
||||
// const char HueConfigResponse_JSON[] PROGMEM = "\x3D\xA7\xB3\xAC\x6B\x3D\x87\x99\xEC\x21\x82\xB4\x2D\x19\xE4\x28\x5B\x3D\x87\x51"
|
||||
// "\xEC\x1B\x61\x9E\xC3\xCC\xF6\x1E\xD1\xB6\x7B\x0E\xA3\xD8\x20\xA0\xC6\x1E\xC3\xCE"
|
||||
// "\xBE\x2D\x9D\x47\xB3\x46\x58\x82\x7D\xFB\xC7\xB0\xF3\x3D\x87\xB7\x46\x1E\xC3\xA8"
|
||||
// "\xF6\x73\xA1\xB7\xE3\x43\xD8\x79\x9E\xC3\xDA\x37\xC7\xB0\xEA\x3D\x83\xD7\x4C\x7E"
|
||||
// "\xCC\x8F\x61\xE6\x7B\x0F\x68\xF0\xF9\xEC\x3A\x8F\x60\xCF\xE1\xB0\xC8\x11\x71\x1E"
|
||||
// "\xCE\x60\x87\x48\x66\x7E\x8F\x61\xE6\x71\x9D\x47\xB0\x87\x7F\x44\x1E\x7A\x21\xEC"
|
||||
// "\x3C\xCF\x61\xED\x1D\xF3\xD8\x75\x1E\xC2\x16\x54\x41\x9E\xC3\xCC\xF6\x1E\xD1\x28"
|
||||
// "\xF6\x1D\x47\xB0\x7C\x56\xD3\x0B\x7D\x47\xB0\xF3\x3D\xA7\xB0\xF6\xE8\x87\xB0\xF3"
|
||||
// "\x3D\xA7\xB0\x2B\xF5\x21\x7E\x68\x4B\xA6\x08\x98\x30\x7F\x77\x40\x95\x40\x10\xB8"
|
||||
// "\x3A\x2F\xB1\xB9\x4C\xF6\x1E\xE3\xDC\x75\x1E\xCF\x0F\x99\xBF\xFB\x73\x8F\x61\xE6"
|
||||
// "\x7B\x0E\x38\xF2\x5B\xA3\xD8\x75\x1E\xC2\xB1\x9A\x08\xB5\x0E\x43\xA4\xF1\xD1\x9E"
|
||||
// "\xC3\xA8\xF6\x17\x87\xC5\x8C\x04\x1C\xB0\xF6\x9E\xC0\x41\x8D\xEA\xBA\x67\xB0\xF3"
|
||||
// "\x38\xCE\xA3\xD8\x42\xFE\x11\xEC\x3C\xCF\x61\xEC\x3A\x8F\x65\x33\x65\x02\x0C\x6E"
|
||||
// "\xCA\xD3\x06\x47\xB0\xF3\x46\x2C\x2F\x33\xDC\x75\x1E\xC0\xB7\x8D\x07\x0B\xAA\xCE"
|
||||
// "\x3D\x87\x99\x8B\x0B\xCC\xEA\x3D\x83\x33\xF5\x61\x79\xFC\xCF\x43\x7E\x04\x2A\x2B"
|
||||
// "\x67\xB8";
|
||||
const char HueConfigResponse_JSON[] PROGMEM =
|
||||
"{\"name\":\"Philips hue\","
|
||||
"\"mac\":\"{ma\","
|
||||
|
@ -85,6 +85,79 @@ void WemoRespondToMSearch(int echo_type)
|
||||
* Wemo web server additions
|
||||
\*********************************************************************************************/
|
||||
|
||||
#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
||||
|
||||
//<scpd xmlns="urn:Belkin:service-1-0"><actionList><action><name>SetBinaryState</name><argumentList><argument><retval/><name>BinaryState</name><relatedStateVariable>BinaryState</relatedStateVariable><direction>in</direction></argument></argumentList></action><action><name>GetBinaryState</name><argumentList><argument><retval/><name>BinaryState</name><relatedStateVariable>BinaryState</relatedStateVariable><direction>out</direction></argument></argumentList></action></actionList><serviceStateTable><stateVariable sendEvents="yes"><name>BinaryState</name><dataType>bool</dataType><defaultValue>0</defaultValue></stateVariable><stateVariable sendEvents="yes"><name>level</name><dataType>string</dataType><defaultValue>0</defaultValue></stateVariable></serviceStateTable></scpd>\r\n\r\n
|
||||
//Successfully compressed from 779 to 249 bytes (-68%)
|
||||
const size_t WEMO_EVENTSERVICE_XML_SIZE = 779;
|
||||
const char WEMO_EVENTSERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3"
|
||||
"\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0A\xC3\xAD\xCE\x20\xB7\xD4\x08"
|
||||
"\x72\x0F\xC3\xD3\xAC\x6B\x3F\x0B\xCE\x88\x76\xF5\xFC\xC8\xBD\x57\x4C\xF4\x3B\x3A"
|
||||
"\xC6\xB3\xF0\xF4\xBF\x8F\x0B\x1A\xFA\x81\x0B\x0D\x04\x29\x47\xE1\xE9\xF7\x46\x76"
|
||||
"\x11\xD8\x08\x58\xC0\x27\x62\xBF\x61\x5D\x31\x0B\xD5\x74\xC8\xCE\xFF\xB6\x38\x20"
|
||||
"\x4A\xC1\x01\x42\xF1\xE8\x26\xFD\x82\x0E\xE7\xBC\x7A\x1D\x80\x8B\x28\xF4\x3B\x01"
|
||||
"\x17\x59\x04\x48\xE0\x83\xB9\x1D\x80\x87\xC1\x20\x24\x70\x58\x43\xC0\xDA\xF8\x2C"
|
||||
"\xC1\x74\x0C\x2F\x82\xD0\x42\x8A\x08\x34\x81\x0B\x92\x42\xF5\x5D\x32\xA0\x41\xCE"
|
||||
"\x7C\x08\xFA\x42\xF3\xE1\x09\x99\xBE\xAF\x1F\x0F\x61\x93\xF1\xEC\x05\x5E\x0A\x44"
|
||||
"\xBA\xB2\xA3\x21\x8C\xFC\x1D\x98\x11\xE8\x76\x02\x24\xB3\xD0\x46\x62\xC5\x85\x44"
|
||||
"\x67\x61\x0B\x67\xE1\xC6\x7A\x1D\x84\x09\x13\x0F\x43\xB0\x12\x34\xC0\x60\x5A\xD8"
|
||||
"\x4C\xCD\x84\x09\x9A\xAF\xAB\xFB\xC3\xC0\xC5\x75\x73\xB0\x13\xB8\x6A\x3B\x3C\x18"
|
||||
"\xC1\x0F\xC9\xC2\x91\xBA\x70\xA4\x6E";
|
||||
|
||||
//<scpd xmlns="urn:Belkin:service-1-0"><specVersion><major>1</major><minor>0</minor></specVersion><actionList><action><name>GetMetaInfo</name><argumentList><retval /><name>GetMetaInfo</name><relatedStateVariable>MetaInfo</relatedStateVariable><direction>in</direction></argumentList></action></actionList><serviceStateTable><stateVariable sendEvents="yes"><name>MetaInfo</name><dataType>string</dataType><defaultValue>0</defaultValue></stateVariable></serviceStateTable></scpd>\r\n\r\n
|
||||
//Successfully compressed from 479 to 253 bytes (-47.2%)
|
||||
const size_t WEMO_METASERVICE_XML_SIZE = 479;
|
||||
const char WEMO_METASERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3"
|
||||
"\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0B\xC3\x18\x64\x66\xFF\xED\xCE"
|
||||
"\x3F\x0F\x41\xB6\x6B\xCF\x9F\x87\x21\xE8\x76\x10\x20\xC5\x3D\x06\xEF\x67\xCF\xC3"
|
||||
"\x8C\xF4\x3B\x08\x10\x62\x9E\x87\x60\x24\x61\x56\x1D\x6E\x71\x05\xBE\xA0\x43\x90"
|
||||
"\x7E\x1E\x9D\x63\x59\xF8\x43\xCE\x88\x6B\xAB\x2D\xE3\x18\x7A\x1D\x9D\x63\x59\xF8"
|
||||
"\x7A\x5F\xC7\x85\x8D\x7D\x40\x83\x85\x7D\xD1\x9D\x84\x8E\xC0\x55\xC3\x3E\xC2\xBA"
|
||||
"\x62\x17\xAA\xE9\x91\x9D\xFF\x6C\x70\x4C\xFC\x04\x5C\x04\x14\x2D\x9E\x82\x6F\xD8"
|
||||
"\x20\xEC\x9B\xC7\xA1\xD8\x08\xB2\x8F\x43\xB0\x12\x75\xB3\xB0\x10\xF8\x0A\x04\x28"
|
||||
"\xA0\x83\x48\x10\xB8\x74\x2F\x55\xD3\x2A\x2B\x04\x1C\xB7\xC0\x8F\x9E\x2F\x3E\x10"
|
||||
"\x99\x9B\xEA\xF1\xF0\xF6\x19\x3F\x1E\xC0\x42\xE0\x68\x12\xF8\x17\x12\xEA\xCA\x8C"
|
||||
"\x86\x33\xF3\xD5\xFD\xE1\xE3\xD0\xEC\x04\x49\xA7\xA0\x8C\xC5\x8B\x0A\x88\xCE\xC2"
|
||||
"\x16\xCF\xC3\x8C\xF4\x3B\x08\x12\x26\x1E\x87\x60\x24\x69\x67\xE1\xE8\x76\x02\x76"
|
||||
"\xDC\x76\x78\x31\x82\x1F\x93\x85\x23\x74\xE1\x48\xDC";
|
||||
|
||||
//<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:%cetBinaryStateResponse xmlns:u="urn:Belkin:service:basicevent:1"><BinaryState>%d</BinaryState></u:%cetBinaryStateResponse></s:Body></s:Envelope>\r\n
|
||||
//Successfully compressed from 282 to 161 bytes (-42.9%)
|
||||
const size_t WEMO_RESPONSE_STATE_SOAP_SIZE = 282;
|
||||
const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "\x3D\x3C\x79\x93\xE3\x36\x16\x0C\x68\xD8\x34\x2E\xF1\xE7\xE3\xE1\xEC\x15\x54\x30"
|
||||
"\xF3\x3B\x0E\xCF\x06\x29\x8D\xBF\x1D\x0D\x83\x42\xF6\x58\xC3\xA6\x7C\x78\xEC\xF6"
|
||||
"\x58\xC3\xB1\x82\x16\x1C\x76\x1E\xC5\xE3\xCD\xF0\x78\x26\xF0\xF1\x7A\x8C\x82\x60"
|
||||
"\xBF\x8C\x02\x0E\x16\x76\x1E\xC3\xF0\xF4\xF1\xE6\x43\xB0\x43\x23\xF0\xF4\x16\x79"
|
||||
"\x9F\x41\xBA\x21\xDB\xD7\xF3\x22\xF5\x5D\x32\xFB\xF0\xCC\xEF\x02\x1E\xDE\x2C\xF8"
|
||||
"\x7B\x05\xFF\x8F\x32\x1C\xC2\x34\xDE\x3C\xFC\xFE\x67\xA1\xB3\xCC\x75\xFB\x43\x66"
|
||||
"\x6F\xA8\xF3\x39\x0F\x61\xF8\x7A\x10\x23\x63\x67\xE1\xF4\x21\xE8\x76\x02\x3C\xC3"
|
||||
"\xD0\xEC\x05\x4C\xFC\xFC\x3D\x0E\xC0\x43\xD8\xCE\xC0\x45\xE1\xA0\xFC\x9C\x29\x1B"
|
||||
"\x8D";
|
||||
|
||||
//<?xml version="1.0"?><root xmlns="urn:Belkin:device-1-0"><device><deviceType>urn:Belkin:device:controllee:1</deviceType><friendlyName>{x1</friendlyName><manufacturer>Belkin International Inc.</manufacturer><modelName>Socket</modelName><modelNumber>3.1415</modelNumber><UDN>uuid:{x2</UDN><serialNumber>{x3</serialNumber><binaryState>0</binaryState><serviceList><service><serviceType>urn:Belkin:service:basicevent:1</serviceType><serviceId>urn:Belkin:serviceId:basicevent1</serviceId><controlURL>/upnp/control/basicevent1</controlURL><eventSubURL>/upnp/event/basicevent1</eventSubURL><SCPDURL>/eventservice.xml</SCPDURL></service><service><serviceType>urn:Belkin:service:metainfo:1</serviceType><serviceId>urn:Belkin:serviceId:metainfo1</serviceId><controlURL>/upnp/control/metainfo1</controlURL><eventSubURL>/upnp/event/metainfo1</eventSubURL><SCPDURL>/metainfoservice.xml</SCPDURL></service></serviceList></device></root>\r\n
|
||||
//Successfully compressed from 923 to 392 bytes (-57.5%)
|
||||
const size_t WEMO_SETUP_XML_SIZE = 923;
|
||||
const char WEMO_SETUP_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E"
|
||||
"\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\x21\xCC\x23\x4D\xE3\xCC\x46"
|
||||
"\x67\xA1\xB3\xAC\xE4\x3A\xD9\xEC\x3F\x0F\x42\x04\x19\x20\x87\x10\xA8\xC8\x63\x3F"
|
||||
"\x01\x33\x07\x3C\xC3\xCE\xAF\xE0\x41\x36\x79\x9C\x87\xA1\xD8\x40\x8D\x83\x9E\x86"
|
||||
"\x3F\xAF\x84\x08\xC8\xBA\xC6\xB3\xF0\xF6\x9B\x0E\x43\xD0\xEC\x20\x48\x9C\x7A\x0D"
|
||||
"\xBE\x16\x62\xC3\xA1\x7F\x7F\x3F\x01\x07\x31\x45\xBD\x4F\xFD\x75\xB9\xD6\x12\x2D"
|
||||
"\xE0\xCE\x87\xA1\xD8\x09\x18\x21\xE8\x37\x04\x61\x17\x58\xD6\x7E\x17\xB0\x33\x47"
|
||||
"\x47\xA1\xD8\x08\xB3\x81\x0A\xC8\xB1\xA3\x9F\xCF\xC3\x96\x74\x99\x34\x81\x0E\xD8"
|
||||
"\x20\xD0\x3D\x08\x59\x08\x5C\x7E\x0B\x17\xA2\x1E\x67\xB4\xD8\x72\x8F\x43\xB0\x88"
|
||||
"\x59\x08\x5C\x7E\x1E\x9E\x7F\xDB\x04\x3B\xA7\xB4\xD8\x72\xCF\x43\xB0\x81\x22\x71"
|
||||
"\xE8\x3B\x7A\xFE\x64\x5E\xAB\xA6\x7E\x1C\x67\xA1\xD8\x40\x8F\x2C\xF4\xF3\xF9\x9E"
|
||||
"\x86\xC8\x2D\xF5\x02\x24\x90\x44\x8A\x09\x7C\x46\x82\x15\x33\xCC\x75\xFB\x43\x66"
|
||||
"\x6F\xA8\xF3\x39\x0F\x43\xB0\x81\x1F\x09\x04\x3C\x58\xB4\x40\x4E\xC5\x0B\x44\x04"
|
||||
"\x6C\x58\x11\x71\x52\xD1\x0F\xC3\xD0\x10\xB8\xE0\x21\x65\xF2\x08\xFC\x3B\x05\x8C"
|
||||
"\xE1\x87\x60\x21\x4D\x3B\x01\x23\x0D\x04\x6C\x08\xF4\x66\x6F\xA8\xBC\x2C\x70\x22"
|
||||
"\xE1\xEC\xCD\xF5\x02\x4E\x1A\x08\xF8\x09\xE8\x45\xE0\xC6\x08\x2F\xE1\x11\xF8\x08"
|
||||
"\x34\x81\x0B\x59\x3A\x1B\x06\x84\x7A\x1D\x80\x87\x5C\x11\x37\x2A\x01\x60\xBC\x34"
|
||||
"\x0D\x75\x7B\xC6\x30\x18\x5F\x0C\xC0\x87\x8A\x03\x02\xE1\x90\x11\xB0\xB0\x5F\xE1"
|
||||
"\x88\x11\xB0\xB0\x51\xE1\x80\x10\xEE\x82\xDF\x0C\x60\x87\x18\x10\x79\x7D\x04\x2E"
|
||||
"\x83\xD1\xF8\x7A\x1D\x9F\xCC\xA3\xF2\x70\xA4\x6E";
|
||||
#else
|
||||
const char WEMO_EVENTSERVICE_XML[] PROGMEM =
|
||||
"<scpd xmlns=\"urn:Belkin:service-1-0\">"
|
||||
"<actionList>"
|
||||
@ -190,6 +263,7 @@ const char WEMO_SETUP_XML[] PROGMEM =
|
||||
"</serviceList>"
|
||||
"</device>"
|
||||
"</root>\r\n";
|
||||
#endif
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
@ -219,7 +293,11 @@ void HandleUpnpEvent(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
||||
snprintf_P(event, sizeof(event), Decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_SIZE).c_str(), state, bitRead(power, devices_present -1), state);
|
||||
#else
|
||||
snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state);
|
||||
#endif
|
||||
WSSend(200, CT_XML, event);
|
||||
}
|
||||
|
||||
@ -227,21 +305,33 @@ void HandleUpnpService(void)
|
||||
{
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE));
|
||||
|
||||
#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
||||
WSSend(200, CT_PLAIN, Decompress(WEMO_EVENTSERVICE_XML, WEMO_EVENTSERVICE_XML_SIZE));
|
||||
#else
|
||||
WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HandleUpnpMetaService(void)
|
||||
{
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE));
|
||||
|
||||
#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
||||
WSSend(200, CT_PLAIN, Decompress(WEMO_METASERVICE_XML, WEMO_METASERVICE_XML_SIZE));
|
||||
#else
|
||||
WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HandleUpnpSetupWemo(void)
|
||||
{
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP));
|
||||
|
||||
#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION)
|
||||
String setup_xml = Decompress(WEMO_SETUP_XML, WEMO_SETUP_XML_SIZE);
|
||||
#else
|
||||
String setup_xml = FPSTR(WEMO_SETUP_XML);
|
||||
#endif
|
||||
setup_xml.replace("{x1", SettingsText(SET_FRIENDLYNAME1));
|
||||
setup_xml.replace("{x2", WemoUuid());
|
||||
setup_xml.replace("{x3", WemoSerialnumber());
|
||||
|
@ -209,10 +209,9 @@ void Ade7953DrvInit(void)
|
||||
}
|
||||
I2cSetActiveFound(ADE7953_ADDR, "ADE7953");
|
||||
Ade7953.init_step = 2;
|
||||
|
||||
Energy.phase_count = 2; // Handle two channels as two phases
|
||||
Energy.voltage_common = true; // Use common voltage and frequency
|
||||
|
||||
Energy.voltage_common = true; // Use common voltage
|
||||
Energy.frequency_common = true; // Use common frequency
|
||||
energy_flg = XNRG_07;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ void SDM120Every250ms(void)
|
||||
break;
|
||||
|
||||
case 9:
|
||||
Energy.export_active = value; // 6.216 kWh
|
||||
Energy.export_active[0] = value; // 6.216 kWh
|
||||
break;
|
||||
|
||||
case 10:
|
||||
|
@ -74,7 +74,7 @@ void Dds2382EverySecond(void)
|
||||
if (Settings.flag3.dds2382_model) { // SetOption71 - Select different Modbus registers for Active Energy (#6531)
|
||||
offset = 19;
|
||||
}
|
||||
Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW
|
||||
Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW
|
||||
float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496.729 kW
|
||||
|
||||
EnergyUpdateTotal(import_active, true); // 484.708 kWh
|
||||
|
@ -40,22 +40,30 @@
|
||||
TasmotaModbus *Sdm630Modbus;
|
||||
|
||||
const uint16_t sdm630_start_addresses[] {
|
||||
0x0000, // L1 - SDM630_VOLTAGE [V]
|
||||
0x0002, // L2 - SDM630_VOLTAGE [V]
|
||||
0x0004, // L3 - SDM630_VOLTAGE [V]
|
||||
0x0006, // L1 - SDM630_CURRENT [A]
|
||||
0x0008, // L2 - SDM630_CURRENT [A]
|
||||
0x000A, // L3 - SDM630_CURRENT [A]
|
||||
0x000C, // L1 - SDM630_POWER [W]
|
||||
0x000E, // L2 - SDM630_POWER [W]
|
||||
0x0010, // L3 - SDM630_POWER [W]
|
||||
0x0018, // L1 - SDM630_REACTIVE_POWER [VAR]
|
||||
0x001A, // L2 - SDM630_REACTIVE_POWER [VAR]
|
||||
0x001C, // L3 - SDM630_REACTIVE_POWER [VAR]
|
||||
0x001E, // L1 - SDM630_POWER_FACTOR
|
||||
0x0020, // L2 - SDM630_POWER_FACTOR
|
||||
0x0022, // L3 - SDM630_POWER_FACTOR
|
||||
0x0156 // Total - SDM630_TOTAL_ACTIVE_ENERGY [Wh]
|
||||
// 3P4 3P3 1P2 Unit Description
|
||||
0x0000, // + - + V Phase 1 line to neutral volts
|
||||
0x0002, // + - - V Phase 2 line to neutral volts
|
||||
0x0004, // + - - V Phase 3 line to neutral volts
|
||||
0x0006, // + + + A Phase 1 current
|
||||
0x0008, // + + - A Phase 2 current
|
||||
0x000A, // + + - A Phase 3 current
|
||||
0x000C, // + - + W Phase 1 power
|
||||
0x000E, // + - + W Phase 2 power
|
||||
0x0010, // + - - W Phase 3 power
|
||||
0x0018, // + - + VAr Phase 1 volt amps reactive
|
||||
0x001A, // + - - VAr Phase 2 volt amps reactive
|
||||
0x001C, // + - - VAr Phase 3 volt amps reactive
|
||||
0x001E, // + - + Phase 1 power factor
|
||||
0x0020, // + - - Phase 2 power factor
|
||||
0x0022, // + - - Phase 3 power factor
|
||||
0x0046, // + + + Hz Frequency of supply voltages
|
||||
0x0160, // + + + kWh Phase 1 export active energy
|
||||
0x0162, // + + + kWh Phase 2 export active energy
|
||||
0x0164, // + + + kWh Phase 3 export active energy
|
||||
// 0x015A, // + + + kWh Phase 1 import active energy
|
||||
// 0x015C, // + + + kWh Phase 2 import active energy
|
||||
// 0x015E, // + + + kWh Phase 3 import active energy
|
||||
0x0156 // + + + kWh Total active energy
|
||||
};
|
||||
|
||||
struct SDM630 {
|
||||
@ -153,6 +161,22 @@ void SDM630Every250ms(void)
|
||||
break;
|
||||
|
||||
case 15:
|
||||
Energy.frequency[0] = value;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
Energy.export_active[0] = value;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
Energy.export_active[1] = value;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
Energy.export_active[2] = value;
|
||||
break;
|
||||
|
||||
case 19:
|
||||
EnergyUpdateTotal(value, true);
|
||||
break;
|
||||
}
|
||||
@ -179,6 +203,7 @@ void Sdm630SnsInit(void)
|
||||
if (result) {
|
||||
if (2 == result) { ClaimSerial(); }
|
||||
Energy.phase_count = 3;
|
||||
Energy.frequency_common = true; // Use common frequency
|
||||
} else {
|
||||
energy_flg = ENERGY_NONE;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ void DDSU666Every250ms(void)
|
||||
break;
|
||||
|
||||
case 7:
|
||||
Energy.export_active = value; // 6.216 kWh
|
||||
Energy.export_active[0] = value; // 6.216 kWh
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2151,6 +2151,7 @@ init10:
|
||||
#else
|
||||
#ifdef ESP32
|
||||
meter_ss[meters] = new HardwareSerial(uart_index);
|
||||
if (uart_index==0) { ClaimSerial(); }
|
||||
uart_index--;
|
||||
if (uart_index<0) uart_index=0;
|
||||
#else
|
||||
@ -2216,7 +2217,13 @@ uint32_t SML_Write(uint32_t meter,char *hstr) {
|
||||
SML_Send_Seq(meter,hstr);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
float SML_GetVal(uint32_t index) {
|
||||
if (index<1 && index>SML_MAX_VARS) { index = 1;}
|
||||
return meter_vars[index-1];
|
||||
}
|
||||
|
||||
#endif // USE_SML_SCRIPT_CMD
|
||||
|
||||
|
||||
void SetDBGLed(uint8_t srcpin, uint8_t ledpin) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user