This commit is contained in:
Proddy
2022-10-04 21:01:23 +02:00
parent 58a0ec9cca
commit e37bbe420c
19 changed files with 221 additions and 134 deletions

View File

@@ -522,7 +522,7 @@ void Thermostat::process_RC10Set(std::shared_ptr<const Telegram> telegram) {
if (hc == nullptr) {
return;
}
has_update(telegram, ibaClockOffset_, 0);
has_update(telegram, ibaCalIntTemperature_, 0);
has_update(telegram, backlight_, 1);
has_update(telegram, wwMode_, 2);
has_update(telegram, hc->nighttemp, 3);
@@ -1102,6 +1102,7 @@ void Thermostat::process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegr
// 0x240 RC300 parameter
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, ibaCalIntTemperature_, 7);
has_update(telegram, ibaDamping_, 8);
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
has_update(telegram, ibaMinExtTemperature_, 10);
@@ -1557,6 +1558,8 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
write_command(EMS_TYPE_RC30Settings, 1, t, EMS_TYPE_RC30Settings);
} else if (model() == EMS_DEVICE_FLAG_RC100H) {
write_command(0x273, 0, t, 0x273);
} else if (model() == EMS_DEVICE_FLAG_RC100 || model() == EMS_DEVICE_FLAG_RC300) {
write_command(0x240, 7, t, 0x240);
} else {
write_command(EMS_TYPE_IBASettings, 2, t, EMS_TYPE_IBASettings);
}
@@ -1564,10 +1567,10 @@ bool Thermostat::set_calinttemp(const char * value, const int8_t id) {
return true;
}
// 0xA5 - Set the display settings
// 0xA5 - Set the display settings, RC30_N
bool Thermostat::set_display(const char * value, const int8_t id) {
int ds = 0;
if (!Helpers::value2number(value, ds)) {
uint8_t ds;
if (!Helpers::value2enum(value, ds, FL_(enum_ibaMainDisplay))) {
return false;
}
@@ -3382,6 +3385,13 @@ void Thermostat::register_device_values() {
FL_(dateTime),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_datetime));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaCalIntTemperature_,
DeviceValueType::INT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(ibaCalIntTemperature),
DeviceValueUOM::DEGREES_R,
MAKE_CF_CB(set_calinttemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&floordrystatus_,
DeviceValueType::ENUM,
@@ -3506,12 +3516,6 @@ void Thermostat::register_device_values() {
FL_(ibaLanguage),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_language));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaMainDisplay_,
DeviceValueType::ENUM,
FL_(enum_ibaMainDisplay),
FL_(ibaMainDisplay),
DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &backlight_, DeviceValueType::BOOL, FL_(backlight), DeviceValueUOM::NONE, MAKE_CF_CB(set_backlight));
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &brightness_, DeviceValueType::INT, FL_(brightness), DeviceValueUOM::NONE, MAKE_CF_CB(set_brightness), -15, 15);
@@ -3599,13 +3603,15 @@ void Thermostat::register_device_values() {
DeviceValueType::ENUM,
FL_(enum_ibaMainDisplay),
FL_(ibaMainDisplay),
DeviceValueUOM::NONE);
DeviceValueUOM::NONE,
MAKE_CF_CB(set_display));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaClockOffset_,
DeviceValueType::INT,
FL_(ibaClockOffset),
DeviceValueUOM::SECONDS); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
DeviceValueUOM::SECONDS,
MAKE_CF_CB(set_clockoffset)); // offset (in sec) to clock, 0xff=-1s, 0x02=2s
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaCalIntTemperature_,
DeviceValueType::INT,
@@ -3950,7 +3956,7 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(tag, &hc->selTemp, DeviceValueType::SHORT, seltemp_divider, FL_(selRoomTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_temp), 0, 30);
}
register_device_value(tag, &hc->roomTemp, DeviceValueType::SHORT, roomtemp_divider, FL_(roomTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->climate, DeviceValueType::ENUM, FL_(enum_climate), FL_(climate), DeviceValueUOM::NONE);
register_device_value(tag, &hc->climate, DeviceValueType::ENUM, FL_(enum_climate), FL_(climate), DeviceValueUOM::NONE); // min, max set in ha function
switch (model) {
case EMS_DEVICE_FLAG_RC10:
@@ -4135,9 +4141,16 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
register_device_value(tag, &hc->mode, DeviceValueType::ENUM, FL_(enum_mode3), FL_(mode), DeviceValueUOM::NONE, MAKE_CF_CB(set_mode));
register_device_value(tag, &hc->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::NONE);
register_device_value(
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp));
register_device_value(
tag, &hc->nighttemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp));
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp), 5, 30);
register_device_value(tag,
&hc->nighttemp,
DeviceValueType::UINT,
DeviceValueNumOp::DV_NUMOP_DIV2,
FL_(nighttemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_nighttemp),
5,
30);
register_device_value(tag, &hc->designtemp, DeviceValueType::UINT, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp), 30, 90);
register_device_value(tag,
&hc->offsettemp,
@@ -4154,7 +4167,9 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
DeviceValueNumOp::DV_NUMOP_DIV2,
FL_(holidaytemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_holidaytemp));
MAKE_CF_CB(set_holidaytemp),
5,
30);
register_device_value(tag, &hc->targetflowtemp, DeviceValueType::UINT, FL_(targetflowtemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &hc->summertemp, DeviceValueType::UINT, FL_(summertemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_summertemp), 9, 25);
register_device_value(tag, &hc->summermode, DeviceValueType::ENUM, FL_(enum_summer), FL_(summermode), DeviceValueUOM::NONE);
@@ -4183,7 +4198,9 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
DeviceValueNumOp::DV_NUMOP_DIV2,
FL_(tempautotemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_tempautotemp));
MAKE_CF_CB(set_tempautotemp),
0,
30);
register_device_value(tag, &hc->noreducetemp, DeviceValueType::INT, FL_(noreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_noreducetemp), -30, 10);
register_device_value(tag, &hc->reducetemp, DeviceValueType::INT, FL_(reducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_reducetemp), -20, 10);
register_device_value(tag, &hc->vacreducetemp, DeviceValueType::INT, FL_(vacreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_vacreducetemp), -20, 10);

