From 0b6c62f5f929fd621aeecfd2dd3109d88ed2e025 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 13 May 2019 18:26:07 +0200 Subject: [PATCH] Add support for Shelly 1PM Template Add support for Shelly 1PM Template {"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18} (#5716) --- sonoff/_changelog.ino | 1 + sonoff/sonoff.ino | 12 +-- sonoff/support.ino | 5 ++ sonoff/xdrv_03_energy.ino | 125 ++++++++++++++++++------------ sonoff/xdrv_04_light.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 4 +- sonoff/xnrg_01_hlw8012.ino | 121 ++++++++++++++++------------- sonoff/xsns_01_counter.ino | 2 +- sonoff/xsns_05_ds18x20_legacy.ino | 2 +- sonoff/xsns_12_ads1115.ino | 2 +- sonoff/xsns_12_ads1115_i2cdev.ino | 2 +- sonoff/xsns_17_senseair.ino | 2 +- sonoff/xsns_29_mcp230xx.ino | 2 +- sonoff/xsns_30_mpr121.ino | 2 +- 15 files changed, 167 insertions(+), 119 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a44056c11..58c510225 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.5.0.10 20190513 * Enable ADC0 by default in my_user_config.h (#5671) * Add user configurable ADC0 to Module and Template configuration compatible with current FLAG options (#5671) + * Add support for Shelly 1PM Template {"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18} (#5716) * * 6.5.0.9 20190418 * Add command SetOption63 0/1 to disable relay state feedback scan at restart (#5594, #5663) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index dc984d536..049fe688f 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -966,7 +966,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } if (jsflg) { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } else { Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_NOT_SUPPORTED); } @@ -1044,7 +1044,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } Response_P(PSTR("{")); MqttShowPWMState(); // Render the PWM status to MQTT - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } else if (CMND_PWMFREQUENCY == command_code) { if ((1 == payload) || ((payload >= PWM_MIN) && (payload <= PWM_MAX))) { @@ -1765,7 +1765,7 @@ void PublishStatus(uint8_t payload) if ((0 == payload) || (8 == payload) || (10 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); MqttShowSensor(); - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); if (8 == payload) { MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); } else { @@ -1776,7 +1776,7 @@ void PublishStatus(uint8_t payload) if ((0 == payload) || (11 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); MqttShowState(); - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } @@ -1792,7 +1792,7 @@ void MqttShowPWMState(void) first = false; } } - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } void MqttShowState(void) @@ -1859,7 +1859,7 @@ bool MqttShowSensor(void) if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } return json_data_available; diff --git a/sonoff/support.ino b/sonoff/support.ino index 173be5e7b..80c774bbc 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -889,6 +889,11 @@ int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char d return len + mlen; } +int ResponseJsonEnd(void) +{ + return ResponseAppend_P(PSTR("}")); +} + /*********************************************************************************************\ * GPIO Module and Template management \*********************************************************************************************/ diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index b9d9776bb..3075b7c27 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -70,6 +70,9 @@ unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hour float energy_power_last[3] = { 0 }; uint8_t energy_power_delta = 0; +bool energy_voltage_available = true; // Enable if voltage is measured +bool energy_current_available = true; // Enable if current is measured + bool energy_type_dc = false; bool energy_power_on = true; bool energy_min_power_flag = false; @@ -228,7 +231,7 @@ void EnergyMarginCheck(void) jsonflg = true; } if (jsonflg) { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); EnergyMqttShow(); } @@ -310,7 +313,7 @@ void EnergyMqttShow(void) tele_period = 2; EnergyShow(true); tele_period = tele_period_save; - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); energy_power_delta = 0; } @@ -549,19 +552,11 @@ void EnergySnsInit(void) #ifdef USE_WEBSERVER const char HTTP_ENERGY_SNS1[] PROGMEM = - "{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; - -const char HTTP_ENERGY_SNS2[] PROGMEM = "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" "{s}" D_POWER_FACTOR "{m}%s{e}"; -const char HTTP_ENERGY_SNS3[] PROGMEM = - "{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"; - -const char HTTP_ENERGY_SNS4[] PROGMEM = +const char HTTP_ENERGY_SNS2[] PROGMEM = "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = , {m} = , {e} = @@ -570,7 +565,7 @@ const char HTTP_ENERGY_SNS4[] PROGMEM = void EnergyShow(bool json) { char speriod[20]; - char sfrequency[20]; +// char sfrequency[20]; bool show_energy_period = (0 == tele_period); @@ -581,36 +576,37 @@ void EnergyShow(bool json) char power_factor_chr[33]; char frequency_chr[33]; if (!energy_type_dc) { - float apparent_power = energy_apparent_power; - if (isnan(apparent_power)) { - apparent_power = energy_voltage * energy_current; - } - if (apparent_power < energy_active_power) { // Should be impossible - energy_active_power = apparent_power; - } - - if (isnan(power_factor)) { - power_factor = (energy_active_power && apparent_power) ? energy_active_power / apparent_power : 0; - if (power_factor > 1) power_factor = 1; - } - - float reactive_power = energy_reactive_power; - if (isnan(reactive_power)) { - reactive_power = 0; - uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(energy_active_power * 100)) / 10; - if ((energy_current > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { - // calculating reactive power only if current is greater than 0.005A and - // difference between active and apparent power is greater than 1.5W or 1% - reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(energy_active_power * energy_active_power * 100))) / 10; + if (energy_current_available && energy_voltage_available) { + float apparent_power = energy_apparent_power; + if (isnan(apparent_power)) { + apparent_power = energy_voltage * energy_current; + } + if (apparent_power < energy_active_power) { // Should be impossible + energy_active_power = apparent_power; } - } - dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr); - dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr); - dtostrfd(power_factor, 2, power_factor_chr); + if (isnan(power_factor)) { + power_factor = (energy_active_power && apparent_power) ? energy_active_power / apparent_power : 0; + if (power_factor > 1) power_factor = 1; + } + + float reactive_power = energy_reactive_power; + if (isnan(reactive_power)) { + reactive_power = 0; + uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(energy_active_power * 100)) / 10; + if ((energy_current > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { + // calculating reactive power only if current is greater than 0.005A and + // difference between active and apparent power is greater than 1.5W or 1% + reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(energy_active_power * energy_active_power * 100))) / 10; + } + } + + dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr); + dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr); + dtostrfd(power_factor, 2, power_factor_chr); + } if (!isnan(energy_frequency)) { dtostrfd(energy_frequency, Settings.flag2.frequency_resolution, frequency_chr); - snprintf_P(sfrequency, sizeof(sfrequency), PSTR(",\"" D_JSON_FREQUENCY "\":%s"), frequency_chr); } } @@ -640,23 +636,42 @@ void EnergyShow(bool json) ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"), GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr); if (!energy_type_dc) { - ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"), - apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : ""); + if (energy_current_available && energy_voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), + apparent_power_chr, reactive_power_chr, power_factor_chr); + } + if (!isnan(energy_frequency)) { + ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), frequency_chr); + } } - ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), voltage_chr, current_chr); + if (energy_voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), voltage_chr); + } + if (energy_current_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), current_chr); + } + ResponseJsonEnd(); #ifdef USE_DOMOTICZ if (show_energy_period) { // Only send if telemetry dtostrfd(energy_total * 1000, 1, energy_total_chr); DomoticzSensorPowerEnergy((int)energy_active_power, energy_total_chr); // PowerUsage, EnergyToday - DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage - DomoticzSensor(DZ_CURRENT, current_chr); // Current + if (energy_voltage_available) { + DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage + } + if (energy_current_available) { + DomoticzSensor(DZ_CURRENT, current_chr); // Current + } } #endif // USE_DOMOTICZ #ifdef USE_KNX if (show_energy_period) { - KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage); - KnxSensor(KNX_ENERGY_CURRENT, energy_current); + if (energy_voltage_available) { + KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage); + } + if (energy_current_available) { + KnxSensor(KNX_ENERGY_CURRENT, energy_current); + } KnxSensor(KNX_ENERGY_POWER, energy_active_power); if (!energy_type_dc) { KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor); } KnxSensor(KNX_ENERGY_DAILY, energy_daily); @@ -666,12 +681,22 @@ void EnergyShow(bool json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_ENERGY_SNS1, voltage_chr, current_chr, active_power_chr); - if (!energy_type_dc) { - WSContentSend_PD(HTTP_ENERGY_SNS2, apparent_power_chr, reactive_power_chr, power_factor_chr); - if (!isnan(energy_frequency)) { WSContentSend_PD(HTTP_ENERGY_SNS3, frequency_chr); } + if (energy_voltage_available) { + WSContentSend_PD(PSTR("{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"), voltage_chr); } - WSContentSend_PD(HTTP_ENERGY_SNS4, energy_daily_chr, energy_yesterday_chr, energy_total_chr); + if (energy_current_available) { + WSContentSend_PD(PSTR("{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"), current_chr); + } + WSContentSend_PD(PSTR("{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"), active_power_chr); + if (!energy_type_dc) { + if (energy_current_available && energy_voltage_available) { + WSContentSend_PD(HTTP_ENERGY_SNS1, apparent_power_chr, reactive_power_chr, power_factor_chr); + } + if (!isnan(energy_frequency)) { + WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), frequency_chr); + } + } + WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr); #endif // USE_WEBSERVER } } diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 1d2f71788..c9bce585e 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1558,7 +1558,7 @@ void LightState(uint8_t append) ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); } else { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index f51fa55eb..dcd18c6f1 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -448,7 +448,7 @@ bool TimerCommand(void) if (!error) { Response_P(PSTR("{")); PrepShowTimer(index); - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } else if (CMND_TIMERS == command_code) { diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 115da5e15..17b14ef42 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -547,7 +547,7 @@ void RulesEvery100ms(void) tele_period = tele_period_save; if (strlen(mqtt_data)) { mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); RulesProcess(); } } @@ -1144,7 +1144,7 @@ bool RulesCommand(void) for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) { ResponseAppend_P(PSTR("%c\"T%d\":%d"), (i) ? ',' : '{', i +1, (rules_timer[i]) ? (rules_timer[i] - millis()) / 1000 : 0); } - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } else if (CMND_EVENT == command_code) { if (XdrvMailbox.data_len > 0) { diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino index e30532069..67eab0fee 100644 --- a/sonoff/xnrg_01_hlw8012.ino +++ b/sonoff/xnrg_01_hlw8012.ino @@ -127,58 +127,62 @@ void HlwEvery200ms(void) energy_active_power = 0; } - hlw_cf1_timer++; - if (hlw_cf1_timer >= 8) { - hlw_cf1_timer = 0; - hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1; - digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); + if (pin[GPIO_NRG_CF1] < 99) { + hlw_cf1_timer++; + if (hlw_cf1_timer >= 8) { + hlw_cf1_timer = 0; + hlw_select_ui_flag = (hlw_select_ui_flag) ? 0 : 1; + if (pin[GPIO_NRG_SEL] < 99) { + digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); + } - if (hlw_cf1_pulse_counter) { - cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; - } + if (hlw_cf1_pulse_counter) { + cf1_pulse_length = hlw_cf1_summed_pulse_length / hlw_cf1_pulse_counter; + } #ifdef HLW_DEBUG - // Debugging for calculating mean and median - char stemp[100]; - stemp[0] = '\0'; - for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, hlw_debug[i]); - } - for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { - for (uint8_t j = i + 1; j < hlw_cf1_pulse_counter; j++) { - if (hlw_debug[i] > hlw_debug[j]) { // Sort ascending - std::swap(hlw_debug[i], hlw_debug[j]); + // Debugging for calculating mean and median + char stemp[100]; + stemp[0] = '\0'; + for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, hlw_debug[i]); + } + for (uint8_t i = 0; i < hlw_cf1_pulse_counter; i++) { + for (uint8_t j = i + 1; j < hlw_cf1_pulse_counter; j++) { + if (hlw_debug[i] > hlw_debug[j]) { // Sort ascending + std::swap(hlw_debug[i], hlw_debug[j]); + } } } - } - unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), - hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median); + unsigned long median = hlw_debug[(hlw_cf1_pulse_counter +1) / 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), + hlw_cf_power_pulse_length, hlw_select_ui_flag, hlw_cf1_pulse_counter, stemp, hlw_cf1_summed_pulse_length, cf1_pulse_length, median); #endif - if (hlw_select_ui_flag == hlw_ui_flag) { - hlw_cf1_voltage_pulse_length = cf1_pulse_length; + if (hlw_select_ui_flag == hlw_ui_flag) { + hlw_cf1_voltage_pulse_length = cf1_pulse_length; + + if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage + hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; // V *10 + energy_voltage = (float)hlw_u / 10; + } else { + energy_voltage = 0; + } - if (hlw_cf1_voltage_pulse_length && energy_power_on) { // If powered on always provide voltage - hlw_u = (hlw_voltage_ratio * Settings.energy_voltage_calibration) / hlw_cf1_voltage_pulse_length; // V *10 - energy_voltage = (float)hlw_u / 10; } else { - energy_voltage = 0; + hlw_cf1_current_pulse_length = cf1_pulse_length; + + if (hlw_cf1_current_pulse_length && energy_active_power) { // No current if no power being consumed + hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; // mA + energy_current = (float)hlw_i / 1000; + } else { + energy_current = 0; + } + } - - } else { - hlw_cf1_current_pulse_length = cf1_pulse_length; - - if (hlw_cf1_current_pulse_length && energy_active_power) { // No current if no power being consumed - hlw_i = (hlw_current_ratio * Settings.energy_current_calibration) / hlw_cf1_current_pulse_length; // mA - energy_current = (float)hlw_i / 1000; - } else { - energy_current = 0; - } - + hlw_cf1_summed_pulse_length = 0; + hlw_cf1_pulse_counter = 0; } - hlw_cf1_summed_pulse_length = 0; - hlw_cf1_pulse_counter = 0; } } @@ -214,10 +218,14 @@ void HlwSnsInit(void) hlw_current_ratio = HLW_IREF; } - pinMode(pin[GPIO_NRG_SEL], OUTPUT); - digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); - pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); + if (pin[GPIO_NRG_SEL] < 99) { + pinMode(pin[GPIO_NRG_SEL], OUTPUT); + digitalWrite(pin[GPIO_NRG_SEL], hlw_select_ui_flag); + } + if (pin[GPIO_NRG_CF1] < 99) { + pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); + attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); + } pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); } @@ -232,14 +240,23 @@ void HlwDrvInit(void) hlw_model_type = 1; // HJL-01/BL0937 } - hlw_ui_flag = 1; // Voltage on high - if (pin[GPIO_NRG_SEL_INV] < 99) { - pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; - pin[GPIO_NRG_SEL_INV] = 99; - hlw_ui_flag = 0; // Voltage on low - } + if (pin[GPIO_HLW_CF] < 99) { // HLW8012 or HJL-01 based device + + hlw_ui_flag = 1; // Voltage on high + if (pin[GPIO_NRG_SEL_INV] < 99) { + pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; + pin[GPIO_NRG_SEL_INV] = 99; + hlw_ui_flag = 0; // Voltage on low + } + + if (99 == pin[GPIO_NRG_SEL]) { + energy_current_available = false; + } + if (99 == pin[GPIO_NRG_CF1]) { + energy_current_available = false; + energy_voltage_available = false; + } - if ((pin[GPIO_NRG_SEL] < 99) && (pin[GPIO_NRG_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // HLW8012 or HJL-01 based device energy_flg = XNRG_01; } } diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index eadd9a4b9..576f868ff 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -131,7 +131,7 @@ void CounterShow(bool json) } if (json) { if (header) { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } } diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index f02ee9e12..d92843393 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -205,7 +205,7 @@ void Ds18x20Show(bool json) } if (json) { if (dsxflg) { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } Ds18x20Search(); // Check for changes in sensors number diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index a91d969bc..e5a9cf323 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -194,7 +194,7 @@ void Ads1115toJSON(char *comma_j) ResponseAppend_P(PSTR("%s\"A%d\":%d"), comma, i, ads1115_values[i]); comma = (char*)","; } - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } void Ads1115toString(uint8_t address) diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index eb5643c3e..e08833346 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -118,7 +118,7 @@ void Ads1115Show(bool json) } if (json) { if (dsxflg) { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } } diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 7ec8fff65..1cf69d23d 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -153,7 +153,7 @@ void SenseairShow(bool json) if (senseair_type != 2) { ResponseAppend_P(PSTR("%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); } - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index bef4e1738..c853862b6 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -335,7 +335,7 @@ void MCP230xx_Show(bool json) ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); } - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } } diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 6f23117c6..fec6cf10d 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -372,7 +372,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR("}")); + ResponseJsonEnd(); } } // if->running } // for-loop i