mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
fix thermostat dhw commands
This commit is contained in:
@@ -302,8 +302,19 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
auto dname = EMSdevice::device_type_2_device_name(device_type);
|
||||
uint8_t device_id = EMSESP::device_id_from_cmd(device_type, cmd, id);
|
||||
|
||||
uint8_t flag = 0;
|
||||
uint8_t tag = id - 1 + DeviceValueTAG::TAG_HC1;
|
||||
if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) {
|
||||
flag = CommandFlag::MQTT_SUB_FLAG_HC;
|
||||
} else if (tag >= DeviceValueTAG::TAG_DHW1 && tag <= DeviceValueTAG::TAG_DHW10) {
|
||||
flag = CommandFlag::MQTT_SUB_FLAG_DHW;
|
||||
} else if (tag >= DeviceValueTAG::TAG_HS1 && tag <= DeviceValueTAG::TAG_HS16) {
|
||||
flag = CommandFlag::MQTT_SUB_FLAG_HS;
|
||||
} else if (tag >= DeviceValueTAG::TAG_AHS1 && tag <= DeviceValueTAG::TAG_AHS1) {
|
||||
flag = CommandFlag::MQTT_SUB_FLAG_AHS;
|
||||
}
|
||||
// see if there is a command registered
|
||||
auto cf = find_command(device_type, device_id, cmd);
|
||||
auto cf = find_command(device_type, device_id, cmd, flag);
|
||||
|
||||
// check if its a call to an end-point of a device
|
||||
// this is used to fetch the attributes of the device entity, or call a command directly
|
||||
@@ -370,9 +381,9 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
// report back. If not OK show output from error, other return the HTTP code
|
||||
if (return_code != CommandRet::OK) {
|
||||
if ((value == nullptr) || (strlen(value) == 0)) {
|
||||
LOG_ERROR("Command '%s' failed with error code %d", cmd, return_code);
|
||||
LOG_ERROR("Command '%s' failed with error code %d", cmd, FL_(cmdRet)[return_code]);
|
||||
} else {
|
||||
LOG_ERROR("Command '%s/%s' failed with error code %d", cmd, value, return_code);
|
||||
LOG_ERROR("Command '%s/%s' failed with error code %c", cmd, value, return_code);
|
||||
}
|
||||
return message(return_code, "callback function failed", output);
|
||||
}
|
||||
@@ -382,7 +393,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
||||
// add a command to the list, which does not return json
|
||||
void Command::add(const uint8_t device_type, const uint8_t device_id, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
||||
// if the command already exists for that device type don't add it
|
||||
if (find_command(device_type, device_id, cmd) != nullptr) {
|
||||
if (find_command(device_type, device_id, cmd, flags) != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -403,7 +414,7 @@ void Command::add(const uint8_t device_type, const char * cmd, const cmd_functio
|
||||
// add a command to the list, which does return a json object as output
|
||||
void Command::add(const uint8_t device_type, const char * cmd, const cmd_json_function_p cb, const char * const * description, uint8_t flags) {
|
||||
// if the command already exists for that device type don't add it
|
||||
if (find_command(device_type, 0, cmd) != nullptr) {
|
||||
if (find_command(device_type, 0, cmd, flags) != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -412,13 +423,14 @@ void Command::add(const uint8_t device_type, const char * cmd, const cmd_json_fu
|
||||
|
||||
// see if a command exists for that device type
|
||||
// is not case sensitive
|
||||
Command::CmdFunction * Command::find_command(const uint8_t device_type, const uint8_t device_id, const char * cmd) {
|
||||
Command::CmdFunction * Command::find_command(const uint8_t device_type, const uint8_t device_id, const char * cmd, const uint8_t flag) {
|
||||
if ((cmd == nullptr) || (strlen(cmd) == 0) || (cmdfunctions_.empty())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto & cf : cmdfunctions_) {
|
||||
if (Helpers::toLower(cmd) == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && (!device_id || cf.device_id_ == device_id)) {
|
||||
if (Helpers::toLower(cmd) == Helpers::toLower(cf.cmd_) && (cf.device_type_ == device_type) && (!device_id || cf.device_id_ == device_id)
|
||||
&& (!(flag & 0x3F) || (flag & 0x3F) == (cf.flags_ & 0x3F))) {
|
||||
return &cf;
|
||||
}
|
||||
}
|
||||
@@ -536,6 +548,12 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
|
||||
} else if (cf.has_flags(MQTT_SUB_FLAG_DHW)) {
|
||||
shell.print("[dhw<n>.]");
|
||||
i += 9;
|
||||
} else if (cf.has_flags(MQTT_SUB_FLAG_AHS)) {
|
||||
shell.print("[ahs<n>.]");
|
||||
i += 9;
|
||||
} else if (cf.has_flags(MQTT_SUB_FLAG_HS)) {
|
||||
shell.print("[hs<n>.]");
|
||||
i += 8;
|
||||
}
|
||||
shell.print(cl);
|
||||
// pad with spaces
|
||||
|
||||
@@ -34,8 +34,10 @@ enum CommandFlag : uint8_t {
|
||||
MQTT_SUB_FLAG_DEFAULT = 0, // 0 no flags set, always subscribe to MQTT
|
||||
MQTT_SUB_FLAG_HC = (1 << 0), // 1 TAG_HC1 - TAG_HC8
|
||||
MQTT_SUB_FLAG_DHW = (1 << 1), // 2 TAG_DHW1 - TAG_DHW4
|
||||
HIDDEN = (1 << 3), // 8 do not show in API or Web
|
||||
ADMIN_ONLY = (1 << 4) // 16 requires authentication
|
||||
MQTT_SUB_FLAG_AHS = (1 << 2), // 4 TAG_DEVICE_DATA_AHS
|
||||
MQTT_SUB_FLAG_HS = (1 << 3), // 8 TAG_DEVICE_DATA_HS
|
||||
HIDDEN = (1 << 6), // 64 do not show in API or Web
|
||||
ADMIN_ONLY = (1 << 7) // 128 requires authentication
|
||||
|
||||
};
|
||||
|
||||
@@ -49,6 +51,8 @@ enum CommandRet : uint8_t {
|
||||
INVALID // 5 - invalid (tag)
|
||||
};
|
||||
|
||||
MAKE_ENUM_FIXED(cmdRet, "fail", "ok", "not found", "error", "not allowed", "invalid")
|
||||
|
||||
using cmd_function_p = std::function<bool(const char * data, const int8_t id)>;
|
||||
using cmd_json_function_p = std::function<bool(const char * data, const int8_t id, JsonObject output)>;
|
||||
|
||||
@@ -123,7 +127,7 @@ class Command {
|
||||
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
||||
|
||||
static void show_all(uuid::console::Shell & shell);
|
||||
static Command::CmdFunction * find_command(const uint8_t device_type, const uint8_t device_id, const char * cmd);
|
||||
static Command::CmdFunction * find_command(const uint8_t device_type, const uint8_t device_id, const char * cmd, const uint8_t flag);
|
||||
|
||||
static void erase_command(const uint8_t device_type, const char * cmd);
|
||||
static void show(uuid::console::Shell & shell, uint8_t device_type, bool verbose);
|
||||
|
||||
@@ -123,6 +123,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
register_telegram_type(curve_typeids[i], "RC30Temp", false, MAKE_PF_CB(process_RC30Temp));
|
||||
register_telegram_type(timer_typeids[i], "RC30Timer", false, MAKE_PF_CB(process_RC35Timer));
|
||||
}
|
||||
register_telegram_type(0xA9, "RC30Vacation", true, MAKE_PF_CB(process_RC30Vacation));
|
||||
register_telegram_type(EMS_TYPE_RC30wwSettings, "RC30WWSettings", true, MAKE_PF_CB(process_RC30wwSettings));
|
||||
register_telegram_type(0x38, "WWTimer", true, MAKE_PF_CB(process_RC35wwTimer));
|
||||
register_telegram_type(0x39, "WWCircTimer", true, MAKE_PF_CB(process_RC35wwTimer));
|
||||
@@ -1514,7 +1515,29 @@ void Thermostat::process_RC35Timer(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
}
|
||||
|
||||
// process_RCTime - type 0x06 - date and time from a thermostat - 14 bytes long
|
||||
// type 0x9A (HC1)
|
||||
void Thermostat::process_RC30Vacation(std::shared_ptr<const Telegram> telegram) {
|
||||
auto hc = heating_circuit(0x9A - telegram->type_id + 1);
|
||||
if (hc == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (telegram->message_length + telegram->offset >= 7 && telegram->offset <= 1) {
|
||||
char data[sizeof(hc->vacation)];
|
||||
snprintf(data,
|
||||
sizeof(data),
|
||||
"%02d.%02d.%04d-%02d.%02d.%04d",
|
||||
telegram->message_data[1 - telegram->offset],
|
||||
telegram->message_data[2 - telegram->offset],
|
||||
telegram->message_data[3 - telegram->offset] + 2000,
|
||||
telegram->message_data[4 - telegram->offset],
|
||||
telegram->message_data[5 - telegram->offset],
|
||||
telegram->message_data[7 - telegram->offset] + 2000);
|
||||
has_update(hc->vacation, data, sizeof(hc->vacation));
|
||||
}
|
||||
}
|
||||
|
||||
// process_RCTime - type 0x06 - date and time from a thermostat - 12 or 15 bytes long
|
||||
void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
|
||||
if (telegram->offset > 0 || telegram->message_length < 8) {
|
||||
return;
|
||||
@@ -1912,6 +1935,7 @@ bool Thermostat::set_remotehum(const char * value, const int8_t id) {
|
||||
Roomctrl::set_remotehum(Roomctrl::RC100H, hc->hc(), hc->remotehum); // RC100H
|
||||
return true;
|
||||
}
|
||||
Roomctrl::set_remotehum(Roomctrl::RC100H, hc->hc(), EMS_VALUE_UINT8_NOTSET); // RC100H
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2044,7 +2068,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 dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
uint8_t set;
|
||||
|
||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_RC10) {
|
||||
@@ -2122,7 +2146,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) {
|
||||
uint8_t dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
bool b;
|
||||
if (!Helpers::value2bool(value, b)) {
|
||||
return false;
|
||||
@@ -2139,7 +2163,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) {
|
||||
uint8_t dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
int t;
|
||||
if (!Helpers::value2number(value, t)) {
|
||||
return false;
|
||||
@@ -2187,7 +2211,7 @@ bool Thermostat::set_cooling(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 dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
uint8_t set;
|
||||
|
||||
if (isRC300() || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
|
||||
@@ -2207,7 +2231,7 @@ bool Thermostat::set_wwcircmode(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
bool Thermostat::set_wwDailyHeating(const char * value, const int8_t id) {
|
||||
uint8_t dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
bool b;
|
||||
if (!Helpers::value2bool(value, b)) {
|
||||
return false;
|
||||
@@ -2218,7 +2242,7 @@ bool Thermostat::set_wwDailyHeating(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
bool Thermostat::set_wwDailyHeatTime(const char * value, const int8_t id) {
|
||||
uint8_t dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
int set;
|
||||
if (!Helpers::value2number(value, set)) {
|
||||
return false;
|
||||
@@ -2236,7 +2260,7 @@ bool Thermostat::set_wwDailyHeatTime(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
bool Thermostat::set_wwDisinfect(const char * value, const int8_t id) {
|
||||
uint8_t dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
bool b;
|
||||
if (!Helpers::value2bool(value, b)) {
|
||||
return false;
|
||||
@@ -2254,7 +2278,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 dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
uint8_t set;
|
||||
if (!Helpers::value2enum(value, set, FL_(enum_dayOfWeek))) {
|
||||
return false;
|
||||
@@ -2272,7 +2296,7 @@ bool Thermostat::set_wwDisinfectDay(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
bool Thermostat::set_wwDisinfectHour(const char * value, const int8_t id) {
|
||||
uint8_t dhw = id - DeviceValueTAG::TAG_DHW1;
|
||||
uint8_t dhw = id2dhw(id);
|
||||
int set;
|
||||
if (isRC300() || (model() == EMSdevice::EMS_DEVICE_FLAG_RC100)) {
|
||||
if (!Helpers::value2number(value, set, 0, 1431)) {
|
||||
@@ -2410,6 +2434,10 @@ bool Thermostat::set_holiday(const char * value, const int8_t id, const bool vac
|
||||
if (data[0] > 31 || data[1] > 12 || data[3] > 31 || data[4] > 12) {
|
||||
return false;
|
||||
}
|
||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_RC30) {
|
||||
write_command(0xA9 + hc->hc(), 1, data, 6, 0x9A + hc->hc());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!vacation || value[10] == '+') { // + for compatibility
|
||||
if (hc) {
|
||||
@@ -3241,7 +3269,7 @@ bool Thermostat::set_switchtime2(const char * value, const int8_t id) {
|
||||
}
|
||||
// sets a single switchtime in the thermostat dhw program for RC35
|
||||
bool Thermostat::set_wwCircSwitchTime(const char * value, const int8_t id) {
|
||||
auto dhw = dhw_circuit(255, id - DeviceValueTAG::TAG_DHW1 + 1);
|
||||
auto dhw = dhw_circuit(255, id2dhw(id));
|
||||
if (dhw == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -3258,7 +3286,7 @@ bool Thermostat::set_wwCircSwitchTime(const char * value, const int8_t id) {
|
||||
|
||||
// sets a single switchtime in the thermostat circulation program for RC35
|
||||
bool Thermostat::set_wwSwitchTime(const char * value, const int8_t id) {
|
||||
auto dhw = dhw_circuit(255, id - DeviceValueTAG::TAG_DHW1 + 1);
|
||||
auto dhw = dhw_circuit(255, id2dhw(id));
|
||||
if (dhw != nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -213,9 +213,9 @@ class Thermostat : public EMSdevice {
|
||||
void register_device_values();
|
||||
void register_device_values(uint8_t hc_num);
|
||||
|
||||
// specific thermostat characteristics, stripping the top 4 bits
|
||||
// specific thermostat characteristics, stripping the top 2 bits
|
||||
inline uint8_t model() const {
|
||||
return (flags() & 0x0F);
|
||||
return (flags() & 0x3F);
|
||||
}
|
||||
|
||||
// check to see if the thermostat is a hybrid of the R300
|
||||
@@ -223,6 +223,10 @@ class Thermostat : public EMSdevice {
|
||||
return ((model() == EMSdevice::EMS_DEVICE_FLAG_RC300) || (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) || (model() == EMSdevice::EMS_DEVICE_FLAG_BC400));
|
||||
}
|
||||
|
||||
inline uint8_t id2dhw(const int8_t id) const {
|
||||
return id - DeviceValueTAG::TAG_DHW1 + DeviceValueTAG::TAG_HC1 - 1;
|
||||
}
|
||||
|
||||
// each thermostat has a list of heating controller type IDs for reading and writing
|
||||
std::vector<uint16_t> monitor_typeids;
|
||||
std::vector<uint16_t> set_typeids;
|
||||
@@ -398,6 +402,7 @@ class Thermostat : public EMSdevice {
|
||||
void process_RC35Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC35Timer(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Vacation(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Set(std::shared_ptr<const Telegram> telegram);
|
||||
void process_RC30Temp(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
@@ -600,6 +600,10 @@ void EMSdevice::add_device_value(uint8_t tag, // to b
|
||||
flags |= CommandFlag::MQTT_SUB_FLAG_HC;
|
||||
} else if (tag >= DeviceValueTAG::TAG_DHW1 && tag <= DeviceValueTAG::TAG_DHW10) {
|
||||
flags |= CommandFlag::MQTT_SUB_FLAG_DHW;
|
||||
} else if (tag >= DeviceValueTAG::TAG_HS1 && tag <= DeviceValueTAG::TAG_HS16) {
|
||||
flags |= CommandFlag::MQTT_SUB_FLAG_HS;
|
||||
} else if (tag >= DeviceValueTAG::TAG_AHS1 && tag <= DeviceValueTAG::TAG_AHS1) {
|
||||
flags |= CommandFlag::MQTT_SUB_FLAG_AHS;
|
||||
}
|
||||
|
||||
// add the command to our library
|
||||
|
||||
@@ -256,7 +256,7 @@ bool System::command_watch(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
void System::store_nvs_values() {
|
||||
if (Command::find_command(EMSdevice::DeviceType::BOILER, 0, "nompower") != nullptr) {
|
||||
if (Command::find_command(EMSdevice::DeviceType::BOILER, 0, "nompower", 0) != nullptr) {
|
||||
Command::call(EMSdevice::DeviceType::BOILER, "nompower", "-1"); // trigger a write
|
||||
}
|
||||
EMSESP::analogsensor_.store_counters();
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.7.0-dev.6"
|
||||
#define EMSESP_APP_VERSION "3.7.0-dev.7"
|
||||
|
||||
Reference in New Issue
Block a user