View File

@@ -850,7 +850,8 @@ void EMSdevice::generate_values_web(JsonObject & output) {
obj["s"] = Helpers::render_value(s, (float)(-1) * dv.numeric_operator, 0);
}
int16_t dv_set_min, dv_set_max;
int16_t dv_set_min;
uint16_t dv_set_max;
if (dv.get_min_max(dv_set_min, dv_set_max)) {
obj["m"] = Helpers::render_value(s, dv_set_min, 0);
obj["x"] = Helpers::render_value(s, dv_set_max, 0);
@@ -980,6 +981,20 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
}
}
void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint16_t max) {
for (auto & dv : devicevalues_) {
if (dv.tag == tag && dv.short_name == FL_(climate[0])) {
if (dv.min != min || dv.max != max) {
dv.min = min;
dv.max = max;
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_climate_config(dv.tag, false, true); // delete topic (remove = true)
}
return;
}
}
}
// set mask per device entity based on the id which is prefixed with the 2 char hex mask value
// returns true if the entity has a mask set (not 0 the default)
void EMSdevice::setCustomEntity(const std::string & entity_id) {
@@ -1002,7 +1017,7 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
// if it's a new mask, reconfigure HA
if (Mqtt::ha_enabled() && ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4))) {
if (Mqtt::ha_enabled() && (has_custom_name || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) {
// remove ha config on change of dv_readonly flag
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
@@ -1018,9 +1033,16 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
dv.custom_fullname = "";
}
auto min = dv.min;
auto max = dv.max;
// set the min / max
dv.set_custom_minmax();
if (Mqtt::ha_enabled() && dv.short_name == FL_(seltemp)[0] && (min != dv.min || max != dv.max)) {
set_climate_minmax(dv.tag, dv.min, dv.max);
}
return;
}
}
@@ -1187,11 +1209,14 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
break;
}
// set the min and max
int16_t dv_set_min, dv_set_max;
if (dv.get_min_max(dv_set_min, dv_set_max)) {
json["min"] = dv_set_min;
json["max"] = dv_set_max;
// set the min and max only for commands
if (dv.has_cmd) {
int16_t dv_set_min;
uint16_t dv_set_max;
if (dv.get_min_max(dv_set_min, dv_set_max)) {
json["min"] = dv_set_min;
json["max"] = dv_set_max;
}
}
// add uom if it's not a " " (single space)
@@ -1469,12 +1494,12 @@ void EMSdevice::mqtt_ha_entity_config_create() {
if (*(int8_t *)(dv.value_p) == 1 && (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
dv.remove_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_climate_config(dv.tag, true);
Mqtt::publish_ha_climate_config(dv.tag, true, false, dv.min, dv.max);
} else if (*(int8_t *)(dv.value_p) == 0
&& (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) || !dv.has_state(DeviceValueState::DV_HA_CLIMATE_NO_RT))) {
dv.add_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_climate_config(dv.tag, false);
Mqtt::publish_ha_climate_config(dv.tag, false, false, dv.min, dv.max);
}
}
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE)

