Merge pull request #660 from MichaelDvP/dev

Climate min/max #647, RC300 CalIntTemp #657
This commit is contained in:
Proddy
2022-10-04 21:01:59 +02:00
committed by GitHub
14 changed files with 158 additions and 75 deletions

View File

@@ -5,6 +5,7 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import RefreshIcon from '@mui/icons-material/Refresh'; import RefreshIcon from '@mui/icons-material/Refresh';
import ReportIcon from '@mui/icons-material/Report'; import ReportIcon from '@mui/icons-material/Report';
import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff'; import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff';
import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
import { ButtonRow, FormLoader, SectionContent } from '../../components'; import { ButtonRow, FormLoader, SectionContent } from '../../components';
import { MqttStatus, MqttDisconnectReason } from '../../types'; import { MqttStatus, MqttDisconnectReason } from '../../types';
@@ -31,6 +32,12 @@ export const mqttPublishHighlight = ({ mqtt_fails }: MqttStatus, theme: Theme) =
return theme.palette.error.main; return theme.palette.error.main;
}; };
export const mqttQueueHighlight = ({ mqtt_queued }: MqttStatus, theme: Theme) => {
if (mqtt_queued <= 1) return theme.palette.success.main;
return theme.palette.warning.main;
};
const MqttStatusForm: FC = () => { const MqttStatusForm: FC = () => {
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus }); const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
@@ -38,14 +45,14 @@ const MqttStatusForm: FC = () => {
const theme = useTheme(); const theme = useTheme();
const mqttStatus = ({ enabled, connected }: MqttStatus) => { const mqttStatus = ({ enabled, connected, connect_count }: MqttStatus) => {
if (!enabled) { if (!enabled) {
return LL.NOT_ENABLED(); return LL.NOT_ENABLED();
} }
if (connected) { if (connected) {
return LL.CONNECTED(); return (LL.CONNECTED() + (connect_count > 1 ? ' (' + connect_count + ')' : ''));
} }
return LL.DISCONNECTED(); return (LL.DISCONNECTED() + (connect_count > 1 ? ' (' + connect_count + ')' : ''));
}; };
const disconnectReason = ({ disconnect_reason }: MqttStatus) => { const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
@@ -77,36 +84,44 @@ const MqttStatusForm: FC = () => {
} }
const renderConnectionStatus = () => { const renderConnectionStatus = () => {
if (data.connected) {
return (
<>
<ListItem>
<ListItemAvatar>
<Avatar>#</Avatar>
</ListItemAvatar>
<ListItemText primary="Client ID" secondary={data.client_id} />
</ListItem>
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
<SpeakerNotesOffIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={'MQTT Publish ' + LL.ERRORS()} secondary={data.mqtt_fails} />
</ListItem>
</>
);
}
return ( return (
<> <>
{!data.connected && (
<>
<ListItem>
<ListItemAvatar>
<Avatar>
<ReportIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
</ListItem>
<Divider variant="inset" component="li" />
</>
)}
<ListItem> <ListItem>
<ListItemAvatar> <ListItemAvatar>
<Avatar> <Avatar>#</Avatar>
<ReportIcon /> </ListItemAvatar>
<ListItemText primary="Client ID" secondary={data.client_id} />
</ListItem>
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: mqttQueueHighlight(data, theme) }}>
<AutoAwesomeMotionIcon />
</Avatar> </Avatar>
</ListItemAvatar> </ListItemAvatar>
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} /> <ListItemText primary="MQTT Queue" secondary={data.mqtt_queued} />
</ListItem>
<Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
<SpeakerNotesOffIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={'MQTT ' + LL.ERRORS()} secondary={data.mqtt_fails} />
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
</> </>

View File

@@ -508,7 +508,7 @@ const DashboardData: FC = () => {
<ValidatedTextField <ValidatedTextField
name="v" name="v"
label={deviceValue.id.slice(2)} label={deviceValue.id.slice(2)}
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v} value={typeof deviceValue.v === 'number' ? (Math.round(deviceValue.v * 10) / 10) : deviceValue.v}
autoFocus autoFocus
multiline={deviceValue.u ? false : true} multiline={deviceValue.u ? false : true}
sx={{ width: '30ch' }} sx={{ width: '30ch' }}

View File

@@ -165,17 +165,21 @@ const SettingsCustomization: FC = () => {
} }
function formatName(de: DeviceEntity) { function formatName(de: DeviceEntity) {
if (de.n === undefined || de.n === de.id) { if (de.n === undefined) {
return de.id; return (
} <>
(
if (de.n[0] === '!') { <Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
return LL.COMMAND() + ': ' + de.n.slice(1); {de.id}
</Link>
)
</>
);
} }
return ( return (
<> <>
{de.cn !== undefined && de.cn !== '' ? de.cn : de.n} {de.n[0] === '!' ? LL.COMMAND() + ': ' + de.n.slice(1) : de.cn !== undefined && de.cn !== '' ? de.cn : de.n}
&nbsp;( &nbsp;(
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}> <Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
{de.id} {de.id}
@@ -322,7 +326,7 @@ const SettingsCustomization: FC = () => {
}; };
const editEntity = (de: DeviceEntity) => { const editEntity = (de: DeviceEntity) => {
if (de.n && de.n[0] === '!') { if (de.n === undefined || (de.n && de.n[0] === '!')) {
return; return;
} }

View File

@@ -15,6 +15,8 @@ export interface MqttStatus {
client_id: string; client_id: string;
disconnect_reason: MqttDisconnectReason; disconnect_reason: MqttDisconnectReason;
mqtt_fails: number; mqtt_fails: number;
mqtt_queued: number;
connect_count: number;
} }
export interface MqttSettings { export interface MqttSettings {

View File

@@ -20,7 +20,9 @@ void MqttStatus::mqttStatus(AsyncWebServerRequest * request) {
root["client_id"] = _mqttSettingsService->getClientId(); root["client_id"] = _mqttSettingsService->getClientId();
root["disconnect_reason"] = (uint8_t)_mqttSettingsService->getDisconnectReason(); root["disconnect_reason"] = (uint8_t)_mqttSettingsService->getDisconnectReason();
root["mqtt_fails"] = emsesp::Mqtt::publish_fails(); // proddy added root["mqtt_queued"] = emsesp::Mqtt::publish_queued(); // mdvp added
root["mqtt_fails"] = emsesp::Mqtt::publish_fails(); // proddy added
root["connect_count"] = emsesp::Mqtt::connect_count(); // mdvp added
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@@ -522,7 +522,7 @@ void Thermostat::process_RC10Set(std::shared_ptr<const Telegram> telegram) {
if (hc == nullptr) { if (hc == nullptr) {
return; return;
} }
has_update(telegram, ibaClockOffset_, 0); has_update(telegram, ibaCalIntTemperature_, 0);
has_update(telegram, backlight_, 1); has_update(telegram, backlight_, 1);
has_update(telegram, wwMode_, 2); has_update(telegram, wwMode_, 2);
has_update(telegram, hc->nighttemp, 3); has_update(telegram, hc->nighttemp, 3);
@@ -1102,6 +1102,7 @@ void Thermostat::process_RC300OutdoorTemp(std::shared_ptr<const Telegram> telegr
// 0x240 RC300 parameter // 0x240 RC300 parameter
void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, ibaCalIntTemperature_, 7);
has_update(telegram, ibaDamping_, 8); has_update(telegram, ibaDamping_, 8);
has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy has_enumupdate(telegram, ibaBuildingType_, 9, 1); // 1=light, 2=medium, 3=heavy
has_update(telegram, ibaMinExtTemperature_, 10); 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); write_command(EMS_TYPE_RC30Settings, 1, t, EMS_TYPE_RC30Settings);
} else if (model() == EMS_DEVICE_FLAG_RC100H) { } else if (model() == EMS_DEVICE_FLAG_RC100H) {
write_command(0x273, 0, t, 0x273); 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 { } else {
write_command(EMS_TYPE_IBASettings, 2, t, EMS_TYPE_IBASettings); 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; 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) { bool Thermostat::set_display(const char * value, const int8_t id) {
int ds = 0; uint8_t ds;
if (!Helpers::value2number(value, ds)) { if (!Helpers::value2enum(value, ds, FL_(enum_ibaMainDisplay))) {
return false; return false;
} }
@@ -3382,6 +3385,13 @@ void Thermostat::register_device_values() {
FL_(dateTime), FL_(dateTime),
DeviceValueUOM::NONE, DeviceValueUOM::NONE,
MAKE_CF_CB(set_datetime)); 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, register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&floordrystatus_, &floordrystatus_,
DeviceValueType::ENUM, DeviceValueType::ENUM,
@@ -3506,12 +3516,6 @@ void Thermostat::register_device_values() {
FL_(ibaLanguage), FL_(ibaLanguage),
DeviceValueUOM::NONE, DeviceValueUOM::NONE,
MAKE_CF_CB(set_language)); 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, &backlight_, DeviceValueType::BOOL, FL_(backlight), DeviceValueUOM::NONE, MAKE_CF_CB(set_backlight));
register_device_value( register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &brightness_, DeviceValueType::INT, FL_(brightness), DeviceValueUOM::NONE, MAKE_CF_CB(set_brightness), -15, 15); 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, DeviceValueType::ENUM,
FL_(enum_ibaMainDisplay), FL_(enum_ibaMainDisplay),
FL_(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, &ibaLanguage_, DeviceValueType::ENUM, FL_(enum_ibaLanguage), FL_(ibaLanguage), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaClockOffset_, &ibaClockOffset_,
DeviceValueType::INT, DeviceValueType::INT,
FL_(ibaClockOffset), 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, register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&ibaCalIntTemperature_, &ibaCalIntTemperature_,
DeviceValueType::INT, 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->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->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, nullptr, 5, 30);
switch (model) { switch (model) {
case EMS_DEVICE_FLAG_RC10: 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->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->modetype, DeviceValueType::ENUM, FL_(enum_modetype3), FL_(modetype), DeviceValueUOM::NONE);
register_device_value( register_device_value(
tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp)); tag, &hc->daytemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(daytemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_daytemp), 5, 30);
register_device_value( register_device_value(tag,
tag, &hc->nighttemp, DeviceValueType::UINT, DeviceValueNumOp::DV_NUMOP_DIV2, FL_(nighttemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_nighttemp)); &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->designtemp, DeviceValueType::UINT, FL_(designtemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_designtemp), 30, 90);
register_device_value(tag, register_device_value(tag,
&hc->offsettemp, &hc->offsettemp,
@@ -4154,7 +4167,9 @@ void Thermostat::register_device_values_hc(std::shared_ptr<Thermostat::HeatingCi
DeviceValueNumOp::DV_NUMOP_DIV2, DeviceValueNumOp::DV_NUMOP_DIV2,
FL_(holidaytemp), FL_(holidaytemp),
DeviceValueUOM::DEGREES, 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->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->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); 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, DeviceValueNumOp::DV_NUMOP_DIV2,
FL_(tempautotemp), FL_(tempautotemp),
DeviceValueUOM::DEGREES, 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->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->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); register_device_value(tag, &hc->vacreducetemp, DeviceValueType::INT, FL_(vacreducetemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_vacreducetemp), -20, 10);

View File

@@ -860,7 +860,8 @@ void EMSdevice::generate_values_web(JsonObject & output) {
obj["s"] = Helpers::render_value(s, (float)(-1) * dv.numeric_operator, 0); 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)) { if (dv.get_min_max(dv_set_min, dv_set_max)) {
obj["m"] = Helpers::render_value(s, dv_set_min, 0); obj["m"] = Helpers::render_value(s, dv_set_min, 0);
obj["x"] = Helpers::render_value(s, dv_set_max, 0); obj["x"] = Helpers::render_value(s, dv_set_max, 0);
@@ -986,6 +987,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 // 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) // returns true if the entity has a mask set (not 0 the default)
void EMSdevice::setCustomEntity(const std::string & entity_id) { void EMSdevice::setCustomEntity(const std::string & entity_id) {
@@ -1009,7 +1024,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 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 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 // remove ha config on change of dv_readonly flag
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true) Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
@@ -1024,7 +1039,13 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
} else { } else {
dv.custom_fullname = ""; dv.custom_fullname = "";
} }
auto min = dv.min;
auto max = dv.max;
dv.set_custom_minmax(); 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; return;
} }
} }
@@ -1192,11 +1213,14 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
break; break;
} }
// set the min and max // set the min and max only for commands
int16_t dv_set_min, dv_set_max; if (dv.has_cmd) {
if (dv.get_min_max(dv_set_min, dv_set_max)) { int16_t dv_set_min;
json["min"] = dv_set_min; uint16_t dv_set_max;
json["max"] = 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) // add uom if it's not a " " (single space)
@@ -1474,12 +1498,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))) { 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.remove_state(DeviceValueState::DV_HA_CLIMATE_NO_RT);
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED); 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 } 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.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_CLIMATE_NO_RT);
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED); 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) 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 list_device_entries(JsonObject & output) const;
void add_handlers_ignored(const uint16_t handler); 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 setCustomEntity(const std::string & entity_id);
void getCustomEntities(std::vector<std::string> & entity_ids); void getCustomEntities(std::vector<std::string> & entity_ids);

