mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Merge pull request #660 from MichaelDvP/dev
Climate min/max #647, RC300 CalIntTemp #657
This commit is contained in:
@@ -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" />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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' }}
|
||||||
|
|||||||
@@ -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}
|
||||||
(
|
(
|
||||||
<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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
10
src/mqtt.cpp
10
src/mqtt.cpp
@@ -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
|
||||||
|
|||||||
14
src/mqtt.h
14
src/mqtt.h
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user