Merge pull request #677 from MichaelDvP/dev_

C3/S2 support, tags translated
This commit is contained in:
Proddy
2022-10-13 21:40:14 +02:00
committed by GitHub
50 changed files with 5982 additions and 895 deletions

View File

@@ -129,10 +129,14 @@ void AnalogSensor::reload() {
} else if (sensor.type() == AnalogType::COUNTER) {
LOG_DEBUG("Adding analog I/O Counter sensor on GPIO%d", sensor.gpio());
pinMode(sensor.gpio(), INPUT_PULLUP);
#ifndef ARDUINO_LOLIN_C3_MINI
#if CONFIG_IDF_TARGET_ESP32
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
dacWrite(sensor.gpio(), 255);
}
#elif CONFIG_IDF_TARGET_ESP32S2
if (sensor.gpio() == 23 || sensor.gpio() == 24) {
dacWrite(sensor.gpio(), 255);
}
#endif
sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.gpio());
@@ -157,17 +161,28 @@ void AnalogSensor::reload() {
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
LOG_DEBUG("Adding analog Write sensor on GPIO%d", sensor.gpio());
pinMode(sensor.gpio(), OUTPUT);
#if CONFIG_IDF_TARGET_ESP32
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
if (sensor.offset() > 255) {
sensor.set_offset(255);
} else if (sensor.offset() < 0) {
sensor.set_offset(0);
}
#ifndef ARDUINO_LOLIN_C3_MINI
dacWrite(sensor.gpio(), sensor.offset());
#endif
sensor.set_value(sensor.offset());
} else {
} else
#elif CONFIG_IDF_TARGET_ESP32S2
if (sensor.gpio() == 23 || sensor.gpio() == 24) {
if (sensor.offset() > 255) {
sensor.set_offset(255);
} else if (sensor.offset() < 0) {
sensor.set_offset(0);
}
dacWrite(sensor.gpio(), sensor.offset());
sensor.set_value(sensor.offset());
} else
#endif
{
digitalWrite(sensor.gpio(), sensor.offset() > 0 ? 1 : 0);
sensor.set_value(digitalRead(sensor.gpio()));
}
@@ -337,9 +352,9 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) const {
if (Mqtt::publish_single()) {
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
if (Mqtt::publish_single2cmd()) {
snprintf(topic, sizeof(topic), "%s/%s", (F_(analogsensor)), sensor.name().c_str());
snprintf(topic, sizeof(topic), "%s/%s", F_(analogsensor), sensor.name().c_str());
} else {
snprintf(topic, sizeof(topic), "%s%s/%s", (F_(analogsensor)), "_data", sensor.name().c_str());
snprintf(topic, sizeof(topic), "%s%s/%s", F_(analogsensor), "_data", sensor.name().c_str());
}
char payload[10];
Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats
@@ -575,16 +590,26 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) {
return true;
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
uint8_t v = val;
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
#if CONFIG_IDF_TARGET_ESP32
if ((sensor.gpio() == 25 || sensor.gpio() == 26) && v <= 255) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT);
#ifndef ARDUINO_LOLIN_C3_MINI
dacWrite(sensor.gpio(), sensor.offset());
#endif
publish_sensor(sensor);
return true;
} else if (v == 0 || v == 1) {
} else
#elif CONFIG_IDF_TARGET_ESP32S2
if ((sensor.gpio() == 23 || sensor.gpio() == 24) && v <= 255) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT);
dacWrite(sensor.gpio(), sensor.offset());
publish_sensor(sensor);
return true;
} else
#endif
if (v == 0 || v == 1) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT);

View File

@@ -25,9 +25,6 @@
#ifndef EMSESP_STANDALONE
#include "driver/adc.h"
#ifndef ARDUINO_LOLIN_S2_MINI
#include <esp_bt.h>
#endif
#endif
#include <uuid/log.h>

View File