View File

@@ -266,7 +266,7 @@ bool DeviceValue::hasValue() const {
// converts to signed int, which means rounding to an whole integer // converts to signed int, which means rounding to an whole integer
// returns false if there is no min/max needed // returns false if there is no min/max needed
// Types BOOL, ENUM, STRING and CMD are not used // 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; 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 // if we have individual limits set already, just do the conversion

View File

@@ -177,7 +177,7 @@ class DeviceValue {
uint8_t state); uint8_t state);
bool hasValue() const; 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(); void set_custom_minmax();
bool get_custom_min(int16_t & val); bool get_custom_min(int16_t & val);

View File

@@ -273,7 +273,7 @@ MAKE_PSTR(response, "response")
MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww") MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww")
MAKE_PSTR(tag_device_data_ww_mqtt, "") MAKE_PSTR(tag_device_data_ww_mqtt, "")
MAKE_PSTR_LIST(climate, F("HA climate config creation")) MAKE_PSTR_LIST(climate, F("HA climate config creation"), F("")) // empty fullname
// syslog // syslog
MAKE_PSTR_LIST(list_syslog_level, F("off"), F("emerg"), F("alert"), F("crit"), F("error"), F("warn"), F("notice"), F("info"), F("debug"), F("trace"), F("all")) MAKE_PSTR_LIST(list_syslog_level, F("off"), F("emerg"), F("alert"), F("crit"), F("error"), F("warn"), F("notice"), F("info"), F("debug"), F("trace"), F("all"))