View File

@@ -187,6 +187,7 @@ class EMSdevice {
void list_device_entries(JsonObject & output) const;
void add_handlers_ignored(const uint16_t handler);
void set_climate_minmax(uint8_t tag, int16_t min, uint16_t max);
void setCustomEntity(const std::string & entity_id);
void getCustomEntities(std::vector<std::string> & entity_ids);

View File

@@ -270,7 +270,7 @@ bool DeviceValue::hasValue() const {
// converts to signed int, which means rounding to an whole integer
// returns false if there is no min/max needed
// Types BOOL, ENUM, STRING and CMD are not used
bool DeviceValue::get_min_max(int16_t & dv_set_min, int16_t & dv_set_max) {
bool DeviceValue::get_min_max(int16_t & dv_set_min, uint16_t & dv_set_max) {
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
// if we have individual limits set already, just do the conversion

View File

@@ -176,7 +176,7 @@ class DeviceValue {
uint8_t state);
bool hasValue() const;
bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max);
bool get_min_max(int16_t & dv_set_min, uint16_t & dv_set_max);
void set_custom_minmax();
bool get_custom_min(int16_t & val);

View File

@@ -1340,6 +1340,7 @@ void EMSESP::scheduled_fetch_values() {
last_fetch_ = uuid::get_uptime();
no = 1;
}
if (txservice_.tx_queue_empty()) {
uint8_t i = 0;
for (const auto & emsdevice : emsdevices) {

View File

@@ -915,7 +915,7 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
// calculate the min and max
int16_t dv_set_min;
int16_t dv_set_max;
uint16_t dv_set_max;
(void)dv.get_min_max(dv_set_min, dv_set_max);
// determine if we're creating the command topics which we use special HA configs
@@ -1241,7 +1241,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdevice
publish_ha(topic, doc.as<JsonObject>());
}
void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove) {
void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove, const int16_t min, const uint16_t max) {
uint8_t hc_num = tag - DeviceValueTAG::TAG_HC1 + 1;
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
@@ -1313,9 +1313,9 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove
doc["curr_temp_t"] = topic_t;
doc["curr_temp_tpl"] = currtemp_s;
}
doc["min_temp"] = Helpers::render_value(min_s, (uint32_t)5, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
doc["max_temp"] = Helpers::render_value(max_s, (uint32_t)30, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
doc["min_temp"] = Helpers::render_value(min_s, min, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
doc["max_temp"] = Helpers::render_value(max_s, max, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
doc["temp_step"] = "0.5";
// the HA climate component only responds to auto, heat and off

View File

@@ -107,7 +107,7 @@ class Mqtt {
const JsonObject & dev_json);
static void publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom);
static void publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove = false);
static void publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove = false, const int16_t min = 5, const uint16_t max = 30);
static void show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_type);
static void show_mqtt(uuid::console::Shell & shell);
@@ -166,6 +166,14 @@ class Mqtt {
return mqtt_publish_fails_;
}
static uint32_t publish_queued() {
return mqtt_messages_.size();
}
static uint8_t connect_count() {
return connectcount_;
}
static void reset_mqtt();
static bool is_nested() {
@@ -177,7 +185,7 @@ class Mqtt {
}
static bool publish_single() {
return publish_single_;
return mqtt_enabled_ && publish_single_;
}
static bool publish_single2cmd() {
@@ -189,7 +197,7 @@ class Mqtt {
}
static bool ha_enabled() {
return ha_enabled_;
return mqtt_enabled_ && ha_enabled_;
}
static void ha_enabled(bool ha_enabled) {

View File

@@ -432,8 +432,13 @@ void TxService::add(const uint8_t operation,
LOG_DEBUG("[DEBUG] New Tx [#%d] telegram, length %d", tx_telegram_id_, message_length);
#endif
// if the queue is full, make room but removing the last one
// if the queue is full, make room by removing the last one
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
if (tx_telegrams_.front().telegram_->operation == Telegram::Operation::TX_WRITE) {
telegram_write_fail_count_++;
} else {
telegram_read_fail_count_++;
}
tx_telegrams_.pop_front();
}
@@ -505,8 +510,13 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt
auto telegram = std::make_shared<Telegram>(operation, src, dest, type_id, offset, message_data, message_length); // operation is TX_WRITE or TX_READ
// if the queue is full, make room but removing the last one
// if the queue is full, make room by removing the last one
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
if (tx_telegrams_.front().telegram_->operation == Telegram::Operation::TX_WRITE) {
telegram_write_fail_count_++;
} else {
telegram_read_fail_count_++;
}
tx_telegrams_.pop_front();
}