@@ -117,9 +117,9 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
// default to 'info' for SYSTEM, DALLASENSOR and ANALOGSENSOR, the other devices to 'values' for shortname version
if (num_paths < (id_n > 0 ? 4 : 3)) {
if (device_type < EMSdevice::DeviceType::BOILER) {
command_p = "info";
command_p = F_(info);
} else {
command_p = "values";
command_p = F_(values);
}
} else {
return message(CommandRet::NOT_FOUND, "missing or bad command", output);
@@ -170,15 +170,15 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec
std::string Command::return_code_string(const uint8_t return_code) {
switch (return_code) {
case CommandRet::ERROR:
return ("Error");
return "Error";
case CommandRet::OK:
return ("OK");
return "OK";
case CommandRet::NOT_FOUND:
return ("Not Found");
return "Not Found";
case CommandRet::NOT_ALLOWED:
return ("Not Authorized");
return "Not Authorized";
case CommandRet::FAIL:
return ("Failed");
return "Failed";
default:
break;
}
@@ -296,7 +296,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
}
// we didn't find the command and its not an endpoint, report error
LOG_DEBUG("Command failed: invalid command '%s'", cmd);
LOG_DEBUG("Command failed: invalid command '%s'", cmd ? cmd : "");
return message(CommandRet::NOT_FOUND, "invalid command", output);
}
@@ -367,7 +367,11 @@ bool Command::list(const uint8_t device_type, JsonObject & output) {
for (const auto & cl : sorted_cmds) {
for (const auto & cf : cmdfunctions_) {
if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == std::string(cf.cmd_))) {
output[cl] = Helpers::translated_word(cf.description_);
if (cf.has_flags(CommandFlag::MQTT_SUB_FLAG_WW)) {
output[cl] = EMSdevice::tag_to_string(DeviceValueTAG::TAG_DEVICE_DATA_WW) + " " + Helpers::translated_word(cf.description_);
} else {
output[cl] = Helpers::translated_word(cf.description_);
}
}
}
}
@@ -499,7 +503,7 @@ void Command::show_devices(uuid::console::Shell & shell) {
// output list of all commands to console
// calls show with verbose mode set
void Command::show_all(uuid::console::Shell & shell) {
shell.println(("Available commands (*=do not need authorization): "));
shell.println("Available commands (*=do not need authorization): ");
// show system first
shell.print(COLOR_BOLD_ON);

View File

@@ -155,14 +155,7 @@ void EMSESPShell::add_console_commands() {
}
},
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
return std::vector<std::string>{
("0B"),
("0D"),
("0A"),
("0F"),
("12"),
};
return std::vector<std::string>{"0B", "0D", "0A", "0F", "12"};
});
commands->add_command(ShellContext::MAIN,
@@ -404,7 +397,7 @@ void EMSESPShell::add_console_commands() {
shell.print("Available commands are: ");
Command::show(shell, device_type, false); // non-verbose mode
} else if (return_code != CommandRet::OK) {
shell.printfln(("Bad syntax (error code %d)"), return_code);
shell.printfln("Bad syntax (error code %d)", return_code);
}
},
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
@@ -425,7 +418,7 @@ void EMSESPShell::add_console_commands() {
if (Command::device_has_commands(device_type)) {
for (const auto & cf : Command::commands()) {
if (cf.device_type_ == device_type) {
command_list.emplace_back((cf.cmd_));
command_list.emplace_back(cf.cmd_);
}
}
return command_list;
@@ -449,7 +442,7 @@ void Console::load_standard_commands(unsigned int context) {
// create commands test and t
EMSESPShell::commands->add_command(context,
CommandFlags::USER,
string_vector{("test")},
string_vector{"test"},
string_vector{F_(name_optional), F_(data_optional)},
[](Shell & shell, const std::vector<std::string> & arguments) {
if (arguments.empty()) {
@@ -543,7 +536,7 @@ void Console::load_standard_commands(unsigned int context) {
become_admin(shell);
} else {
shell.delay_until(now + INVALID_PASSWORD_DELAY_MS, [](Shell & shell) {
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, ("Invalid su password on console"));
shell.logger().log(LogLevel::NOTICE, LogFacility::AUTH, "Invalid su password on console");
shell.println("su: incorrect password");
});
}
@@ -692,7 +685,7 @@ void Console::load_system_commands(unsigned int context) {
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
std::string board_profile = Helpers::toUpper(arguments.front());
if (!EMSESP::system_.load_board_profile(data, board_profile)) {
shell.println(("Invalid board profile (S32, E32, MH-ET, NODEMCU, OLIMEX, OLIMEXPOE, C3MINI, CUSTOM)"));
shell.println("Invalid board profile (S32, E32, MH-ET, NODEMCU, OLIMEX, OLIMEXPOE, C3MINI, S2MINI, CUSTOM)");
return;
}
EMSESP::webSettingsService.update(
@@ -731,7 +724,7 @@ std::string EMSESPShell::prompt_suffix() {
}
void EMSESPShell::end_of_transmission() {
invoke_command((F_(exit)));
invoke_command(F_(exit));
}
EMSESPStreamConsole::EMSESPStreamConsole(Stream & stream, bool local)

View File

@@ -204,7 +204,7 @@ void DallasSensor::loop() {
scancnt_ = 0;
} else if (scancnt_ == SCAN_START + 1) { // startup
firstscan_ = sensors_.size();
// LOG_DEBUG(("Adding %d dallas sensor(s) from first scan"), firstscan_);
// LOG_DEBUG("Adding %d dallas sensor(s) from first scan", firstscan_);
} else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor #
scancnt_ = SCAN_START;
sensors_.clear(); // restart scaning and clear to get correct numbering
@@ -399,8 +399,8 @@ bool DallasSensor::get_value_info(JsonObject & output, const char * cmd, const i
}
output["type"] = F_(number);
output["min"] = serialized(Helpers::render_value(val, -55, 0, EMSESP::system_.fahrenheit() ? 2 : 0));
output["max"] = serialized(Helpers::render_value(val, 125, 0, EMSESP::system_.fahrenheit() ? 2 : 0));
output["min"] = serialized(Helpers::render_value(val, (int8_t)-55, 0, EMSESP::system_.fahrenheit() ? (uint8_t)2 : (uint8_t)0));
output["max"] = serialized(Helpers::render_value(val, (int8_t)125, 0, EMSESP::system_.fahrenheit() ? (uint8_t)2 : (uint8_t)0));
output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
output["writeable"] = false;

View File

@@ -1693,7 +1693,7 @@ bool Boiler::set_tempDiffBoiler(const char * value, const int8_t id) {
// Set the dhw temperature 0x33/0x35 or 0xEA
bool Boiler::set_ww_temp(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -1713,7 +1713,7 @@ bool Boiler::set_ww_temp(const char * value, const int8_t id) {
// Set the lower dhw temperature 0xEA
bool Boiler::set_ww_temp_low(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -1735,7 +1735,7 @@ bool Boiler::set_ww_temp_single(const char * value, const int8_t id) {
// Set the dhw disinfection temperature
bool Boiler::set_ww_disinfect_temp(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -1751,7 +1751,7 @@ bool Boiler::set_ww_disinfect_temp(const char * value, const int8_t id) {
// flow temp
bool Boiler::set_flow_temp(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -1766,7 +1766,7 @@ bool Boiler::set_flow_temp(const char * value, const int8_t id) {
// set selected burner power
bool Boiler::set_burn_power(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1778,7 +1778,7 @@ bool Boiler::set_burn_power(const char * value, const int8_t id) {
// Set the dhw flow temperature offset 0x33
bool Boiler::set_ww_flowTempOffset(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v, true)) {
return false;
}
@@ -1794,7 +1794,7 @@ bool Boiler::set_ww_flowTempOffset(const char * value, const int8_t id) {
// set heating activated
bool Boiler::set_heating_activated(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -1810,7 +1810,7 @@ bool Boiler::set_heating_activated(const char * value, const int8_t id) {
// set heating maximum temperature
bool Boiler::set_heating_temp(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -1826,7 +1826,7 @@ bool Boiler::set_heating_temp(const char * value, const int8_t id) {
// set min boiler output
bool Boiler::set_min_power(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1842,7 +1842,7 @@ bool Boiler::set_min_power(const char * value, const int8_t id) {
// set max boiler output
bool Boiler::set_max_power(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1858,7 +1858,7 @@ bool Boiler::set_max_power(const char * value, const int8_t id) {
// set ww on hysteresis
bool Boiler::set_ww_hyst_on(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v, true)) {
return false;
}
@@ -1874,7 +1874,7 @@ bool Boiler::set_ww_hyst_on(const char * value, const int8_t id) {
// set ww off hysteresis
bool Boiler::set_ww_hyst_off(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v, true)) {
return false;
}
@@ -1890,7 +1890,7 @@ bool Boiler::set_ww_hyst_off(const char * value, const int8_t id) {
// set ww charge optimization
bool Boiler::set_ww_chargeOptimization(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -1907,7 +1907,7 @@ bool Boiler::set_ww_chargeOptimization(const char * value, const int8_t id) {
// set dhw max power
bool Boiler::set_ww_maxpower(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1919,7 +1919,7 @@ bool Boiler::set_ww_maxpower(const char * value, const int8_t id) {
// set dhw maximum temperature
bool Boiler::set_ww_maxtemp(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1931,7 +1931,7 @@ bool Boiler::set_ww_maxtemp(const char * value, const int8_t id) {
// set min pump modulation
bool Boiler::set_min_pump(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1947,7 +1947,7 @@ bool Boiler::set_min_pump(const char * value, const int8_t id) {
// set max pump modulation
bool Boiler::set_max_pump(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -1963,7 +1963,7 @@ bool Boiler::set_max_pump(const char * value, const int8_t id) {
// set boiler on hysteresis
bool Boiler::set_hyst_on(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v, true)) {
return false;
}
@@ -1979,7 +1979,7 @@ bool Boiler::set_hyst_on(const char * value, const int8_t id) {
// set boiler off hysteresis
bool Boiler::set_hyst_off(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v, true)) {
return false;
}
@@ -1995,7 +1995,7 @@ bool Boiler::set_hyst_off(const char * value, const int8_t id) {
// set min burner period
bool Boiler::set_burn_period(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -2011,7 +2011,7 @@ bool Boiler::set_burn_period(const char * value, const int8_t id) {
// set pump delay
bool Boiler::set_pump_delay(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -2047,7 +2047,7 @@ bool Boiler::set_ww_mode(const char * value, const int8_t id) {
// turn on/off dhw
bool Boiler::set_ww_activated(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -2071,7 +2071,7 @@ bool Boiler::set_tapwarmwater_activated(const char * value, const int8_t id) {
// return false;
// }
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -2106,7 +2106,7 @@ bool Boiler::set_tapwarmwater_activated(const char * value, const int8_t id) {
// true = on, false = off
// See also https://github.com/emsesp/EMS-ESP/issues/341#issuecomment-596245458 for Junkers
bool Boiler::set_ww_onetime(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -2122,7 +2122,7 @@ bool Boiler::set_ww_onetime(const char * value, const int8_t id) {
// starting dhw disinfect, set to off seems not working
bool Boiler::set_ww_disinfect(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -2139,7 +2139,7 @@ bool Boiler::set_ww_disinfect(const char * value, const int8_t id) {
// Activate / De-activate circulation of dhw 0x35
// true = on, false = off
bool Boiler::set_ww_circulation(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -2155,7 +2155,7 @@ bool Boiler::set_ww_circulation(const char * value, const int8_t id) {
// configuration of dhw circulation pump
bool Boiler::set_ww_circulation_pump(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
@@ -2172,7 +2172,7 @@ bool Boiler::set_ww_circulation_pump(const char * value, const int8_t id) {
// Set the mode of circulation, 1x3min, ... 6x3min, continuous
// true = on, false = off
bool Boiler::set_ww_circulation_mode(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
@@ -2307,7 +2307,7 @@ bool Boiler::set_maintenancedate(const char * value, const int8_t id) {
// Set the pool temperature 0x48A
bool Boiler::set_pool_temp(const char * value, const int8_t id) {
float v = 0;
float v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -2319,7 +2319,7 @@ bool Boiler::set_pool_temp(const char * value, const int8_t id) {
}
bool Boiler::set_emergency_temp(const char * value, const int8_t id) {
int v = 0;
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -2330,7 +2330,7 @@ bool Boiler::set_emergency_temp(const char * value, const int8_t id) {
}
bool Boiler::set_emergency_ops(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}

View File

@@ -25,12 +25,97 @@ REGISTER_FACTORY(Heatpump, EMSdevice::DeviceType::HEATPUMP);
Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
// telegram handlers
register_telegram_type(0x042B, "HP1", false, MAKE_PF_CB(process_HPMonitor1));
// register_telegram_type(0x042B, "HP1", false, MAKE_PF_CB(process_HPMonitor1));
register_telegram_type(0x047B, "HP2", false, MAKE_PF_CB(process_HPMonitor2));
register_telegram_type(0x998, "HPSettings", true, MAKE_PF_CB(process_HPSettings));
register_telegram_type(0x999, "HPFunctionTest", true, MAKE_PF_CB(process_HPFunctionTest));
// device values
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &airHumidity_, DeviceValueType::UINT, FL_(airHumidity), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dewTemperature_, DeviceValueType::UINT, FL_(dewTemperature), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&controlStrategy_,
DeviceValueType::ENUM,
FL_(enum_hybridStrategy),
FL_(hybridStrategy),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_controlStrategy));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&lowNoiseMode_,
DeviceValueType::ENUM,
FL_(enum_lowNoiseMode),
FL_(lowNoiseMode),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_lowNoiseMode));
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &lowNoiseStart_, DeviceValueType::UINT, FL_(lowNoiseStart), DeviceValueUOM::NONE, MAKE_CF_CB(set_lowNoiseStart), 0, 23);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &lowNoiseStop_, DeviceValueType::UINT, FL_(lowNoiseStop), DeviceValueUOM::NONE, MAKE_CF_CB(set_lowNoiseStop), 0, 23);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&hybridDHW_,
DeviceValueType::ENUM,
FL_(enum_comfort2),
FL_(hybridDHW),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_hybridDHW));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&energyPriceGas_,
DeviceValueType::UINT,
FL_(energyPriceGas),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_energyPriceGas));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&energyPriceEl_,
DeviceValueType::UINT,
FL_(energyPriceEl),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_energyPriceEl));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&energyPricePV_,
DeviceValueType::UINT,
FL_(energyPricePV),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_energyPricePV));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&switchOverTemp_,
DeviceValueType::INT,
FL_(switchOverTemp),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_switchOverTemp));
// Function test
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&airPurgeMode_,
DeviceValueType::BOOL,
FL_(airPurgeMode),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_airPurgeMode));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatPumpOutput_,
DeviceValueType::UINT,
FL_(heatPumpOutput),
DeviceValueUOM::PERCENT,
MAKE_CF_CB(set_heatPumpOutput));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&coolingCircuit_,
DeviceValueType::BOOL,
FL_(coolingCircuit),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_coolingCircuit));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&compStartMod_,
DeviceValueType::UINT,
FL_(compStartMod),
DeviceValueUOM::PERCENT,
MAKE_CF_CB(set_compStartMod));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&heatDrainPan_,
DeviceValueType::BOOL,
FL_(heatDrainPan),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_heatDrainPan));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatCable_, DeviceValueType::BOOL, FL_(heatCable), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatCable));
}
/*
@@ -53,6 +138,175 @@ void Heatpump::process_HPMonitor1(std::shared_ptr<const Telegram> telegram) {
// still to implement
}
// 0x0998 HPSettings
// [emsesp] Heatpump(0x53) -> Me(0x0B), ?(0x0998), data: 00 00 0B 00 00 1F 01 00 01 01 16 06 00 04 02 FF 00 01 7C 01
void Heatpump::process_HPSettings(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, controlStrategy_, 0);
has_update(telegram, hybridDHW_, 1);
has_update(telegram, energyPriceGas_, 2);
has_update(telegram, energyPriceEl_, 5);
has_update(telegram, energyPricePV_, 6);
has_update(telegram, lowNoiseMode_, 9);
has_update(telegram, lowNoiseStart_, 10);
has_update(telegram, lowNoiseStop_, 11);
has_update(telegram, switchOverTemp_, 14);
}
void Heatpump::process_HPFunctionTest(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, airPurgeMode_, 0);
has_update(telegram, heatPumpOutput_, 2);
has_update(telegram, coolingCircuit_, 6);
has_update(telegram, compStartMod_, 7);
has_update(telegram, heatDrainPan_, 9);
has_update(telegram, heatCable_, 10);
}
/*
* Broadcast (0x099A), data: 05 00 00 00 00 00 00 37 00 00 1D 00 00 52 00 00 13 01 00 01 7C
* Broadcast (0x099B), data: 80 00 80 00 01 3C 01 38 80 00 80 00 80 00 01 37 00 00 00 00 64
* Broadcast (0x099C), data: 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 76 00 00
data: 00 2B 00 03 04 13 00 00 00 00 00 02 02 02 (offset 24)
* Broadcast (0x099D), data: 02 02 00 00 02 00 01 38 00 00 63 03 E8 00 00 00 00
* Broadcast (0x099E), data: 03
* Broadcast (0x099F), data 05 4E 20 00 00 00 00 02 00 01 34 00 00 3F 00 00 5C 00 01 DD 00 01 37 00
data 00 3F 00 00 5D 00 00 57 00 02 23 00 01 3D 02 80 00 5A 01 86 01 68 00 00 C0 (offset 24)
data 00 00 00 00 (offset 49)
* Broadcast (0x09A0), data: 02 23 01 3E 01 39 00 5D 01 DE 01 38 00 40 00 5E 00 58 00 3F 01 34 00 02
* Broadcast (0x09A2), data: 00 00 00 00
* Broadcast (0x09A3), data: 01 01 01 00 0A 01 0A 00 00 00 00 00 00 01 01 00 00 (offset 2)
* Broadcast (0x09A4), data: 00 35 00 00 01 42 00 00 00 00 30 01 00 00 00 00 00 00 00 00 00 00 00 00 00
data: 02 (offset 25)
* Broadcast (0x09A5), data: 00 00 00 00 00 00 00 00 0A 01 00 01 03 03 00 5A 00 00 00 00 00 00 00 00 14
data: 00 00 00 (offset 25)
* Broadcast (0x09A6), data: 05 01 00 01 F4 1F 01 1F 01 01 03 00 3F 00 00 00 19 64 00 3C 00 01 01 19
data: 02 EC 01 19 00 (offset 24)
* Broadcast (0x09A8), data: 01 18 01 00 01 17 00 06 00 00 86 06 00 2E 07 D0 00 00 00 45 00 04
* Broadcast (0x04AA), data: 00 00
*/
#pragma GCC diagnostic pop
bool Heatpump::set_controlStrategy(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_hybridStrategy1))) {
return false;
}
write_command(0x998, 0, v, 0x998);
return true;
}
bool Heatpump::set_lowNoiseMode(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_lowNoiseMode))) {
return false;
}
write_command(0x998, 9, v, 0x998);
return true;
}
bool Heatpump::set_lowNoiseStart(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v, 0, 23)) {
return false;
}
write_command(0x998, 10, v, 0x998);
return true;
}
bool Heatpump::set_lowNoiseStop(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v, 0, 23)) {
return false;
}
write_command(0x998, 11, v, 0x998);
return true;
}
bool Heatpump::set_hybridDHW(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_comfort2))) {
return false;
}
write_command(0x998, 1, v, 0x998);
return true;
}
bool Heatpump::set_energyPriceGas(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x998, 2, v, 0x998);
return true;
}
bool Heatpump::set_energyPriceEl(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x998, 5, v, 0x998);
return true;
}
bool Heatpump::set_energyPricePV(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x998, 6, v, 0x998);
return true;
}
bool Heatpump::set_switchOverTemp(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
write_command(0x998, 14, v, 0x998);
return true;
}
// Function tests:
bool Heatpump::set_airPurgeMode(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x999, 0, v, 0x999);
return true;
}
bool Heatpump::set_heatPumpOutput(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v, 0, 100)) {
return false;
}
write_command(0x999, 2, v, 0x999);
return true;
}
bool Heatpump::set_coolingCircuit(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x999, 6, v, 0x999);
return true;
}
bool Heatpump::set_compStartMod(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v, 0, 100)) {
return false;
}
write_command(0x999, 7, v, 0x999);
return true;
}
bool Heatpump::set_heatDrainPan(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x999, 9, v, 0x999);
return true;
}
bool Heatpump::set_heatCable(const char * value, const int8_t id) {
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}
write_command(0x999, 10, v, 0x999);
return true;
}
} // namespace emsesp

View File

@@ -31,8 +31,46 @@ class Heatpump : public EMSdevice {
uint8_t airHumidity_;
uint8_t dewTemperature_;
// HM200
uint8_t controlStrategy_;
uint8_t lowNoiseMode_;
uint8_t lowNoiseStart_;
uint8_t lowNoiseStop_;
uint8_t hybridDHW_;
uint8_t energyPriceGas_;
uint8_t energyPriceEl_;
uint8_t energyPricePV_;
int8_t switchOverTemp_;
// Function test
uint8_t airPurgeMode_;
uint8_t heatPumpOutput_;
uint8_t coolingCircuit_;
uint8_t compStartMod_;
uint8_t heatDrainPan_;
uint8_t heatCable_;
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);
void process_HPSettings(std::shared_ptr<const Telegram> telegram);
void process_HPFunctionTest(std::shared_ptr<const Telegram> telegram);
bool set_controlStrategy(const char * value, const int8_t id);
bool set_lowNoiseMode(const char * value, const int8_t id);
bool set_lowNoiseStart(const char * value, const int8_t id);
bool set_lowNoiseStop(const char * value, const int8_t id);
bool set_hybridDHW(const char * value, const int8_t id);
bool set_energyPriceGas(const char * value, const int8_t id);
bool set_energyPriceEl(const char * value, const int8_t id);
bool set_energyPricePV(const char * value, const int8_t id);
bool set_switchOverTemp(const char * value, const int8_t id);
bool set_airPurgeMode(const char * value, const int8_t id);
bool set_heatPumpOutput(const char * value, const int8_t id);
bool set_coolingCircuit(const char * value, const int8_t id);
bool set_compStartMod(const char * value, const int8_t id);
bool set_heatDrainPan(const char * value, const int8_t id);
bool set_heatCable(const char * value, const int8_t id);
};
} // namespace emsesp

View File

@@ -389,7 +389,7 @@ bool Mixer::set_setValveTime(const char * value, const int8_t id) {
bool Mixer::set_wwMaxTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
float v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -399,7 +399,7 @@ bool Mixer::set_wwMaxTemp(const char * value, const int8_t id) {
bool Mixer::set_wwDiffTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
float v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -409,7 +409,7 @@ bool Mixer::set_wwDiffTemp(const char * value, const int8_t id) {
bool Mixer::set_wwReducedTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
float v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -419,7 +419,7 @@ bool Mixer::set_wwReducedTemp(const char * value, const int8_t id) {
bool Mixer::set_wwRequiredTemp(const char * value, const int8_t id) {
uint8_t wwc = device_id() - 0x28;
float v = 0;
float v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -428,7 +428,7 @@ bool Mixer::set_wwRequiredTemp(const char * value, const int8_t id) {
}
bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) {
float v = 0;
float v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
@@ -442,7 +442,7 @@ bool Mixer::set_wwDisinfectionTemp(const char * value, const int8_t id) {
}
bool Mixer::set_wwCircPump(const char * value, const int8_t id) {
bool v = false;
bool v;
if (!Helpers::value2bool(value, v)) {
return false;
}

View File

@@ -593,12 +593,12 @@ void Thermostat::process_RC20Timer(std::shared_ptr<const Telegram> telegram) {
uint8_t time = telegram->message_data[1];
// we use EN settings for the day abbreviation
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
auto sday = (FL_(enum_dayOfWeek)[day][0]);
if (day == 7) {
snprintf(data, sizeof(data), "%02d not_set", no);
} else {
snprintf(data, sizeof(data), "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), temp);
snprintf(data, sizeof(data), "%02d %s %02d:%02d T%d", no, sday, time / 6, 10 * (time % 6), temp);
}
has_update(hc->switchtime1, data, sizeof(hc->switchtime1));
}
@@ -679,12 +679,6 @@ void Thermostat::process_JunkersSet(std::shared_ptr<const Telegram> telegram) {
return;
}
has_update(telegram, hc->daytemp, 17); // is * 2
has_update(telegram, hc->nighttemp, 16); // is * 2
has_update(telegram, hc->nofrosttemp, 15); // is * 2
has_update(telegram, hc->control, 1); // remote: 0-off, 1-FB10, 2-FB100
has_enumupdate(telegram, hc->program, 13, 1); // 1-6: 1 = A, 2 = B,...
has_enumupdate(telegram, hc->mode, 14, 1); // 0 = nofrost, 1 = eco, 2 = heat, 3 = auto
has_update(telegram, hc->daytemp, 17); // is * 2
has_update(telegram, hc->nighttemp, 16); // is * 2
has_update(telegram, hc->nofrosttemp, 15); // is * 2
@@ -800,11 +794,11 @@ void Thermostat::process_RC35wwTimer(std::shared_ptr<const Telegram> telegram) {
char data[sizeof(wwSwitchTime_)];
// we use EN settings for the day abbreviation
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
auto sday = (FL_(enum_dayOfWeek)[day][0]);
if (day == 7) {
snprintf(data, sizeof(data), "%02d not_set", no);
} else {
snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday, time / 6, 10 * (time % 6), on ? "on" : "off");
}
if (telegram->type_id == 0x38) {
has_update(wwSwitchTime_, data, sizeof(wwSwitchTime_));
@@ -1270,13 +1264,13 @@ void Thermostat::process_RC35Timer(std::shared_ptr<const Telegram> telegram) {
uint8_t time = telegram->message_data[1];
// we use EN settings for the day abbreviation
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
auto sday = (FL_(enum_dayOfWeek)[day][0]);
if (day == 7) {
snprintf(data, sizeof(data), "%02d not_set", no);
} else if (model() == EMS_DEVICE_FLAG_RC30) {
snprintf(data, sizeof(data), "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on);
snprintf(data, sizeof(data), "%02d %s %02d:%02d T%d", no, sday, time / 6, 10 * (time % 6), on);
} else {
snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
snprintf(data, sizeof(data), "%02d %s %02d:%02d %s", no, sday, time / 6, 10 * (time % 6), on ? "on" : "off");
}
if (!prog) {
strlcpy(hc->switchtime1, data, sizeof(hc->switchtime1));
@@ -1506,7 +1500,7 @@ bool Thermostat::set_tempDiffBoiler(const char * value, const int8_t id) {
// 0xA5 - Set minimum external temperature
bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
int mt = 0;
int mt;
if (!Helpers::value2temperature(value, mt)) {
return false;
}
@@ -1524,7 +1518,7 @@ bool Thermostat::set_minexttemp(const char * value, const int8_t id) {
// 0xA5/0xA7 - Clock offset
bool Thermostat::set_clockoffset(const char * value, const int8_t id) {
int co = 0;
int co;
if (!Helpers::value2number(value, co)) {
return false;
}
@@ -1540,7 +1534,7 @@ bool Thermostat::set_clockoffset(const char * value, const int8_t id) {
// 0xA5/0xA7 - Calibrate internal temperature
bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
float ct = 0;
float ct;
if (!Helpers::value2temperature(value, ct, true)) {
return false;
}
@@ -1577,7 +1571,7 @@ bool Thermostat::set_display(const char * value, const int8_t id) {
// 0xA7 - Set Screen brightness
bool Thermostat::set_brightness(const char * value, const int8_t id) {
int bo = 0;
int bo;
if (!Helpers::value2number(value, bo, -15, 15)) {
return false;
}
@@ -1588,7 +1582,7 @@ bool Thermostat::set_brightness(const char * value, const int8_t id) {
}
bool Thermostat::set_remotetemp(const char * value, const int8_t id) {
float f = 0;
float f;
if (!Helpers::value2temperature(value, f)) {
return false;
}
@@ -1612,7 +1606,7 @@ bool Thermostat::set_remotetemp(const char * value, const int8_t id) {
// 0xA5/0xA7 - Set the building settings
bool Thermostat::set_building(const char * value, const int8_t id) {
uint8_t bd = 0;
uint8_t bd;
if (!Helpers::value2enum(value, bd, FL_(enum_ibaBuildingType))) {
return false;
}
@@ -1630,7 +1624,7 @@ bool Thermostat::set_building(const char * value, const int8_t id) {
// 0xB0/0xA7 - Set RC10 heating pid
bool Thermostat::set_heatingpid(const char * value, const int8_t id) {
uint8_t pid = 0;
uint8_t pid;
if (!Helpers::value2enum(value, pid, FL_(enum_PID))) {
return false;
}
@@ -1663,7 +1657,7 @@ bool Thermostat::set_damping(const char * value, const int8_t id) {
// 0xA5/0xA7 Set the language settings
bool Thermostat::set_language(const char * value, const int8_t id) {
uint8_t lg = 0;
uint8_t lg;
if (model() == EMS_DEVICE_FLAG_RC30) {
if (!Helpers::value2enum(value, lg, FL_(enum_ibaLanguage_RC30))) {
@@ -1688,7 +1682,7 @@ bool Thermostat::set_control(const char * value, const int8_t id) {
return false;
}
uint8_t ctrl = 0;
uint8_t ctrl;
if (model() == EMS_DEVICE_FLAG_JUNKERS && !has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
if (Helpers::value2enum(value, ctrl, FL_(enum_j_control))) {
write_command(set_typeids[hc->hc()], 1, ctrl);
@@ -1710,7 +1704,7 @@ bool Thermostat::set_roomsensor(const char * value, const int8_t id) {
return false;
}
uint8_t ctrl = 0;
uint8_t ctrl;
if (model() == EMS_DEVICE_FLAG_JUNKERS && !has_flags(EMS_DEVICE_FLAG_JUNKERS_OLD)) {
if (Helpers::value2enum(value, ctrl, FL_(enum_roomsensor))) {
write_command(set_typeids[hc->hc()], 9, ctrl + 1);
@@ -1722,7 +1716,7 @@ bool Thermostat::set_roomsensor(const char * value, const int8_t id) {
// sets the thermostat ww working mode, where mode is a string, ems and ems+
bool Thermostat::set_wwmode(const char * value, const int8_t id) {
uint8_t set = 0xFF;
uint8_t set;
if (model() == EMS_DEVICE_FLAG_RC10) {
if (!Helpers::value2enum(value, set, FL_(enum_wwMode3))) {
@@ -1751,7 +1745,7 @@ bool Thermostat::set_wwmode(const char * value, const int8_t id) {
//Set ww when thermostat mode is off (RC30)
bool Thermostat::set_wwwhenmodeoff(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1775,7 +1769,7 @@ bool Thermostat::set_wwtemp(const char * value, const int8_t id) {
// Set ww low temperature, ems+
bool Thermostat::set_wwtemplow(const char * value, const int8_t id) {
int t = 0;
int t;
if (!Helpers::value2temperature(value, t)) {
return false;
}
@@ -1787,7 +1781,7 @@ bool Thermostat::set_wwtemplow(const char * value, const int8_t id) {
// Set ww charge RC300, ems+
bool Thermostat::set_wwcharge(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1803,7 +1797,7 @@ bool Thermostat::set_wwcharge(const char * value, const int8_t id) {
// Set ww charge duration in steps of 15 min, ems+
bool Thermostat::set_wwchargeduration(const char * value, const int8_t id) {
int t = 0xFF;
int t;
if (!Helpers::value2number(value, t)) {
return false;
}
@@ -1837,7 +1831,7 @@ bool Thermostat::set_wwprio(const char * value, const int8_t id) {
// sets the thermostat ww circulation working mode, where mode is a string
bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
uint8_t set = 0xFF;
uint8_t set;
if ((model() == EMS_DEVICE_FLAG_RC300) || (model() == EMS_DEVICE_FLAG_RC100)) {
if (!Helpers::value2enum(value, set, FL_(enum_wwCircMode))) {
@@ -1856,7 +1850,7 @@ bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
}
bool Thermostat::set_wwDailyHeating(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1883,7 +1877,7 @@ bool Thermostat::set_wwDailyHeatTime(const char * value, const int8_t id) {
}
bool Thermostat::set_wwDisinfect(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1900,7 +1894,7 @@ bool Thermostat::set_wwDisinfect(const char * value, const int8_t id) {
}
bool Thermostat::set_wwDisinfectDay(const char * value, const int8_t id) {
uint8_t set = 0xFF;
uint8_t set;
if (!Helpers::value2enum(value, set, FL_(enum_dayOfWeek))) {
return false;
}
@@ -1939,7 +1933,7 @@ bool Thermostat::set_wwDisinfectHour(const char * value, const int8_t id) {
}
bool Thermostat::set_wwMaxTemp(const char * value, const int8_t id) {
int t = 0;
int t;
if (!Helpers::value2temperature(value, t, false, 0, 90)) {
return false;
}
@@ -1962,7 +1956,7 @@ bool Thermostat::set_wwOneTimeKey(const char * value, const int8_t id) {
// for RC10, 0xB0 or RC30, 0xA7
bool Thermostat::set_backlight(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1977,7 +1971,7 @@ bool Thermostat::set_backlight(const char * value, const int8_t id) {
}
bool Thermostat::set_autodst(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1988,7 +1982,7 @@ bool Thermostat::set_autodst(const char * value, const int8_t id) {
}
bool Thermostat::set_preheating(const char * value, const int8_t id) {
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
}
@@ -1999,7 +1993,7 @@ bool Thermostat::set_preheating(const char * value, const int8_t id) {
}
bool Thermostat::set_offtemp(const char * value, const int8_t id) {
int ot = 0;
int ot;
if (!Helpers::value2temperature(value, ot, true)) {
return false;
}
@@ -2011,7 +2005,7 @@ bool Thermostat::set_offtemp(const char * value, const int8_t id) {
}
bool Thermostat::set_mixingvalves(const char * value, const int8_t id) {
int m = 0;
int m;
if (!Helpers::value2number(value, m, 0, 2)) {
return false;
}
@@ -2022,7 +2016,7 @@ bool Thermostat::set_mixingvalves(const char * value, const int8_t id) {
}
bool Thermostat::set_wwProgMode(const char * value, const int8_t id) {
uint8_t set = 0xFF;
uint8_t set;
if (!Helpers::value2enum(value, set, FL_(enum_wwProgMode))) {
return false;
}
@@ -2033,7 +2027,7 @@ bool Thermostat::set_wwProgMode(const char * value, const int8_t id) {
}
bool Thermostat::set_wwCircProg(const char * value, const int8_t id) {
uint8_t set = 0xFF;
uint8_t set;
if (!Helpers::value2enum(value, set, FL_(enum_wwProgMode))) {
return false;
}
@@ -2199,7 +2193,7 @@ bool Thermostat::set_roominfl_factor(const char * value, const int8_t id) {
if (hc == nullptr) {
return false;
}
float val = 0;
float val;
if (!Helpers::value2float(value, val)) {
return false;
}
@@ -2416,7 +2410,7 @@ bool Thermostat::set_summermode(const char * value, const int8_t id) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if (is_fetch(summer2_typeids[hc->hc()])) {
if ((hc->statusbyte & 1) && Helpers::value2enum(value, set, FL_(enum_summermode))) {
@@ -2442,7 +2436,7 @@ bool Thermostat::set_fastheatup(const char * value, const int8_t id) {
return false;
}
int set = 0;
int set;
if (!Helpers::value2number(value, set)) {
return false;
@@ -2460,7 +2454,7 @@ bool Thermostat::set_switchonoptimization(const char * value, const int8_t id) {
return false;
}
bool b = false;
bool b;
if (!Helpers::value2bool(value, b)) {
return false;
@@ -2478,7 +2472,7 @@ bool Thermostat::set_reducemode(const char * value, const int8_t id) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if (model() == EMS_DEVICE_FLAG_RC300 || model() == EMS_DEVICE_FLAG_RC100) {
if (Helpers::value2enum(value, set, FL_(enum_reducemode1))) {
write_command(set_typeids[hc->hc()], 5, set + 1, set_typeids[hc->hc()]);
@@ -2502,7 +2496,7 @@ bool Thermostat::set_vacreducemode(const char * value, const int8_t id) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if (!Helpers::value2enum(value, set, FL_(enum_reducemode))) {
return false;
}
@@ -2518,7 +2512,7 @@ bool Thermostat::set_nofrostmode(const char * value, const int8_t id) {
if (hc == nullptr) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if (model() == EMS_DEVICE_FLAG_RC300 || model() == EMS_DEVICE_FLAG_RC100) {
if (Helpers::value2enum(value, set, FL_(enum_nofrostmode1))) {
write_command(curve_typeids[hc->hc()], 5, set + 1, curve_typeids[hc->hc()]);
@@ -2541,7 +2535,7 @@ bool Thermostat::set_heatingtype(const char * value, const int8_t id) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if (Helpers::value2enum(value, set, FL_(enum_heatingtype))) {
if ((model() == EMS_DEVICE_FLAG_RC20_N) || (model() == EMS_DEVICE_FLAG_RC25)) {
write_command(set_typeids[hc->hc()], 0, set, set_typeids[hc->hc()]);
@@ -2566,7 +2560,7 @@ bool Thermostat::set_controlmode(const char * value, const int8_t id) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if (model() == EMS_DEVICE_FLAG_RC100) {
if (Helpers::value2enum(value, set, FL_(enum_controlmode))) {
write_command(curve_typeids[hc->hc()], 0, set, curve_typeids[hc->hc()]);
@@ -2726,14 +2720,14 @@ bool Thermostat::set_switchtime(const char * value, const uint16_t type_id, char
}
if (data[0] != 0xE7) {
// we use EN settings for the day abbreviation
std::string sday = (FL_(enum_dayOfWeek)[day][0]);
auto sday = (FL_(enum_dayOfWeek)[day][0]);
if (model() == EMS_DEVICE_FLAG_RC35 || model() == EMS_DEVICE_FLAG_RC30_N) {
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), on ? "on" : "off");
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday, time / 6, 10 * (time % 6), on ? "on" : "off");
} else if ((model() == EMS_DEVICE_FLAG_RC20) || (model() == EMS_DEVICE_FLAG_RC30)) {
snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday.c_str(), time / 6, 10 * (time % 6), on);
snprintf(out, len, "%02d %s %02d:%02d T%d", no, sday, time / 6, 10 * (time % 6), on);
} else {
std::string son = (FL_(enum_switchmode)[on][0]);
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday.c_str(), time / 6, 10 * (time % 6), son.c_str());
auto son = (FL_(enum_switchmode)[on][0]);
snprintf(out, len, "%02d %s %02d:%02d %s", no, sday, time / 6, 10 * (time % 6), son);
}
} else {
snprintf(out, len, "%02d not_set", no);
@@ -2811,7 +2805,7 @@ bool Thermostat::set_program(const char * value, const int8_t id) {
return false;
}
uint8_t set = 0xFF;
uint8_t set;
if ((model() == EMS_DEVICE_FLAG_RC20_N) || (model() == EMS_DEVICE_FLAG_RC25)) {
if (Helpers::value2enum(value, set, FL_(enum_progMode3))) {
write_command(set_typeids[hc->hc()], 11, set + 1, set_typeids[hc->hc()]);
@@ -3249,7 +3243,7 @@ bool Thermostat::set_temperature(const float temperature, const uint8_t mode, co
}
bool Thermostat::set_temperature_value(const char * value, const int8_t id, const uint8_t mode, bool relative) {
float f = 0;
float f;
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
if (Helpers::value2temperature(value, f, relative)) {
return set_temperature(f, mode, hc_num);

View File

@@ -44,7 +44,7 @@ bool EMSdevice::has_entities() const {
}
std::string EMSdevice::tag_to_string(uint8_t tag) {
return (DeviceValue::DeviceValueTAG_s[tag]);
return (Helpers::translated_word(DeviceValue::DeviceValueTAG_s[tag]));
}
std::string EMSdevice::tag_to_mqtt(uint8_t tag) {
@@ -62,21 +62,21 @@ std::string EMSdevice::uom_to_string(uint8_t uom) {
std::string EMSdevice::brand_to_string() const {
switch (brand_) {
case EMSdevice::Brand::BOSCH:
return ("Bosch");
return "Bosch";
case EMSdevice::Brand::JUNKERS:
return ("Junkers");
return "Junkers";
case EMSdevice::Brand::BUDERUS:
return ("Buderus");
return "Buderus";
case EMSdevice::Brand::NEFIT:
return ("Nefit");
return "Nefit";
case EMSdevice::Brand::SIEGER:
return ("Sieger");
return "Sieger";
case EMSdevice::Brand::WORCESTER:
return ("Worcester");
return "Worcester";
case EMSdevice::Brand::IVT:
return ("IVT");
return "IVT";
default:
return ("");
return "";
}
}
@@ -84,29 +84,29 @@ std::string EMSdevice::brand_to_string() const {
const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) {
switch (device_type) {
case DeviceType::SYSTEM:
return (F_(system));
return F_(system);
case DeviceType::BOILER:
return (F_(boiler));
return F_(boiler);
case DeviceType::THERMOSTAT:
return (F_(thermostat));
return F_(thermostat);
case DeviceType::HEATPUMP:
return (F_(heatpump));
return F_(heatpump);
case DeviceType::SOLAR:
return (F_(solar));
return F_(solar);
case DeviceType::CONNECT:
return (F_(connect));
return F_(connect);
case DeviceType::MIXER:
return (F_(mixer));
return F_(mixer);
case DeviceType::DALLASSENSOR:
return (F_(dallassensor));
return F_(dallassensor);
case DeviceType::ANALOGSENSOR:
return (F_(analogsensor));
return F_(analogsensor);
case DeviceType::CONTROLLER:
return (F_(controller));
return F_(controller);
case DeviceType::SWITCH:
return (F_(switch));
return F_(switch);
case DeviceType::GATEWAY:
return (F_(gateway));
return F_(gateway);
default:
return Helpers::translated_word(FL_(unknown));
}
@@ -125,35 +125,35 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
*p = tolower(*p);
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(boiler)))) {
if (!strcmp(lowtopic, F_(boiler))) {
return DeviceType::BOILER;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(thermostat)))) {
if (!strcmp(lowtopic, F_(thermostat))) {
return DeviceType::THERMOSTAT;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(system)))) {
if (!strcmp(lowtopic, F_(system))) {
return DeviceType::SYSTEM;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(heatpump)))) {
if (!strcmp(lowtopic, F_(heatpump))) {
return DeviceType::HEATPUMP;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(solar)))) {
if (!strcmp(lowtopic, F_(solar))) {
return DeviceType::SOLAR;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(mixer)))) {
if (!strcmp(lowtopic, F_(mixer))) {
return DeviceType::MIXER;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(dallassensor)))) {
if (!strcmp(lowtopic, F_(dallassensor))) {
return DeviceType::DALLASSENSOR;
}
if (!strcmp(lowtopic, reinterpret_cast<PGM_P>(F_(analogsensor)))) {
if (!strcmp(lowtopic, F_(analogsensor))) {
return DeviceType::ANALOGSENSOR;
}
@@ -264,9 +264,9 @@ void EMSdevice::list_device_entries(JsonObject & output) const {
// if we have a tag prefix it
char key[50];
if (!EMSdevice::tag_to_mqtt(dv.tag).empty()) {
snprintf(key, sizeof(key), "%s.%s", EMSdevice::tag_to_mqtt(dv.tag).c_str(), (dv.short_name));
snprintf(key, sizeof(key), "%s.%s", EMSdevice::tag_to_mqtt(dv.tag).c_str(), dv.short_name);
} else {
snprintf(key, sizeof(key), "%s", (dv.short_name));
snprintf(key, sizeof(key), "%s", dv.short_name);
}
JsonArray details = output.createNestedArray(key);
@@ -446,7 +446,7 @@ void EMSdevice::add_device_value(uint8_t tag,
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
for (EntityCustomization entityCustomization : settings.entityCustomizations) {
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
std::string entity = tag < DeviceValueTAG::TAG_HC1 ? (short_name) : tag_to_string(tag) + "/" + (short_name);
std::string entity = tag < DeviceValueTAG::TAG_HC1 ? short_name : tag_to_mqtt(tag) + "/" + short_name;
for (std::string entity_id : entityCustomization.entity_ids) {
// if there is an appended custom name, strip it to get the true entity name
// and extract the new custom name
@@ -637,14 +637,14 @@ void EMSdevice::publish_value(void * value_p) const {
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
if (Mqtt::publish_single2cmd()) {
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
snprintf(topic, sizeof(topic), "%s/%s/%s", device_type_2_device_name(device_type_), tag_to_mqtt(dv.tag).c_str(), (dv.short_name));
snprintf(topic, sizeof(topic), "%s/%s/%s", device_type_2_device_name(device_type_), tag_to_mqtt(dv.tag).c_str(), dv.short_name);
} else {
snprintf(topic, sizeof(topic), "%s/%s", device_type_2_device_name(device_type_), (dv.short_name));
}
} else if (Mqtt::is_nested() && dv.tag >= DeviceValueTAG::TAG_HC1) {
snprintf(topic, sizeof(topic), "%s/%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), tag_to_mqtt(dv.tag).c_str(), (dv.short_name));
snprintf(topic, sizeof(topic), "%s/%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), tag_to_mqtt(dv.tag).c_str(), dv.short_name);
} else {
snprintf(topic, sizeof(topic), "%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), (dv.short_name));
snprintf(topic, sizeof(topic), "%s/%s", Mqtt::tag_to_topic(device_type_, dv.tag).c_str(), dv.short_name);
}
int8_t num_op = dv.numeric_operator;
@@ -713,7 +713,7 @@ std::string EMSdevice::get_value_uom(const char * key) const {
char * key_p = new_key;
for (uint8_t i = 0; i < DeviceValue::tag_count; i++) {
auto tag = (DeviceValue::DeviceValueTAG_s[i]);
auto tag = Helpers::translated_word(DeviceValue::DeviceValueTAG_s[i]);
if (tag) {
std::string key2 = key; // copy string to a std::string so we can use the find function
uint8_t length = strlen(tag);
@@ -804,16 +804,16 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique
if ((dv.tag == DeviceValueTAG::TAG_NONE) || tag_to_string(dv.tag).empty()) {
obj["id"] = mask + dv.get_fullname();
obj["id"] = mask + fullname;
} else {
obj["id"] = mask + tag_to_string(dv.tag) + " " + dv.get_fullname();
obj["id"] = mask + tag_to_string(dv.tag) + " " + fullname;
}
// add commands and options
if (dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY)) {
// add the name of the Command function
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["c"] = tag_to_mqtt(dv.tag) + "/" + (dv.short_name);
obj["c"] = tag_to_mqtt(dv.tag) + "/" + dv.short_name;
} else {
obj["c"] = dv.short_name;
}
@@ -908,9 +908,9 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
// id holds the shortname and must always have a value for the WebUI table to work
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
obj["id"] = tag_to_string(dv.tag) + "/" + (dv.short_name);
obj["id"] = tag_to_mqtt(dv.tag) + "/" + dv.short_name;
} else {
obj["id"] = (dv.short_name);
obj["id"] = dv.short_name;
}
// n is the fullname, and can be optional
@@ -936,11 +936,6 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
obj["n"] = "!" + std::string(fullname); // prefix commands with a !
}
// add the custom name, is optional
if (!dv.custom_fullname.empty()) {
obj["cn"] = dv.custom_fullname;
}
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble
obj["w"] = dv.has_cmd; // if writable
@@ -976,7 +971,7 @@ void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint16_t max) {
// returns true if the entity has a mask set (not 0 the default)
void EMSdevice::setCustomEntity(const std::string & entity_id) {
for (auto & dv : devicevalues_) {
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? (dv.short_name) : tag_to_string(dv.tag) + "/" + (dv.short_name);
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? dv.short_name : tag_to_mqtt(dv.tag) + "/" + dv.short_name;
// extra shortname
std::string shortname;
@@ -1028,7 +1023,7 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
// populate a string vector with entities that have masks set or have a custom name
void EMSdevice::getCustomEntities(std::vector<std::string> & entity_ids) {
for (const auto & dv : devicevalues_) {
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? (dv.short_name) : tag_to_string(dv.tag) + "/" + (dv.short_name);
std::string entity_name = dv.tag < DeviceValueTAG::TAG_HC1 ? dv.short_name : tag_to_mqtt(dv.tag) + "/" + dv.short_name;
uint8_t mask = dv.state >> 4;
if (mask || !dv.custom_fullname.empty()) {
@@ -1293,7 +1288,7 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
if (dv.tag != old_tag) {
old_tag = dv.tag;
if (nested && have_tag && dv.tag >= DeviceValueTAG::TAG_HC1) {
json = output.createNestedObject(tag_to_string(dv.tag));
json = output.createNestedObject(tag_to_mqtt(dv.tag));
}
}
}
@@ -1473,14 +1468,14 @@ bool EMSdevice::has_telegram_id(uint16_t id) const {
std::string EMSdevice::telegram_type_name(std::shared_ptr<const Telegram> telegram) const {
// see if it's one of the common ones, like Version
if (telegram->type_id == EMS_TYPE_VERSION) {
return ("Version");
return "Version";
} else if (telegram->type_id == EMS_TYPE_UBADevices) {
return ("UBADevices");
return "UBADevices";
}
for (const auto & tf : telegram_functions_) {
if ((tf.telegram_type_id_ == telegram->type_id) && (telegram->type_id != 0xFF)) {
return (tf.telegram_type_name_);
return tf.telegram_type_name_;
}
}
@@ -1495,7 +1490,7 @@ bool EMSdevice::handle_telegram(std::shared_ptr<const Telegram> telegram) {
// if the data block is empty and we have not received data before, assume that this telegram
// is not recognized by the bus master. So remove it from the automatic fetch list
if (telegram->message_length == 0 && telegram->offset == 0 && !tf.received_) {
EMSESP::logger().debug(("This telegram (%s) is not recognized by the EMS bus"), (tf.telegram_type_name_));
EMSESP::logger().debug("This telegram (%s) is not recognized by the EMS bus", tf.telegram_type_name_);
tf.fetch_ = false;
return false;
}

View File

@@ -129,99 +129,99 @@ const char * DeviceValue::DeviceValueUOM_s[] = {
// mapping of TAGs, to match order in DeviceValueTAG enum in emsdevice.h
// must be an int of 4 bytes, 32bit aligned
const char * const DeviceValue::DeviceValueTAG_s[] = {
const char * const * DeviceValue::DeviceValueTAG_s[] = {
F_(tag_none), // ""
F_(tag_heartbeat), // ""
F_(tag_boiler_data_ww), // "dhw"
F_(tag_device_data), // ""
F_(tag_device_data_ww), // "dhw"
F_(tag_hc1), // "hc1"
F_(tag_hc2), // "hc2"
F_(tag_hc3), // "hc3"
F_(tag_hc4), // "hc4"
F_(tag_hc5), // "hc5"
F_(tag_hc6), // "hc6"
F_(tag_hc7), // "hc7"
F_(tag_hc8), // "hc8"
F_(tag_wwc1), // "wwc1"
F_(tag_wwc2), // "Wwc2"
F_(tag_wwc3), // "wwc3"
F_(tag_wwc4), // "wwc4"
F_(tag_wwc5), // "wwc5"
F_(tag_wwc6), // "wwc6"
F_(tag_wwc7), // "wwc7"
F_(tag_wwc8), // "wwc8"
F_(tag_wwc9), // "wwc9"
F_(tag_wwc10), // "wwc10"
F_(tag_ahs), // "ahs"
F_(tag_hs1), // "hs1"
F_(tag_hs2), // "hs2"
F_(tag_hs3), // "hs3"
F_(tag_hs4), // "hs4"
F_(tag_hs5), // "hs5"
F_(tag_hs6), // "hs6"
F_(tag_hs7), // "hs7"
F_(tag_hs8), // "hs8"
F_(tag_hs9), // "hs9"
F_(tag_hs10), // "hs10"
F_(tag_hs11), // "hs11"
F_(tag_hs12), // "hs12"
F_(tag_hs13), // "hs13"
F_(tag_hs14), // "hs14"
F_(tag_hs15), // "hs15"
F_(tag_hs16) // "hs16"
FL_(tag_none), // ""
FL_(tag_heartbeat), // ""
FL_(tag_boiler_data_ww), // "dhw"
FL_(tag_device_data), // ""
FL_(tag_device_data_ww), // "dhw"
FL_(tag_hc1), // "hc1"
FL_(tag_hc2), // "hc2"
FL_(tag_hc3), // "hc3"
FL_(tag_hc4), // "hc4"
FL_(tag_hc5), // "hc5"
FL_(tag_hc6), // "hc6"
FL_(tag_hc7), // "hc7"
FL_(tag_hc8), // "hc8"
FL_(tag_wwc1), // "wwc1"
FL_(tag_wwc2), // "Wwc2"
FL_(tag_wwc3), // "wwc3"
FL_(tag_wwc4), // "wwc4"
FL_(tag_wwc5), // "wwc5"
FL_(tag_wwc6), // "wwc6"
FL_(tag_wwc7), // "wwc7"
FL_(tag_wwc8), // "wwc8"
FL_(tag_wwc9), // "wwc9"
FL_(tag_wwc10), // "wwc10"
FL_(tag_ahs), // "ahs"
FL_(tag_hs1), // "hs1"
FL_(tag_hs2), // "hs2"
FL_(tag_hs3), // "hs3"
FL_(tag_hs4), // "hs4"
FL_(tag_hs5), // "hs5"
FL_(tag_hs6), // "hs6"
FL_(tag_hs7), // "hs7"
FL_(tag_hs8), // "hs8"
FL_(tag_hs9), // "hs9"
FL_(tag_hs10), // "hs10"
FL_(tag_hs11), // "hs11"
FL_(tag_hs12), // "hs12"
FL_(tag_hs13), // "hs13"
FL_(tag_hs14), // "hs14"
FL_(tag_hs15), // "hs15"
FL_(tag_hs16) // "hs16"
};
// MQTT topics derived from tags
const char * const DeviceValue::DeviceValueTAG_mqtt[] = {
F_(tag_none), // ""
FL_(tag_none)[0], // ""
F_(heartbeat), // "heartbeat"
F_(tag_boiler_data_ww_mqtt), // "ww"
F_(tag_device_data), // ""
FL_(tag_device_data)[0], // ""
F_(tag_device_data_ww_mqtt), // ""
F_(tag_hc1), // "hc1"
F_(tag_hc2), // "hc2"
F_(tag_hc3), // "hc3"
F_(tag_hc4), // "hc4"
F_(tag_hc5), // "hc5"
F_(tag_hc6), // "hc6"
F_(tag_hc7), // "hc7"
F_(tag_hc8), // "hc8"
F_(tag_wwc1), // "wwc1"
F_(tag_wwc2), // "Wwc2"
F_(tag_wwc3), // "wwc3"
F_(tag_wwc4), // "wwc4"
F_(tag_wwc5), // "wwc5"
F_(tag_wwc6), // "wwc6"
F_(tag_wwc7), // "wwc7"
F_(tag_wwc8), // "wwc8"
F_(tag_wwc9), // "wwc9"
F_(tag_wwc10), // "wwc10"
F_(tag_ahs), // "ahs"
F_(tag_hs1), // "hs1"
F_(tag_hs2), // "hs2"
F_(tag_hs3), // "hs3"
F_(tag_hs4), // "hs4"
F_(tag_hs5), // "hs5"
F_(tag_hs6), // "hs6"
F_(tag_hs7), // "hs7"
F_(tag_hs8), // "hs8"
F_(tag_hs9), // "hs9"
F_(tag_hs10), // "hs10"
F_(tag_hs11), // "hs11"
F_(tag_hs12), // "hs12"
F_(tag_hs13), // "hs13"
F_(tag_hs14), // "hs14"
F_(tag_hs15), // "hs15"
F_(tag_hs16) // "hs16"
FL_(tag_hc1)[0], // "hc1"
FL_(tag_hc2)[0], // "hc2"
FL_(tag_hc3)[0], // "hc3"
FL_(tag_hc4)[0], // "hc4"
FL_(tag_hc5)[0], // "hc5"
FL_(tag_hc6)[0], // "hc6"
FL_(tag_hc7)[0], // "hc7"
FL_(tag_hc8)[0], // "hc8"
FL_(tag_wwc1)[0], // "wwc1"
FL_(tag_wwc2)[0], // "Wwc2"
FL_(tag_wwc3)[0], // "wwc3"
FL_(tag_wwc4)[0], // "wwc4"
FL_(tag_wwc5)[0], // "wwc5"
FL_(tag_wwc6)[0], // "wwc6"
FL_(tag_wwc7)[0], // "wwc7"
FL_(tag_wwc8)[0], // "wwc8"
FL_(tag_wwc9)[0], // "wwc9"
FL_(tag_wwc10)[0], // "wwc10"
FL_(tag_ahs)[0], // "ahs"
FL_(tag_hs1)[0], // "hs1"
FL_(tag_hs2)[0], // "hs2"
FL_(tag_hs3)[0], // "hs3"
FL_(tag_hs4)[0], // "hs4"
FL_(tag_hs5)[0], // "hs5"
FL_(tag_hs6)[0], // "hs6"
FL_(tag_hs7)[0], // "hs7"
FL_(tag_hs8)[0], // "hs8"
FL_(tag_hs9)[0], // "hs9"
FL_(tag_hs10)[0], // "hs10"
FL_(tag_hs11)[0], // "hs11"
FL_(tag_hs12)[0], // "hs12"
FL_(tag_hs13)[0], // "hs13"
FL_(tag_hs14)[0], // "hs14"
FL_(tag_hs15)[0], // "hs15"
FL_(tag_hs16)[0] // "hs16"
};
// count #tags once at compile time
size_t DeviceValue::tag_count = sizeof(DeviceValue::DeviceValueTAG_s) / sizeof(char *);
size_t DeviceValue::tag_count = sizeof(DeviceValue::DeviceValueTAG_s) / sizeof(char * const *);
// checks whether the device value has an actual value
// returns true if its valid

View File

@@ -198,10 +198,10 @@ class DeviceValue {
return state;
}
static const char * DeviceValueUOM_s[];
static const char * const DeviceValueTAG_s[];
static const char * const DeviceValueTAG_mqtt[];
static size_t tag_count; // # tags
static const char * DeviceValueUOM_s[];
static const char * const * DeviceValueTAG_s[];
static const char * const DeviceValueTAG_mqtt[];
static size_t tag_count; // # tags
};
}; // namespace emsesp

View File

@@ -249,14 +249,14 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
if (bus_status() != BUS_STATUS_OFFLINE) {
shell.printfln("EMS Bus info:");
EMSESP::webSettingsService.read([&](WebSettings & settings) { shell.printfln(" Tx mode: %d", settings.tx_mode); });
shell.printfln(" Bus protocol: %s", EMSbus::is_ht3() ? ("HT3") : ("Buderus"));
shell.printfln(" Bus protocol: %s", EMSbus::is_ht3() ? "HT3" : "Buderus");
shell.printfln(" #recognized EMS devices: %d", EMSESP::emsdevices.size());
shell.printfln(" #telegrams received: %d", rxservice_.telegram_count());
shell.printfln(" #read requests sent: %d", txservice_.telegram_read_count());
shell.printfln(" #write requests sent: %d", txservice_.telegram_write_count());
shell.printfln(" #incomplete telegrams: %d", rxservice_.telegram_error_count());
shell.printfln((" #read fails (after %d retries): %d"), TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_read_fail_count());
shell.printfln((" #write fails (after %d retries): %d"), TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_write_fail_count());
shell.printfln(" #read fails (after %d retries): %d", TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_read_fail_count());
shell.printfln(" #write fails (after %d retries): %d", TxService::MAXIMUM_TX_RETRIES, txservice_.telegram_write_fail_count());
shell.printfln(" Rx line quality: %d%%", rxservice_.quality());
shell.printfln(" Tx line quality: %d%%", (txservice_.read_quality() + txservice_.read_quality()) / 2);
shell.println();
@@ -267,7 +267,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
if (rx_telegrams.empty()) {
shell.printfln("Rx Queue is empty");
} else {
shell.printfln(("Rx Queue (%ld telegram%s):"), rx_telegrams.size(), rx_telegrams.size() == 1 ? "" : "s");
shell.printfln("Rx Queue (%ld telegram%s):", rx_telegrams.size(), rx_telegrams.size() == 1 ? "" : "s");
for (const auto & it : rx_telegrams) {
shell.printfln(" [%02d] %s", it.id_, pretty_telegram(it.telegram_).c_str());
}
@@ -280,7 +280,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
if (tx_telegrams.empty()) {
shell.printfln("Tx Queue is empty");
} else {
shell.printfln(("Tx Queue (%ld telegram%s):"), tx_telegrams.size(), tx_telegrams.size() == 1 ? "" : "s");
shell.printfln("Tx Queue (%ld telegram%s):", tx_telegrams.size(), tx_telegrams.size() == 1 ? "" : "s");
std::string op;
for (const auto & it : tx_telegrams) {
@@ -311,7 +311,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
// print header
shell.printfln(("%s: %s (%d)"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str(), emsdevice->count_entities());
shell.printfln("%s: %s (%d)", emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str(), emsdevice->count_entities());
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XXLARGE_DYN); // use max size
JsonObject json = doc.to<JsonObject>();
@@ -325,17 +325,7 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
shell.printf(" %s: ", key);
JsonVariant data = p.value();
shell.print(COLOR_BRIGHT_GREEN);
if (data.is<const char *>()) {
shell.print(data.as<const char *>());
} else if (data.is<int>()) {
shell.print(data.as<int>());
} else if (data.is<float>()) {
char s[10];
shell.print(Helpers::render_value(s, data.as<float>(), 1));
} else if (data.is<bool>()) {
shell.print(data.as<bool>() ? Helpers::translated_word(FL_(on)) : Helpers::translated_word(FL_(off)));
}
shell.print(data.as<std::string>());
// if there is a uom print it
std::string uom = emsdevice->get_value_uom(key);
if (uom == "°C" && EMSESP::system_.fahrenheit()) {
@@ -366,7 +356,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
for (const auto & sensor : dallassensor_.sensors()) {
if (Helpers::hasValue(sensor.temperature_c)) {
shell.printfln((" %s: %s%s °%c%s (offset %s, ID: %s)"),
shell.printfln(" %s: %s%s °%c%s (offset %s, ID: %s)",
sensor.name().c_str(),
COLOR_BRIGHT_GREEN,
Helpers::render_value(s, sensor.temperature_c, 10, fahrenheit),
@@ -375,7 +365,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
Helpers::render_value(s2, sensor.offset(), 10, fahrenheit),
sensor.id().c_str());
} else {
shell.printfln((" %s (offset %s, ID: %s)"), sensor.name().c_str(), Helpers::render_value(s, sensor.offset(), 10, fahrenheit), sensor.id().c_str());
shell.printfln(" %s (offset %s, ID: %s)", sensor.name().c_str(), Helpers::render_value(s, sensor.offset(), 10, fahrenheit), sensor.id().c_str());
}
}
shell.println();
@@ -388,7 +378,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
for (const auto & sensor : analogsensor_.sensors()) {
switch (sensor.type()) {
case AnalogSensor::AnalogType::ADC:
shell.printfln((" %s: %s%s %s%s (Type: ADC, Factor: %s, Offset: %d)"),
shell.printfln(" %s: %s%s %s%s (Type: ADC, Factor: %s, Offset: %d)",
sensor.name().c_str(),
COLOR_BRIGHT_GREEN,
Helpers::render_value(s, sensor.value(), 2),
@@ -400,7 +390,7 @@ void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
default:
// case AnalogSensor::AnalogType::DIGITAL_IN:
// case AnalogSensor::AnalogType::COUNTER:
shell.printfln((" %s: %s%d%s (Type: %s)"),
shell.printfln(" %s: %s%d%s (Type: %s)",
sensor.name().c_str(),
COLOR_BRIGHT_GREEN,
(uint16_t)sensor.value(), // as int
@@ -523,7 +513,7 @@ void EMSESP::publish_device_values(uint8_t device_type) {
for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) {
if (nested && !nest_created && emsdevice->has_tag(tag)) {
json_hc = doc.createNestedObject(EMSdevice::tag_to_string(tag));
json_hc = doc.createNestedObject(EMSdevice::tag_to_mqtt(tag));
nest_created = true;
}
need_publish |= emsdevice->generate_values(json_hc, tag, false, EMSdevice::OUTPUT_TARGET::MQTT);
@@ -858,7 +848,7 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
}
if (!found) {
LOG_DEBUG(("No telegram type handler found for ID 0x%02X (src 0x%02X)"), telegram->type_id, telegram->src);
LOG_DEBUG("No telegram type handler found for ID 0x%02X (src 0x%02X)", telegram->type_id, telegram->src);
if (watch() == WATCH_UNKNOWN) {
LOG_NOTICE("%s", pretty_telegram(telegram).c_str());
}
@@ -973,7 +963,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
// if we don't recognize the productID report it and add as a generic device
if (device_p == nullptr) {
LOG_NOTICE(("Unrecognized EMS device (deviceID 0x%02X, productID %d). Please report on GitHub."), device_id, product_id);
LOG_NOTICE("Unrecognized EMS device (deviceID 0x%02X, productID %d). Please report on GitHub.", device_id, product_id);
emsdevices.push_back(
EMSFactory::add(DeviceType::GENERIC, device_id, product_id, version, "unknown", DeviceFlags::EMS_DEVICE_FLAG_NONE, EMSdevice::Brand::NO_BRAND));
return false; // not found
@@ -1020,12 +1010,12 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
LOG_WARNING("Unknown EMS boiler. Using generic profile. Please report on GitHub.");
} else {
LOG_WARNING(("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub."), device_id);
LOG_WARNING("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub.", device_id);
return false;
}
}
LOG_DEBUG(("Adding new device %s (deviceID 0x%02X, productID %d, version %s)"), name, device_id, product_id, version);
LOG_DEBUG("Adding new device %s (deviceID 0x%02X, productID %d, version %s)", name, device_id, product_id, version);
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, name, flags, brand));
// assign a unique ID. Note that this is not actual unique after a restart as it's dependent on the order that devices are found
@@ -1055,7 +1045,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
FL_(info_cmd));
Command::add(
device_type,
("values"),
F_(values),
[device_type](const char * value, const int8_t id, JsonObject & output) {
return command_info(device_type, output, id, EMSdevice::OUTPUT_TARGET::API_SHORTNAMES); // HIDDEN command showing short names, used in e.g. /api/boiler
},
@@ -1125,7 +1115,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t
for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)) {
if (!nest_created && emsdevice->has_tag(tag)) {
output_hc = output.createNestedObject(EMSdevice::tag_to_string(tag));
output_hc = output.createNestedObject(EMSdevice::tag_to_mqtt(tag));
nest_created = true;
}
has_value |= emsdevice->generate_values(output_hc, tag, true, output_target); // use nested for id -1 and 0
@@ -1324,7 +1314,7 @@ void EMSESP::start() {
device_library_ = {
#include "device_library.h"
};
LOG_INFO(("Loaded EMS device library (%d records)"), device_library_.size());
LOG_INFO("Loaded EMS device library (%d records)", device_library_.size());
#if defined(EMSESP_STANDALONE)
Mqtt::on_connect(); // simulate an MQTT connection

View File

@@ -159,7 +159,6 @@ MAKE_PSTR_LIST(rc20, "rc20")
MAKE_PSTR_LIST(fb10, "fb10")
MAKE_PSTR_LIST(fb100, "fb100")
MAKE_PSTR_LIST(dash, "-")
MAKE_PSTR_LIST(error, "error")
MAKE_PSTR_LIST(BLANK, "")
MAKE_PSTR_LIST(pwm, "pwm")
MAKE_PSTR_LIST(pwm_invers, "pwm inverse")
@@ -219,50 +218,6 @@ MAKE_PSTR(uom_sqm, "sqm")
MAKE_PSTR(uom_m3, "m3")
MAKE_PSTR(uom_l, "l")
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
// use empty string if want to suppress showing tags
// mqtt tags must not have spaces
MAKE_PSTR(tag_none, "")
MAKE_PSTR(tag_heartbeat, "")
MAKE_PSTR(tag_boiler_data_ww, "dhw")
MAKE_PSTR(tag_device_data, "")
MAKE_PSTR(tag_device_data_ww, "dhw")
MAKE_PSTR(tag_hc1, "hc1")
MAKE_PSTR(tag_hc2, "hc2")
MAKE_PSTR(tag_hc3, "hc3")
MAKE_PSTR(tag_hc4, "hc4")
MAKE_PSTR(tag_hc5, "hc5")
MAKE_PSTR(tag_hc6, "hc6")
MAKE_PSTR(tag_hc7, "hc7")
MAKE_PSTR(tag_hc8, "hc8")
MAKE_PSTR(tag_wwc1, "wwc1")
MAKE_PSTR(tag_wwc2, "wwc2")
MAKE_PSTR(tag_wwc3, "wwc3")
MAKE_PSTR(tag_wwc4, "wwc4")
MAKE_PSTR(tag_wwc5, "wwc5")
MAKE_PSTR(tag_wwc6, "wwc6")
MAKE_PSTR(tag_wwc7, "wwc7")
MAKE_PSTR(tag_wwc8, "wwc8")
MAKE_PSTR(tag_wwc9, "wwc9")
MAKE_PSTR(tag_wwc10, "wwc10")
MAKE_PSTR(tag_ahs, "ahs")
MAKE_PSTR(tag_hs1, "hs1")
MAKE_PSTR(tag_hs2, "hs2")
MAKE_PSTR(tag_hs3, "hs3")
MAKE_PSTR(tag_hs4, "hs4")
MAKE_PSTR(tag_hs5, "hs5")
MAKE_PSTR(tag_hs6, "hs6")
MAKE_PSTR(tag_hs7, "hs7")
MAKE_PSTR(tag_hs8, "hs8")
MAKE_PSTR(tag_hs9, "hs9")
MAKE_PSTR(tag_hs10, "hs10")
MAKE_PSTR(tag_hs11, "hs11")
MAKE_PSTR(tag_hs12, "hs12")
MAKE_PSTR(tag_hs13, "hs13")
MAKE_PSTR(tag_hs14, "hs14")
MAKE_PSTR(tag_hs15, "hs15")
MAKE_PSTR(tag_hs16, "hs16")
// MQTT topics and prefixes
MAKE_PSTR(heating_active, "heating_active")
MAKE_PSTR(tapwater_active, "tapwater_active")
@@ -295,6 +250,7 @@ MAKE_PSTR_ENUM(enum_freq, FL_(off), FL_(1x3min), FL_(2x3min), FL_(3x3min), FL_(4
MAKE_PSTR_ENUM(enum_off_time_date_manual, FL_(off), FL_(time), FL_(date), FL_(manual))
MAKE_PSTR_ENUM(enum_comfort, FL_(hot), FL_(eco), FL_(intelligent))
MAKE_PSTR_ENUM(enum_comfort1, FL_(high_comfort), FL_(eco))
MAKE_PSTR_ENUM(enum_comfort2, FL_(eco), FL_(high_comfort))
MAKE_PSTR_ENUM(enum_flow, FL_(off), FL_(flow), FL_(bufferedflow), FL_(buffer), FL_(layeredbuffer))
MAKE_PSTR_ENUM(enum_reset, FL_(dash), FL_(maintenance), FL_(error))
MAKE_PSTR_ENUM(enum_maxHeat, FL_(0kW), FL_(2kW), FL_(3kW), FL_(4kW), FL_(6kW), FL_(9kW))
@@ -334,7 +290,7 @@ MAKE_PSTR_ENUM(enum_nofrostmode, FL_(off), FL_(room), FL_(outdoor))
MAKE_PSTR_ENUM(enum_nofrostmode1, FL_(room), FL_(outdoor), FL_(room_outdoor))
MAKE_PSTR_ENUM(enum_controlmode, FL_(off), FL_(optimized), FL_(simple), FL_(mpc), FL_(room), FL_(power), FL_(constant))
MAKE_PSTR_ENUM(enum_controlmode1, FL_(weather_compensated), FL_(outside_basepoint), FL_(na), FL_(room)) // RC310 1-4
MAKE_PSTR_ENUM(enum_controlmode1, FL_(weather_compensated), FL_(outside_basepoint), FL_(na), FL_(room), FL_(power), FL_(constant)) // RC310 1-4
MAKE_PSTR_ENUM(enum_controlmode2, FL_(outdoor), FL_(room))
MAKE_PSTR_ENUM(enum_control, FL_(off), FL_(rc20), FL_(rc3x))
MAKE_PSTR_ENUM(enum_j_control, FL_(off), FL_(fb10), FL_(fb100))
@@ -346,6 +302,8 @@ MAKE_PSTR_ENUM(enum_dayOfWeek, FL_(day_mo), FL_(day_tu), FL_(day_we), FL_(day_th
MAKE_PSTR_ENUM(enum_progMode2, FL_(own_1), FL_(family), FL_(morning), FL_(evening), FL_(am), FL_(pm), FL_(midday), FL_(singles), FL_(seniors), FL_(new), FL_(own_2))
MAKE_PSTR_ENUM(enum_progMode3, FL_(family), FL_(morning), FL_(evening), FL_(am), FL_(pm), FL_(midday), FL_(singles), FL_(seniors))
MAKE_PSTR_ENUM(enum_hybridStrategy, FL_(co2_optimized), FL_(cost_optimized), FL_(outside_temp_switched), FL_(co2_cost_mix))
MAKE_PSTR_ENUM(enum_hybridStrategy1, FL_(cost_optimized), FL_(co2_optimized), FL_(outside_temp_alt), FL_(outside_temp_par), FL_(hp_prefered), FL_(boiler_only))
MAKE_PSTR_ENUM(enum_lowNoiseMode, FL_(off), FL_(reduced_output), FL_(switchoff), FL_(perm))
// heat pump
MAKE_PSTR_ENUM(enum_hpactivity, FL_(none), FL_(heating), FL_(cooling), FL_(hot_water), FL_(pool))

View File

@@ -32,22 +32,66 @@
// if there is no translation, it will default to en
// commands
MAKE_PSTR_LIST(info_cmd, "lists all values")
MAKE_PSTR_LIST(commands_cmd, "lists all commands")
MAKE_PSTR_LIST(entities_cmd, "lists all entities")
MAKE_PSTR_LIST(send_cmd, "send a telegram")
MAKE_PSTR_LIST(setiovalue_cmd, "set io value")
MAKE_PSTR_LIST(changeloglevel_cmd, "change log level")
MAKE_PSTR_LIST(fetch_cmd, "refresh all EMS values")
MAKE_PSTR_LIST(restart_cmd, "restart EMS-ESP")
MAKE_PSTR_LIST(watch_cmd, "watch incoming telegrams")
MAKE_PSTR_LIST(publish_cmd, "publish all to MQTT")
MAKE_PSTR_LIST(system_info_cmd, "show system status")
MAKE_PSTR_LIST(info_cmd, "lists all values", "Liste aller Werte")
MAKE_PSTR_LIST(commands_cmd, "lists all commands", "Liste aller Kommandos")
MAKE_PSTR_LIST(entities_cmd, "lists all entities", "Liste aller Entitäten")
MAKE_PSTR_LIST(send_cmd, "send a telegram", "Sende EMS-Telegramm")
MAKE_PSTR_LIST(setiovalue_cmd, "set io value", "Setze Wertevorgabe")
MAKE_PSTR_LIST(changeloglevel_cmd, "change log level", "Ändere Sysloglevel")
MAKE_PSTR_LIST(fetch_cmd, "refresh all EMS values", "Lese alle EMS-Werte neu")
MAKE_PSTR_LIST(restart_cmd, "restart EMS-ESP", "Neustart")
MAKE_PSTR_LIST(watch_cmd, "watch incoming telegrams", "Watch auf eingehende Telegramme")
MAKE_PSTR_LIST(publish_cmd, "publish all to MQTT", "Publiziere MQTT")
MAKE_PSTR_LIST(system_info_cmd, "show system status", "Zeige System-Status")
#if defined(EMSESP_DEBUG)
MAKE_PSTR_LIST(test_cmd, "run a test")
#endif
// TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp
// use empty string if want to suppress showing tags
// mqtt tags must not have spaces
MAKE_PSTR_LIST(tag_none, "")
MAKE_PSTR_LIST(tag_heartbeat, "")
MAKE_PSTR_LIST(tag_boiler_data_ww, "dhw", "WW")
MAKE_PSTR_LIST(tag_device_data, "")
MAKE_PSTR_LIST(tag_device_data_ww, "dhw", "WW")
MAKE_PSTR_LIST(tag_hc1, "hc1", "HK1")
MAKE_PSTR_LIST(tag_hc2, "hc2", "HK2")
MAKE_PSTR_LIST(tag_hc3, "hc3", "HK3")
MAKE_PSTR_LIST(tag_hc4, "hc4", "HK4")
MAKE_PSTR_LIST(tag_hc5, "hc5", "HK5")
MAKE_PSTR_LIST(tag_hc6, "hc6", "HK6")
MAKE_PSTR_LIST(tag_hc7, "hc7", "HK7")
MAKE_PSTR_LIST(tag_hc8, "hc8", "HK8")
MAKE_PSTR_LIST(tag_wwc1, "wwc1", "WWK1")
MAKE_PSTR_LIST(tag_wwc2, "wwc2", "WWK2")
MAKE_PSTR_LIST(tag_wwc3, "wwc3", "WWK3")
MAKE_PSTR_LIST(tag_wwc4, "wwc4", "WWK4")
MAKE_PSTR_LIST(tag_wwc5, "wwc5", "WWK5")
MAKE_PSTR_LIST(tag_wwc6, "wwc6", "WWK6")
MAKE_PSTR_LIST(tag_wwc7, "wwc7", "WWK7")
MAKE_PSTR_LIST(tag_wwc8, "wwc8", "WWK8")
MAKE_PSTR_LIST(tag_wwc9, "wwc9", "WWK9")
MAKE_PSTR_LIST(tag_wwc10, "wwc10", "WWK10")
MAKE_PSTR_LIST(tag_ahs, "ahs", "AHQ")
MAKE_PSTR_LIST(tag_hs1, "hs1")
MAKE_PSTR_LIST(tag_hs2, "hs2")
MAKE_PSTR_LIST(tag_hs3, "hs3")
MAKE_PSTR_LIST(tag_hs4, "hs4")
MAKE_PSTR_LIST(tag_hs5, "hs5")
MAKE_PSTR_LIST(tag_hs6, "hs6")
MAKE_PSTR_LIST(tag_hs7, "hs7")
MAKE_PSTR_LIST(tag_hs8, "hs8")
MAKE_PSTR_LIST(tag_hs9, "hs9")
MAKE_PSTR_LIST(tag_hs10, "hs10")
MAKE_PSTR_LIST(tag_hs11, "hs11")
MAKE_PSTR_LIST(tag_hs12, "hs12")
MAKE_PSTR_LIST(tag_hs13, "hs13")
MAKE_PSTR_LIST(tag_hs14, "hs14")
MAKE_PSTR_LIST(tag_hs15, "hs15")
MAKE_PSTR_LIST(tag_hs16, "hs16")
// General
MAKE_PSTR_LIST(on, "on", "an", "aan", "")
MAKE_PSTR_LIST(off, "off", "aus", "uit", "av")
@@ -96,6 +140,7 @@ MAKE_PSTR_LIST(blocking, "blocking", "Blockierung", "Blokkering", "Blockering")
MAKE_PSTR_LIST(extern, "extern", "extern", "extern", "extern")
MAKE_PSTR_LIST(intern, "intern", "intern", "intern", "intern")
MAKE_PSTR_LIST(lower, "lower", "niedirger", "lager", "lägre")
MAKE_PSTR_LIST(error, "error", "Fehler")
// boiler
MAKE_PSTR_LIST(time, "time", "Zeit", "Tijd", "Tid")
@@ -124,6 +169,13 @@ MAKE_PSTR_LIST(valve, "valve", "Ventil", "Klep", "Ventil")
MAKE_PSTR_LIST(none, "none", "keine", "geen", "ingen")
MAKE_PSTR_LIST(hot_water, "hot water", "Warmwasser", "warm water", "varmvatten")
MAKE_PSTR_LIST(pool, "pool", "Pool", "zwembad", "pool")
MAKE_PSTR_LIST(outside_temp_alt, "outside temperature alt.", "Außentemp. alternativ")
MAKE_PSTR_LIST(outside_temp_par, "outside temperature parallel", "Außentemp. parallel")
MAKE_PSTR_LIST(hp_prefered, "heatpump prefered", "Wärmepumpe bevorzugt")
MAKE_PSTR_LIST(boiler_only, "boiler only", "nur Kessel")
MAKE_PSTR_LIST(reduced_output, "reduced output", "Reduzierte Leistung")
MAKE_PSTR_LIST(switchoff, "switch off hp", "WP ausschalten")
MAKE_PSTR_LIST(perm, "perm. reduced", "perm. reduziert")
// thermostat
MAKE_PSTR_LIST(seltemp, "selTemp", "Solltemperatur", "Doeltemperatuur", "Börtemperatur")
@@ -193,7 +245,7 @@ MAKE_PSTR_LIST(cyl2, "cyl 2", "Zyl_2", "Cil 2", "Cyl 2")
// Entity translations
// Boiler
MAKE_PSTR_LIST(wwtapactivated, "wwtapactivated", "turn on/off", "Durchlauferhitzer aktiv", "zet aan/uit", "sätt på/av")
MAKE_PSTR_LIST(reset, "reset", "Reset", "Reset", "Nollställ", "reset")
MAKE_PSTR_LIST(reset, "reset", "Reset", "Reset", "Reset", "Nollställ")
MAKE_PSTR_LIST(oilPreHeat, "oilpreheat", "oil preheating", "Ölvorwärmung", "Olie voorverwarming", "Förvärmning olja")
MAKE_PSTR_LIST(heatingActive, "heatingactive", "heating active", "Heizen aktiv", "Verwarming actief", "Uppvärmning aktiv")
MAKE_PSTR_LIST(tapwaterActive, "tapwateractive", "tapwater active", "Warmwasser aktiv", "Warm water actief", "Varmvatten aktiv")
@@ -234,13 +286,13 @@ MAKE_PSTR_LIST(heatWorkMin, "heatworkmin", "total heat operating time", "Heizung
MAKE_PSTR_LIST(UBAuptime, "ubauptime", "total UBA operating time", "Anlagen-Gesamtlaufzeit", "totale looptijd branderautomaat (UBA)", "Total Tid")
MAKE_PSTR_LIST(lastCode, "lastcode", "last error code", "Letzter Fehler", "Laatste foutcode", "Senaste Felkod")
MAKE_PSTR_LIST(serviceCode, "servicecode", "service code", "Statusmeldung", "Statuscode", "Servicekod")
MAKE_PSTR_LIST(serviceCodeNumber, "servicecodenumber", "service code number", "Statusmeldungsnummer", "Status codenummer", "Servicekodsnummer")
MAKE_PSTR_LIST(serviceCodeNumber, "servicecodenumber", "service code number", "Statusmeldungsnummer", "Status codenummer", "Servicekod")
MAKE_PSTR_LIST(maintenanceMessage, "maintenancemessage", "maintenance message", "Wartungsmeldung", "Onderhoudsmelding", "Servicemeddelande")
MAKE_PSTR_LIST(maintenanceDate, "maintenancedate", "next maintenance date", "Wartungsdatum", "Onderhoudsdatum", "Datum nästa Service")
MAKE_PSTR_LIST(maintenanceType, "maintenance", "maintenance scheduled", "Wartungsplan", "Onderhoud gepland", "Underhåll schemlagt")
MAKE_PSTR_LIST(maintenanceTime, "maintenancetime", "time to next maintenance", "Wartung in", "Onderhoud in", "Tid till nästa underhåll")
MAKE_PSTR_LIST(emergencyOps, "emergencyops", "emergency operation", "Notoperation", "Noodoperatie", "Nöddrift")
MAKE_PSTR_LIST(emergencyTemp, "emergencytemp", "emergency temperature", "Nottemperatur", "Noodtemperatuur", "Nödtemperatur")
MAKE_PSTR_LIST(emergencyTemp, "emergencytemp", "emergency temperature", "Nottemperatur", "Noodtemperatuur", "Nöddrift temperatur")
// heatpump/compress specific
MAKE_PSTR_LIST(upTimeControl, "uptimecontrol", "total operating time heat", "Betriebszeit Heizen gesamt", "Totale bedrijfstijd", "Total tid uppvärmning")
@@ -276,8 +328,8 @@ MAKE_PSTR_LIST(hpPoolOn, "hppoolon", "hp pool", "WP Pool", "WP zwembadbedrijf",
MAKE_PSTR_LIST(hpBrinePumpSpd, "hpbrinepumpspd", "brine pump speed", "Solepumpen-Geschw.", "Snelheid pekelpomp", "Hastighet Brine-pump")
MAKE_PSTR_LIST(hpCompSpd, "hpcompspd", "compressor speed", "Kompressor-Geschw.", "Snelheid compressor", "Kompressorhastighet")
MAKE_PSTR_LIST(hpCircSpd, "hpcircspd", "circulation pump speed", "Zirkulationspumpen-Geschw.", "Snelheid circulatiepomp", "Hastighet Cirkulationspump")
MAKE_PSTR_LIST(hpBrineIn, "hpbrinein", "brine in/evaporator", "Sole in/Verdampfer", "pekel in/verdamper", "Brine in/förångare")
MAKE_PSTR_LIST(hpBrineOut, "hpbrineout", "brine out/condenser", "Sole aus/Kondensator", "pekel uit/condensor", "Brine ut/kondensor")
MAKE_PSTR_LIST(hpBrineIn, "hpbrinein", "brine in/evaporator", "Sole in/Verdampfer", "pekel in/verdamper", "Brine in (förångare)")
MAKE_PSTR_LIST(hpBrineOut, "hpbrineout", "brine out/condenser", "Sole aus/Kondensator", "pekel uit/condensor", "Brine ut (kondensor)")
MAKE_PSTR_LIST(hpSuctionGas, "hpsuctiongas", "suction gas", "Gasansaugung", "Gasaanzuiging", "Gasintag")
MAKE_PSTR_LIST(hpHotGas, "hphotgas", "hot gas/compressed", "Heißgas/verdichtet", "heet gas/samengeperst", "Hetgas/komprimerad")
MAKE_PSTR_LIST(hpSwitchValve, "hpswitchvalve", "switch valve", "Schaltventil", "schakelklep", "Växelventil")
@@ -316,6 +368,19 @@ MAKE_PSTR_LIST(fossileFactor, "fossilefactor", "fossile energy factor", "Energie
MAKE_PSTR_LIST(electricFactor, "electricfactor", "electric energy factor", "Energiefaktor elektrisch", "Energiefactor electrisch", "Elektrisk energifaktor")
MAKE_PSTR_LIST(delayBoiler, "delayboiler", "delay boiler support", "Verzögerungs-Option", "Vertragingsoptie", "Fördörjningsoption")
MAKE_PSTR_LIST(tempDiffBoiler, "tempdiffboiler", "temp diff boiler support", "Temperaturdifferenz-Option", "Verschiltemperatuuroptie", "Temperaturskillnadsoption")
MAKE_PSTR_LIST(lowNoiseMode, "lownoisemode", "low noise mode", "Geräuscharmer Betrieb")
MAKE_PSTR_LIST(lowNoiseStart, "lownoisestart", "low noise starttime", "Start geräuscharmer Betrieb")
MAKE_PSTR_LIST(lowNoiseStop, "lownoisestop", "low noise stoptime", "Stopp geräuscharmer Betrieb")
MAKE_PSTR_LIST(energyPriceGas, "energypricegas", "energy price gas", "Energiepreis Gas")
MAKE_PSTR_LIST(energyPriceEl, "energypriceel", "energy price electric", "Energiepreis Eletrizität")
MAKE_PSTR_LIST(energyPricePV, "energyfeedpv", "feed in PV", "PV Einspeisevergütung")
MAKE_PSTR_LIST(hybridDHW, "hybriddhw", "hybrid DHW", "Hybrid Warmwasser")
MAKE_PSTR_LIST(airPurgeMode, "airpurgemode", "air purge mode", "Luftspülung")
MAKE_PSTR_LIST(heatPumpOutput, "heatpumpoutput", "heatpump output", "WP Leistung")
MAKE_PSTR_LIST(coolingCircuit, "coolingcircuit", "cooling circuit", "Kühlkreislauf")
MAKE_PSTR_LIST(compStartMod, "compstartmod", "compressor start modulation", "Kompressor Startleistung")
MAKE_PSTR_LIST(heatDrainPan, "heatdrainpan", "heat drain pan", "Wärmeausgleichsgefäß")
MAKE_PSTR_LIST(heatCable, "heatcable", "heating cable", "Heizband")
// alternative heatsource AM200
MAKE_PSTR_LIST(aCylTopTemp, "cyltoptemp", "cylinder top temperature", "Speichertemperatur Oben", "Buffer temperatuur boven", "Cylindertemperatur Toppen")
@@ -398,7 +463,7 @@ MAKE_PSTR_LIST(switchtime2, "switchtime2", "own2 program switchtime", "Programm
MAKE_PSTR_LIST(wwswitchtime, "wwswitchtime", "program switchtime", "Programm Schaltzeit", "Warm water programma schakeltijd", "Varmvattenprogram Bytestid")
MAKE_PSTR_LIST(wwcircswitchtime, "wwcircswitchtime", "circulation program switchtime", "Zirculationsprogramm Schaltzeit", "Schakeltijd circulatieprogramma", "Cirkulationsprogram Bytestid")
MAKE_PSTR_LIST(dateTime, "datetime", "date/time", "Datum/Zeit", "Datum/Tijd", "Datum/Tid")
MAKE_PSTR_LIST(errorCode, "errorcode", "error code", "Fehlermeldung", "Foutmeldingscode", "Felkod")
MAKE_PSTR_LIST(errorCode, "errorcode", "error code", "Fehlernummer", "Foutmeldingscode", "Felkod")
MAKE_PSTR_LIST(ibaMainDisplay, "display", "display", "Anzeige", "Display", "Display")
MAKE_PSTR_LIST(ibaLanguage, "language", "language", "Sprache", "Taal", "Språk")
MAKE_PSTR_LIST(ibaClockOffset, "clockoffset", "clock offset", "Uhrkorrektur", "Klokcorrectie", "Tidskorrigering")
@@ -407,10 +472,10 @@ MAKE_PSTR_LIST(heatingPID, "heatingpid", "heating PID", "Heizungs-PID", "", "Upp
MAKE_PSTR_LIST(ibaCalIntTemperature, "intoffset", "internal temperature offset", "Korrektur interner Temperatur", "", "Korrigering interntemperatur")
MAKE_PSTR_LIST(ibaMinExtTemperature, "minexttemp", "minimal external temperature", "min. Aussentemperatur", "", "Min Extern Temperatur")
MAKE_PSTR_LIST(backlight, "backlight", "key backlight", "Gegenlicht", "Toetsverlichting", "Bakgrundsbelysning")
MAKE_PSTR_LIST(damping, "damping", "damping outdoor temperature", "Dämpfung der Außentemperatur", "Demping buitentemperatuur", "Dämpning Utomhustemperatur")
MAKE_PSTR_LIST(damping, "damping", "damping outdoor temperature", "Dämpfung der Außentemperatur", "Demping buitentemperatuur", "Utomhustemperatur dämpning")
MAKE_PSTR_LIST(tempsensor1, "inttemp1", "temperature sensor 1", "Temperatursensor 1", "Temperatuursensor 1", "Temperatursensor 1")
MAKE_PSTR_LIST(tempsensor2, "inttemp2", "temperature sensor 2", "Temperatursensor 2", "Temperatuursensor 2", "Temperatursensor 2")
MAKE_PSTR_LIST(dampedoutdoortemp, "dampedoutdoortemp", "damped outdoor temperature", "gedämpfte Außentemperatur", "Gedempte buitentemperatuur", "Dämpad Utomhustemperatur")
MAKE_PSTR_LIST(dampedoutdoortemp, "dampedoutdoortemp", "damped outdoor temperature", "gedämpfte Außentemperatur", "Gedempte buitentemperatuur", "Utomhustemperatur dämpad")
MAKE_PSTR_LIST(floordrystatus, "floordry", "floor drying", "Estrichtrocknung", "Vloerdroogprogramma", "Golvtorkning")
MAKE_PSTR_LIST(floordrytemp, "floordrytemp", "floor drying temperature", "Estrichtrocknungs Temperatur", "Temperatuur vloerdroogprogramma", "Golvtorkning Temperatur")
MAKE_PSTR_LIST(brightness, "brightness", "screen brightness", "Bildschirmhelligkeit", "Schermhelderheid", "Ljusstyrka")

View File

@@ -205,7 +205,7 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
return;
}
shell.printfln(("MQTT queue (%d/%d messages):"), mqtt_messages_.size(), MAX_MQTT_MESSAGES);
shell.printfln("MQTT queue (%d/%d messages):", mqtt_messages_.size(), MAX_MQTT_MESSAGES);
for (const auto & message : mqtt_messages_) {
auto content = message.content_;
@@ -222,12 +222,12 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
// Publish messages
if (message.retry_count_ == 0) {
if (message.packet_id_ == 0) {
shell.printfln((" [%02d] (Pub) topic=%s payload=%s"), message.id_, topic, content->payload.c_str());
shell.printfln(" [%02d] (Pub) topic=%s payload=%s", message.id_, topic, content->payload.c_str());
} else {
shell.printfln((" [%02d] (Pub) topic=%s payload=%s (pid %d)"), message.id_, topic, content->payload.c_str(), message.packet_id_);
shell.printfln(" [%02d] (Pub) topic=%s payload=%s (pid %d)", message.id_, topic, content->payload.c_str(), message.packet_id_);
}
} else {
shell.printfln((" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"),
shell.printfln(" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)",
message.id_,
topic,
content->payload.c_str(),
@@ -236,7 +236,7 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
}
} else {
// Subscribe messages
shell.printfln((" [%02d] (Sub) topic=%s"), message.id_, topic);
shell.printfln(" [%02d] (Sub) topic=%s", message.id_, topic);
}
}
shell.println();
@@ -264,7 +264,7 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) cons
#if defined(EMSESP_DEBUG)
if (len) {
LOG_DEBUG(("Received topic `%s` => payload `%s` (length %d)"), topic, message, len);
LOG_DEBUG("Received topic `%s` => payload `%s` (length %d)", topic, message, len);
} else {
LOG_DEBUG("Received topic `%s`", topic);
}
@@ -554,7 +554,7 @@ void Mqtt::on_connect() {
doc["version"] = EMSESP_APP_VERSION;
#ifndef EMSESP_STANDALONE
if (WiFi.status() == WL_CONNECTED) {
doc["connection"] = ("WiFi");
doc["connection"] = "WiFi";
doc["hostname"] = WiFi.getHostname();
doc["SSID"] = WiFi.SSID();
doc["BSSID"] = WiFi.BSSIDstr();
@@ -567,7 +567,7 @@ void Mqtt::on_connect() {
doc["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
}
} else if (EMSESP::system_.ethernet_connected()) {
doc["connection"] = ("Ethernet");
doc["connection"] = "Ethernet";
doc["hostname"] = ETH.getHostname();
doc["MAC"] = ETH.macAddress();
doc["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
@@ -609,7 +609,7 @@ void Mqtt::on_connect() {
LOG_INFO("Queue size: %d", mqtt_messages_.size());
for (const auto & message : mqtt_messages_) {
auto content = message.content_;
LOG_INFO((" [%02d] (%d) topic=%s payload=%s"), message.id_, content->operation, content->topic.c_str(), content->payload.c_str());
LOG_INFO(" [%02d] (%d) topic=%s payload=%s", message.id_, content->operation, content->topic.c_str(), content->payload.c_str());
}
*/
}
@@ -857,7 +857,7 @@ void Mqtt::process_queue() {
// else try and publish it
uint16_t packet_id = mqttClient_->publish(topic, mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_);
LOG_DEBUG(("Publishing topic %s (#%02d, retain=%d, retry=%d, size=%d, pid=%d)"),
LOG_DEBUG("Publishing topic %s (#%02d, retain=%d, retry=%d, size=%d, pid=%d)",
topic,
mqtt_message.id_,
message->retain,
@@ -978,9 +978,9 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice
// create entity by add the hc/wwc tag if present, separating with a .
char new_entity[50];
if (tag >= DeviceValueTAG::TAG_HC1) {
snprintf(new_entity, sizeof(new_entity), "%s.%s", EMSdevice::tag_to_string(tag).c_str(), (entity));
snprintf(new_entity, sizeof(new_entity), "%s.%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity);
} else {
snprintf(new_entity, sizeof(new_entity), "%s", (entity));
snprintf(new_entity, sizeof(new_entity), "%s", entity);
}
// build unique identifier which will be used in the topic, replacing all . with _ as not to break HA
@@ -1140,9 +1140,9 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice
// and has no unit of measure or icon
if (type == DeviceValueType::BOOL) {
char result[10];
doc[("payload_on")] = Helpers::render_boolean(result, true);
doc[("payload_off")] = Helpers::render_boolean(result, false);
doc[sc_ha] = F_(measurement);
doc["payload_on"] = Helpers::render_boolean(result, true);
doc["payload_off"] = Helpers::render_boolean(result, false);
doc[sc_ha] = F_(measurement);
} else {
// always set the uom
if (uom != DeviceValueUOM::NONE) {

View File

@@ -38,6 +38,10 @@
#include "../rom/rtc.h"
#endif
#endif
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels(1, 7, NEO_GRB + NEO_KHZ800);
#endif
namespace emsesp {
@@ -348,27 +352,24 @@ void System::wifi_tweak() {
#endif
}
#ifdef ARDUINO_LOLIN_C3_MINI
// https://www.wemos.cc/en/latest/c3/c3_mini.html
bool System::is_valid_gpio(uint8_t pin) {
if ((pin >= 11 && pin <= 19) || (pin > 21)) {
return false; // bad pin
}
return true;
}
#else
// check for valid ESP32 pins. This is very dependent on which ESP32 board is being used.
// Typically you can't use 1, 6-11, 12, 14, 15, 20, 24, 28-31 and 40+
// we allow 0 as it has a special function on the NodeMCU apparently
// See https://diyprojects.io/esp32-how-to-use-gpio-digital-io-arduino-code/#.YFpVEq9KhjG
// and https://nodemcu.readthedocs.io/en/dev-esp32/modules/gpio/
bool System::is_valid_gpio(uint8_t pin) {
#if CONFIG_IDF_TARGET_ESP32
if ((pin == 1) || (pin >= 6 && pin <= 12) || (pin >= 14 && pin <= 15) || (pin == 20) || (pin == 24) || (pin >= 28 && pin <= 31) || (pin > 40)) {
#elif CONFIG_IDF_TARGET_ESP32S2
if ((pin >= 19 && pin <= 20) || (pin >= 22 && pin <= 32) || (pin > 40)) {
#elif CONFIG_IDF_TARGET_ESP32C3
// https://www.wemos.cc/en/latest/c3/c3_mini.html
if ((pin >= 11 && pin <= 19) || (pin > 21)) {
#endif
return false; // bad pin
}
return true;
}
#endif
// Starts up the UART Serial bridge
void System::start() {
@@ -379,6 +380,7 @@ void System::start() {
setCpuFrequencyMhz(160);
}
fstotal_ = LittleFS.totalBytes() / 1024; // read only once, it takes 500 ms to read
psram_ = ESP.getPsramSize() / 1024;
appused_ = ESP.getSketchSize() / 1024;
appfree_ = ESP.getFreeSketchSpace() / 1024 - appused_;
#endif
@@ -457,8 +459,18 @@ void System::led_init(bool refresh) {
}
if ((led_gpio_ != 0) && is_valid_gpio(led_gpio_)) {
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
// rgb LED WS2812B, use Adafruit Neopixel
// Adafruit_NeoPixel pixels(1, 7, NEO_GRB + NEO_KHZ800);
pixels.begin();
pixels.setPin(led_gpio_);
// pixels.setBrightness(0);
// pixels.Color(0, 0, 0, 0);
// pixels.show();
#else
pinMode(led_gpio_, OUTPUT); // 0 means disabled
digitalWrite(led_gpio_, !LED_ON); // start with LED off
#endif
}
}
@@ -551,8 +563,9 @@ bool System::heartbeat_json(JsonObject & output) {
output["txfails"] = EMSESP::txservice_.telegram_read_fail_count() + EMSESP::txservice_.telegram_write_fail_count();
if (Mqtt::enabled()) {
output["mqttcount"] = Mqtt::publish_count();
output["mqttfails"] = Mqtt::publish_fails();
output["mqttcount"] = Mqtt::publish_count();
output["mqttfails"] = Mqtt::publish_fails();
output["mqttconnects"] = Mqtt::connect_count();
}
output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
output["apifails"] = WebAPIService::api_fails();
@@ -648,13 +661,23 @@ void System::system_check() {
if (healthcheck_ == 0) {
// everything is healthy, show LED permanently on or off depending on setting
if (led_gpio_) {
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
pixels.setPixelColor(0, 0, hide_led_ ? 0 : 128, 0);
pixels.show();
#else
digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON);
#endif
}
send_heartbeat();
} else {
// turn off LED so we're ready to the flashes
if (led_gpio_) {
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
pixels.setPixelColor(0, 0, 0, 0);
pixels.show();
#else
digitalWrite(led_gpio_, !LED_ON);
#endif
}
}
}
@@ -687,7 +710,7 @@ void System::commands_init() {
// uses LED to show system health
void System::led_monitor() {
// we only need to run the LED healthcheck if there are errors
if (!healthcheck_) {
if (!healthcheck_ || !led_gpio_) {
return; // all good
}
@@ -715,13 +738,36 @@ void System::led_monitor() {
// Serial.println("resetting flash check");
led_long_timer_ = uuid::get_uptime();
led_flash_step_ = 0;
digitalWrite(led_gpio_, !LED_ON); // LED off
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
pixels.setPixelColor(0, 0, 0, 0);
pixels.show();
#else
digitalWrite(led_gpio_, !LED_ON); // LED off
#endif
} else if (led_flash_step_ % 2) {
// handle the step events (on odd numbers 3,5,7,etc). see if we need to turn on a LED
// 1 flash is the EMS bus is not connected
// 2 flashes if the network (wifi or ethernet) is not connected
// 3 flashes is both the bus and the network are not connected. Then you know you're truly f*cked.
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
if (led_flash_step_ == 3) {
if ((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) {
pixels.setPixelColor(0, 128, 0, 0); // red
} else if ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS) {
pixels.setPixelColor(0, 0, 0, 128); // blue
}
}
if (led_flash_step_ == 5 && (healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) {
pixels.setPixelColor(0, 128, 0, 0); // red
}
if ((led_flash_step_ == 7) && ((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK)
&& ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS)) {
pixels.setPixelColor(0, 0, 0, 128); // blue
}
pixels.show();
#else
if ((led_flash_step_ == 3)
&& (((healthcheck_ & HEALTHCHECK_NO_NETWORK) == HEALTHCHECK_NO_NETWORK) || ((healthcheck_ & HEALTHCHECK_NO_BUS) == HEALTHCHECK_NO_BUS))) {
led_on_ = true;
@@ -736,13 +782,19 @@ void System::led_monitor() {
led_on_ = true;
}
if (led_on_ && led_gpio_) {
digitalWrite(led_gpio_, LED_ON);
if (led_on_) {
digitalWrite(led_gpio_, LED_ON); // LED off
}
#endif
} else {
// turn the led off after the flash, on even number count
if (led_on_ && led_gpio_) {
digitalWrite(led_gpio_, !LED_ON);
if (led_on_) {
#if defined(ARDUINO_LOLIN_C3_MINI) && !defined(BOARD_C3_MINI_V1)
pixels.setPixelColor(0, 0, 0, 0);
pixels.show();
#else
digitalWrite(led_gpio_, !LED_ON); // LED off
#endif
led_on_ = false;
}
}
@@ -811,7 +863,7 @@ void System::show_system(uuid::console::Shell & shell) {
shell.printfln(" Network: connected");
shell.printfln(" SSID: %s", WiFi.SSID().c_str());
shell.printfln(" BSSID: %s", WiFi.BSSIDstr().c_str());
shell.printfln((" RSSI: %d dBm (%d %%)"), WiFi.RSSI(), wifi_quality(WiFi.RSSI()));
shell.printfln(" RSSI: %d dBm (%d %%)", WiFi.RSSI(), wifi_quality(WiFi.RSSI()));
shell.printfln(" MAC address: %s", WiFi.macAddress().c_str());
shell.printfln(" Hostname: %s", WiFi.getHostname());
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str());
@@ -965,9 +1017,10 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
JsonObject node;
// System
node = output.createNestedObject("System Status");
node["version"] = EMSESP_APP_VERSION;
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
node = output.createNestedObject("System Status");
node["version"] = EMSESP_APP_VERSION;
node["platform"] = EMSESP_PLATFORM;
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
// node["uptime (seconds)"] = uuid::get_uptime_sec();
#ifndef EMSESP_STANDALONE
node["freemem"] = ESP.getFreeHeap() / 1024; // kilobytes
@@ -979,7 +1032,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
// Network Status
node = output.createNestedObject("Network Status");
if (WiFi.status() == WL_CONNECTED) {
node["connection"] = ("WiFi");
node["connection"] = "WiFi";
node["hostname"] = WiFi.getHostname();
// node["SSID"] = WiFi.SSID();
// node["BSSID"] = WiFi.BSSIDstr();
@@ -992,7 +1045,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
}
} else if (EMSESP::system_.ethernet_connected()) {
node["connection"] = ("Ethernet");
node["connection"] = "Ethernet";
node["hostname"] = ETH.getHostname();
node["MAC"] = ETH.macAddress();
node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
@@ -1048,7 +1101,9 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node["MQTT status"] = Mqtt::connected() ? F_(connected) : F_(disconnected);
if (Mqtt::enabled()) {
node["MQTT publishes"] = Mqtt::publish_count();
node["MQTT queued"] = Mqtt::publish_queued();
node["MQTT publish fails"] = Mqtt::publish_fails();
node["MQTT connects"] = Mqtt::connect_count();
}
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) {
node["enabled"] = settings.enabled;
@@ -1106,20 +1161,20 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node = output.createNestedObject("Bus Status");
switch (EMSESP::bus_status()) {
case EMSESP::BUS_STATUS_OFFLINE:
node["bus status"] = ("disconnected");
node["bus status"] = "disconnected";
break;
case EMSESP::BUS_STATUS_TX_ERRORS:
node["bus status"] = ("connected, tx issues - try a different Tx Mode");
node["bus status"] = "connected, tx issues - try a different Tx Mode";
break;
case EMSESP::BUS_STATUS_CONNECTED:
node["bus status"] = ("connected");
node["bus status"] = "connected";
break;
default:
node["bus status"] = ("unknown");
node["bus status"] = "unknown";
break;
}
if (EMSESP::bus_status() != EMSESP::BUS_STATUS_OFFLINE) {
node["bus protocol"] = EMSbus::is_ht3() ? ("HT3") : ("Buderus");
node["bus protocol"] = EMSbus::is_ht3() ? "HT3" : "Buderus";
node["bus telegrams received (rx)"] = EMSESP::rxservice_.telegram_count();
node["bus reads (tx)"] = EMSESP::txservice_.telegram_read_count();
node["bus writes (tx)"] = EMSESP::txservice_.telegram_write_count();
@@ -1230,7 +1285,9 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
} else if (board_profile == "OLIMEXPOE") {
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, 12, 0, 3}; // Olimex ESP32-POE
} else if (board_profile == "C3MINI") {
data = {7, 2, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini
data = {7, 1, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini
} else if (board_profile == "S2MINI") {
data = {15, 7, 11, 12, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; //Lolin S2 Mini
} else if (board_profile == "CUSTOM") {
// send back current values
data = {(int8_t)EMSESP::system_.led_gpio_,
@@ -1267,6 +1324,9 @@ bool System::command_restart(const char * value, const int8_t id) {
return true;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch"
std::string System::reset_reason(uint8_t cpu) const {
#ifndef EMSESP_STANDALONE
switch (rtc_get_reset_reason(cpu)) {
@@ -1275,11 +1335,11 @@ std::string System::reset_reason(uint8_t cpu) const {
// case 2 :reset pin not on esp32
case 3:
return ("Software reset");
case 4:
case 4: // not on S2, C3
return ("Legacy watch dog reset");
case 5:
return ("Deep sleep reset");
case 6:
case 6: // not on S2, C3
return ("Reset by SDIO");
case 7:
return ("Timer group0 watch dog reset");
@@ -1295,7 +1355,7 @@ std::string System::reset_reason(uint8_t cpu) const {
return ("Software reset CPU");
case 13:
return ("RTC watch dog reset: CPU");
case 14:
case 14: // not on S2, C3
return ("APP CPU reset by PRO CPU");
case 15:
return ("Brownout reset");
@@ -1307,11 +1367,12 @@ std::string System::reset_reason(uint8_t cpu) const {
#endif
return ("Unkonwn");
}
#pragma GCC diagnostic pop
// set NTP status
void System::ntp_connected(bool b) {
if (b != ntp_connected_) {
LOG_INFO(b ? ("NTP connected") : ("NTP disconnected"));
LOG_INFO(b ? "NTP connected" : "NTP disconnected");
}
ntp_connected_ = b;
ntp_last_check_ = b ? uuid::get_uptime_sec() : 0;

View File

@@ -29,8 +29,8 @@
#ifndef EMSESP_STANDALONE
#include <esp_wifi.h>
#ifndef ARDUINO_LOLIN_S2_MINI
#include <esp_bt.h>
#if CONFIG_IDF_TARGET_ESP32
// #include <esp_bt.h>
#endif
#include <ETH.h>
#include <uuid/syslog.h>
@@ -225,6 +225,9 @@ class System {
uint32_t FStotal() {
return fstotal_;
}
uint32_t PSram() {
return psram_;
}
uint32_t appFree() {
return appfree_;
}
@@ -307,6 +310,7 @@ class System {
uint8_t eth_clock_mode_;
uint32_t fstotal_;
uint32_t psram_;
uint32_t appused_;
uint32_t appfree_;
};

View File

@@ -120,7 +120,7 @@ std::string Telegram::to_string() const {
// returns telegram's message body only, in hex
std::string Telegram::to_string_message() const {
if (this->message_length == 0) {
return ("<empty>");
return "<empty>";
}
return Helpers::data_to_hex(this->message_data, this->message_length);
@@ -141,7 +141,7 @@ void RxService::loop() {
// length includes the CRC
// for EMS+ the type_id has the value + 256. We look for these type of telegrams with F7, F9 and FF in 3rd byte
void RxService::add(uint8_t * data, uint8_t length) {
if (length < 2) {
if (length < 5) {
return;
}
@@ -612,7 +612,7 @@ void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const ui
}
LOG_ERROR("Last Tx %s operation failed after %d retries. Ignoring request: %s",
(operation == Telegram::Operation::TX_WRITE) ? ("Write") : ("Read"),
(operation == Telegram::Operation::TX_WRITE) ? "Write" : "Read",
MAXIMUM_TX_RETRIES,
telegram_last_->to_string().c_str());

View File

@@ -82,9 +82,9 @@ void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
uart_param_config(EMSUART_NUM, &uart_config);
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
uart_set_rx_full_threshold(EMSUART_NUM, 1);
uart_set_rx_timeout(EMSUART_NUM, 0); // disable
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, configMAX_PRIORITIES - 1, NULL);

View File

@@ -26,12 +26,8 @@
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK
#if (defined(ARDUINO_LOLIN_C3_MINI)) || (defined(ARDUINO_LOLIN_S2_MINI))
#define EMSUART_NUM UART_NUM_1 // on C3 and S2 we're using UART1
#else
#define EMSUART_NUM UART_NUM_2 // on the ESP32 we're using UART2
#endif
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMSUART_NUM UART_NUM_1 // on C3 and S2 there is no UART2, use UART1 for all
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMS_TXMODE_DEFAULT 1
#define EMS_TXMODE_EMSPLUS 2

View File

@@ -1 +1,11 @@
#define EMSESP_APP_VERSION "3.5.0b6"
#define EMSESP_APP_VERSION "3.5.0b7"
#if CONFIG_IDF_TARGET_ESP32C3
#define EMSESP_PLATFORM "ESP32-C3";
#elif CONFIG_IDF_TARGET_ESP32S2
#define EMSESP_PLATFORM "ESP32-S2";
#elif CONFIG_IDF_TARGET_ESP32
#define EMSESP_PLATFORM "ESP32";
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif

View File

@@ -139,7 +139,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
int ret_codes[5] = {400, 200, 400, 400, 401};
response->setCode(ret_codes[return_code]);
response->setLength();
response->setContentType("application/json");
response->setContentType("application/json; charset=utf-8");
request->send(response);
api_count_++;

View File

@@ -62,7 +62,7 @@ WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securi
// scan devices service
void WebDataService::scan_devices(AsyncWebServerRequest * request) {
EMSESP::logger().info(F("Scanning devices..."));
EMSESP::logger().info("Scanning devices...");
EMSESP::scan_devices();
request->send(200);
}
@@ -236,7 +236,7 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant &
// write debug
if (return_code != CommandRet::OK) {
EMSESP::logger().err(("Write command failed %s (%s)"), (const char *)output["message"], Command::return_code_string(return_code).c_str());
EMSESP::logger().err("Write command failed %s (%s)", (const char *)output["message"], Command::return_code_string(return_code).c_str());
} else {
EMSESP::logger().debug("Write command successful");
}

View File

@@ -75,15 +75,18 @@ void WebSettings::read(WebSettings & settings, JsonObject & root) {
root["eth_power"] = settings.eth_power;
root["eth_phy_addr"] = settings.eth_phy_addr;
root["eth_clock_mode"] = settings.eth_clock_mode;
root["platform"] = EMSESP_PLATFORM;
}
// call on initialization and also when settings are updated via web or console
StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) {
// load default GPIO configuration based on board profile
std::vector<int8_t> data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
#ifdef ARDUINO_LOLIN_C3_MINI
settings.board_profile = "C3MINI";
#else
#if CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = root["board_profile"] | "C3MINI";
#elif CONFIG_IDF_TARGET_ESP32S2
settings.board_profile = root["board_profile"] | "S2MINI";
#elif CONFIG_IDF_TARGET_ESP32
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE;
#endif
if (!System::load_board_profile(data, settings.board_profile.c_str())) {