View File

@@ -917,8 +917,8 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
} }
// calculate the min and max // calculate the min and max
int16_t dv_set_min; 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); (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 // determine if we're creating the command topics which we use special HA configs
@@ -1248,7 +1248,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
publish_ha(topic, doc.as<JsonObject>()); 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; uint8_t hc_num = tag - DeviceValueTAG::TAG_HC1 + 1;
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
@@ -1321,8 +1321,8 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove
doc["curr_temp_tpl"] = currtemp_s; doc["curr_temp_tpl"] = currtemp_s;
} }
doc["min_temp"] = Helpers::render_value(min_s, (uint32_t)5, 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, (uint32_t)30, 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"; doc["temp_step"] = "0.5";
// the HA climate component only responds to auto, heat and off // the HA climate component only responds to auto, heat and off

View File

@@ -108,7 +108,7 @@ class Mqtt {
const JsonObject & dev_json); const JsonObject & dev_json);
static void publish_system_ha_sensor_config(uint8_t type, const __FlashStringHelper * name, const __FlashStringHelper * entity, const uint8_t uom); static void publish_system_ha_sensor_config(uint8_t type, const __FlashStringHelper * name, const __FlashStringHelper * 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_topic_handlers(uuid::console::Shell & shell, const uint8_t device_type);
static void show_mqtt(uuid::console::Shell & shell); static void show_mqtt(uuid::console::Shell & shell);
@@ -167,6 +167,14 @@ class Mqtt {
return mqtt_publish_fails_; 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 void reset_mqtt();
static bool is_nested() { static bool is_nested() {
@@ -178,7 +186,7 @@ class Mqtt {
} }
static bool publish_single() { static bool publish_single() {
return publish_single_; return mqtt_enabled_ && publish_single_;
} }
static bool publish_single2cmd() { static bool publish_single2cmd() {
@@ -190,7 +198,7 @@ class Mqtt {
} }
static bool ha_enabled() { static bool ha_enabled() {
return ha_enabled_; return mqtt_enabled_ && ha_enabled_;
} }
static void ha_enabled(bool ha_enabled) { static void ha_enabled(bool ha_enabled) {

View File

@@ -434,6 +434,11 @@ void TxService::add(const uint8_t operation,
// if the queue is full, make room but removing the last one // if the queue is full, make room but removing the last one
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) { 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(); tx_telegrams_.pop_front();
} }
@@ -507,6 +512,11 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt
// if the queue is full, make room but removing the last one // if the queue is full, make room but removing the last one
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) { 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(); tx_telegrams_.pop_front();
} }