mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
ha optimistic, cs6800 changes, custom entity hide
This commit is contained in:
@@ -11,6 +11,9 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
|
|||||||
- boiler auxheatersource [#2489](https://github.com/emsesp/EMS-ESP32/discussions/2489)
|
- boiler auxheatersource [#2489](https://github.com/emsesp/EMS-ESP32/discussions/2489)
|
||||||
- thermostat last error for RC100/300 [#2501](https://github.com/emsesp/EMS-ESP32/issues/2501)
|
- thermostat last error for RC100/300 [#2501](https://github.com/emsesp/EMS-ESP32/issues/2501)
|
||||||
- boiler 0xC6 telegram [#1963](https://github.com/emsesp/EMS-ESP32/issues/1963)
|
- boiler 0xC6 telegram [#1963](https://github.com/emsesp/EMS-ESP32/issues/1963)
|
||||||
|
- HA optimistic [#2551](https://github.com/emsesp/EMS-ESP32/issues/2551)
|
||||||
|
- CS6800i changes [#2448](https://github.com/emsesp/EMS-ESP32/issues/2448), [#2449](https://github.com/emsesp/EMS-ESP32/issues/2449)
|
||||||
|
- charging pump [#2544](https://github.com/emsesp/EMS-ESP32/issues/2544)
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
@@ -21,6 +24,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/).
|
|||||||
- also rebuild HA config on mqtt connect for scheduler, custom and shower
|
- also rebuild HA config on mqtt connect for scheduler, custom and shower
|
||||||
- FB100 controls the hc, not the master [#2510](https://github.com/emsesp/EMS-ESP32/issues/2510)
|
- FB100 controls the hc, not the master [#2510](https://github.com/emsesp/EMS-ESP32/issues/2510)
|
||||||
- IPM DHW module, [#2524](https://github.com/emsesp/EMS-ESP32/issues/2524)
|
- IPM DHW module, [#2524](https://github.com/emsesp/EMS-ESP32/issues/2524)
|
||||||
|
- charge optimization [#2543](https://github.com/emsesp/EMS-ESP32/issues/2543)
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,8 @@ export const readCustomEntities = () =>
|
|||||||
o_name: ei.name,
|
o_name: ei.name,
|
||||||
o_writeable: ei.writeable,
|
o_writeable: ei.writeable,
|
||||||
o_value: ei.value,
|
o_value: ei.value,
|
||||||
o_deleted: ei.deleted
|
o_deleted: ei.deleted,
|
||||||
|
o_hide: ei.hide
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ const CustomEntities = () => {
|
|||||||
ei.factor !== ei.o_factor ||
|
ei.factor !== ei.o_factor ||
|
||||||
ei.value_type !== ei.o_value_type ||
|
ei.value_type !== ei.o_value_type ||
|
||||||
ei.writeable !== ei.o_writeable ||
|
ei.writeable !== ei.o_writeable ||
|
||||||
|
ei.hide !== ei.o_hide ||
|
||||||
ei.deleted !== ei.o_deleted ||
|
ei.deleted !== ei.o_deleted ||
|
||||||
(ei.value || '') !== (ei.o_value || '')
|
(ei.value || '') !== (ei.o_value || '')
|
||||||
);
|
);
|
||||||
@@ -147,6 +148,7 @@ const CustomEntities = () => {
|
|||||||
factor: condensed_ei.factor,
|
factor: condensed_ei.factor,
|
||||||
uom: condensed_ei.uom,
|
uom: condensed_ei.uom,
|
||||||
writeable: condensed_ei.writeable,
|
writeable: condensed_ei.writeable,
|
||||||
|
hide: condensed_ei.hide,
|
||||||
value_type: condensed_ei.value_type,
|
value_type: condensed_ei.value_type,
|
||||||
value: condensed_ei.value
|
value: condensed_ei.value
|
||||||
}))
|
}))
|
||||||
@@ -209,6 +211,7 @@ const CustomEntities = () => {
|
|||||||
value_type: item.value_type,
|
value_type: item.value_type,
|
||||||
writeable: item.writeable,
|
writeable: item.writeable,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
hide: item.hide,
|
||||||
value: item.value
|
value: item.value
|
||||||
});
|
});
|
||||||
setDialogOpen(true);
|
setDialogOpen(true);
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { useEffect, useState } from 'react';
|
|||||||
|
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||||
import DoneIcon from '@mui/icons-material/Done';
|
import DoneIcon from '@mui/icons-material/Done';
|
||||||
|
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||||
|
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
||||||
|
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -128,6 +132,20 @@ const CustomEntitiesDialog = ({
|
|||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid mt={3}>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
icon={<InsertCommentOutlinedIcon htmlColor="white" />}
|
||||||
|
checkedIcon={<CommentsDisabledOutlinedIcon color="primary" />}
|
||||||
|
checked={editItem.hide}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
name="hide"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="API/Mqtt"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
name="ram"
|
name="ram"
|
||||||
@@ -177,10 +195,12 @@ const CustomEntitiesDialog = ({
|
|||||||
)}
|
)}
|
||||||
{editItem.ram === 0 && (
|
{editItem.ram === 0 && (
|
||||||
<>
|
<>
|
||||||
<Grid mt={3} size={9}>
|
<Grid mt={3}>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
icon={<EditOffOutlinedIcon color="primary" />}
|
||||||
|
checkedIcon={<EditOutlinedIcon htmlColor="white" />}
|
||||||
checked={editItem.writeable}
|
checked={editItem.writeable}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
name="writeable"
|
name="writeable"
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ export interface EntityItem {
|
|||||||
value_type: number;
|
value_type: number;
|
||||||
value?: unknown;
|
value?: unknown;
|
||||||
writeable: boolean;
|
writeable: boolean;
|
||||||
|
hide: boolean;
|
||||||
deleted?: boolean;
|
deleted?: boolean;
|
||||||
o_id?: number;
|
o_id?: number;
|
||||||
o_ram?: number;
|
o_ram?: number;
|
||||||
@@ -397,6 +398,7 @@ export interface EntityItem {
|
|||||||
o_deleted?: boolean;
|
o_deleted?: boolean;
|
||||||
o_writeable?: boolean;
|
o_writeable?: boolean;
|
||||||
o_value?: unknown;
|
o_value?: unknown;
|
||||||
|
o_hide?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Entities {
|
export interface Entities {
|
||||||
|
|||||||
@@ -254,7 +254,6 @@ const MqttSettings = () => {
|
|||||||
}
|
}
|
||||||
label={LL.MQTT_RESPONSE()}
|
label={LL.MQTT_RESPONSE()}
|
||||||
/>
|
/>
|
||||||
{!data.ha_enabled && (
|
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
@@ -263,6 +262,7 @@ const MqttSettings = () => {
|
|||||||
name="publish_single"
|
name="publish_single"
|
||||||
checked={data.publish_single}
|
checked={data.publish_single}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={data.ha_enabled}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={LL.MQTT_PUBLISH_TEXT_1()}
|
label={LL.MQTT_PUBLISH_TEXT_1()}
|
||||||
@@ -283,8 +283,6 @@ const MqttSettings = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
|
||||||
{!data.publish_single && (
|
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
<Grid>
|
<Grid>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
@@ -293,10 +291,23 @@ const MqttSettings = () => {
|
|||||||
name="ha_enabled"
|
name="ha_enabled"
|
||||||
checked={data.ha_enabled}
|
checked={data.ha_enabled}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={data.publish_single}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={LL.MQTT_PUBLISH_TEXT_3()}
|
label={LL.MQTT_PUBLISH_TEXT_3()}
|
||||||
/>
|
/>
|
||||||
|
{data.ha_enabled && data.discovery_type === 0 && (
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
name="ha_optimistic"
|
||||||
|
checked={data.ha_optimistic}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Optimistic"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.ha_enabled && (
|
{data.ha_enabled && (
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
<Grid container spacing={2} rowSpacing={0}>
|
||||||
@@ -349,7 +360,6 @@ const MqttSettings = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
{LL.MQTT_PUBLISH_INTERVALS()} (0=auto)
|
{LL.MQTT_PUBLISH_INTERVALS()} (0=auto)
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export interface MqttSettingsType {
|
|||||||
mqtt_qos: number;
|
mqtt_qos: number;
|
||||||
mqtt_retain: boolean;
|
mqtt_retain: boolean;
|
||||||
ha_enabled: boolean;
|
ha_enabled: boolean;
|
||||||
|
ha_optimistic: boolean;
|
||||||
nested_format: number;
|
nested_format: number;
|
||||||
send_response: boolean;
|
send_response: boolean;
|
||||||
publish_single: boolean;
|
publish_single: boolean;
|
||||||
|
|||||||
@@ -567,6 +567,7 @@ let mqtt_settings = {
|
|||||||
rootCA: '',
|
rootCA: '',
|
||||||
mqtt_retain: false,
|
mqtt_retain: false,
|
||||||
ha_enabled: true,
|
ha_enabled: true,
|
||||||
|
ha_optimistic: false,
|
||||||
nested_format: 1,
|
nested_format: 1,
|
||||||
discovery_type: 0,
|
discovery_type: 0,
|
||||||
discovery_prefix: 'homeassistant',
|
discovery_prefix: 'homeassistant',
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ void MqttSettings::read(MqttSettings & settings, JsonObject root) {
|
|||||||
root["mqtt_qos"] = settings.mqtt_qos;
|
root["mqtt_qos"] = settings.mqtt_qos;
|
||||||
root["mqtt_retain"] = settings.mqtt_retain;
|
root["mqtt_retain"] = settings.mqtt_retain;
|
||||||
root["ha_enabled"] = settings.ha_enabled;
|
root["ha_enabled"] = settings.ha_enabled;
|
||||||
|
root["ha_optimistic"] = settings.ha_optimistic;
|
||||||
root["nested_format"] = settings.nested_format;
|
root["nested_format"] = settings.nested_format;
|
||||||
root["discovery_prefix"] = settings.discovery_prefix;
|
root["discovery_prefix"] = settings.discovery_prefix;
|
||||||
root["discovery_type"] = settings.discovery_type;
|
root["discovery_type"] = settings.discovery_type;
|
||||||
@@ -284,6 +285,7 @@ StateUpdateResult MqttSettings::update(JsonObject root, MqttSettings & settings)
|
|||||||
newSettings.publish_time_heartbeat = static_cast<uint16_t>(root["publish_time_heartbeat"] | EMSESP_DEFAULT_PUBLISH_HEARTBEAT);
|
newSettings.publish_time_heartbeat = static_cast<uint16_t>(root["publish_time_heartbeat"] | EMSESP_DEFAULT_PUBLISH_HEARTBEAT);
|
||||||
|
|
||||||
newSettings.ha_enabled = root["ha_enabled"] | EMSESP_DEFAULT_HA_ENABLED;
|
newSettings.ha_enabled = root["ha_enabled"] | EMSESP_DEFAULT_HA_ENABLED;
|
||||||
|
newSettings.ha_optimistic = root["ha_optimistic"] | EMSESP_DEFAULT_HA_OPTIMISTIC;
|
||||||
newSettings.nested_format = static_cast<uint8_t>(root["nested_format"] | EMSESP_DEFAULT_NESTED_FORMAT);
|
newSettings.nested_format = static_cast<uint8_t>(root["nested_format"] | EMSESP_DEFAULT_NESTED_FORMAT);
|
||||||
newSettings.discovery_prefix = root["discovery_prefix"] | EMSESP_DEFAULT_DISCOVERY_PREFIX;
|
newSettings.discovery_prefix = root["discovery_prefix"] | EMSESP_DEFAULT_DISCOVERY_PREFIX;
|
||||||
newSettings.discovery_type = static_cast<uint8_t>(root["discovery_type"] | EMSESP_DEFAULT_DISCOVERY_TYPE);
|
newSettings.discovery_type = static_cast<uint8_t>(root["discovery_type"] | EMSESP_DEFAULT_DISCOVERY_TYPE);
|
||||||
@@ -345,6 +347,14 @@ StateUpdateResult MqttSettings::update(JsonObject root, MqttSettings & settings)
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newSettings.discovery_type != 0) {
|
||||||
|
newSettings.ha_optimistic = false;
|
||||||
|
}
|
||||||
|
if (newSettings.ha_optimistic != settings.ha_optimistic) {
|
||||||
|
emsesp::EMSESP::mqtt_.ha_optimistic(newSettings.ha_optimistic);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (newSettings.mqtt_retain != settings.mqtt_retain) {
|
if (newSettings.mqtt_retain != settings.mqtt_retain) {
|
||||||
emsesp::EMSESP::mqtt_.set_retain(newSettings.mqtt_retain);
|
emsesp::EMSESP::mqtt_.set_retain(newSettings.mqtt_retain);
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class MqttSettings {
|
|||||||
uint8_t mqtt_qos;
|
uint8_t mqtt_qos;
|
||||||
bool mqtt_retain;
|
bool mqtt_retain;
|
||||||
bool ha_enabled;
|
bool ha_enabled;
|
||||||
|
bool ha_optimistic;
|
||||||
uint8_t nested_format;
|
uint8_t nested_format;
|
||||||
String discovery_prefix;
|
String discovery_prefix;
|
||||||
uint8_t discovery_type;
|
uint8_t discovery_type;
|
||||||
|
|||||||
@@ -682,6 +682,9 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
|
|
||||||
Mqtt::add_ha_sections_to_doc("analog", stat_t, config, !is_ha_device_created, val_cond);
|
Mqtt::add_ha_sections_to_doc("analog", stat_t, config, !is_ha_device_created, val_cond);
|
||||||
|
|
||||||
|
if (Mqtt::ha_optimistic()) {
|
||||||
|
config["optimistic"] = true;
|
||||||
|
}
|
||||||
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
sensor.ha_registered = Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,6 +185,10 @@
|
|||||||
#define EMSESP_DEFAULT_HA_ENABLED false
|
#define EMSESP_DEFAULT_HA_ENABLED false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EMSESP_DEFAULT_HA_OPTIMISTIC
|
||||||
|
#define EMSESP_DEFAULT_HA_OPTIMISTIC false
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_PUBLISH_TIME
|
#ifndef EMSESP_DEFAULT_PUBLISH_TIME
|
||||||
#define EMSESP_DEFAULT_PUBLISH_TIME 10
|
#define EMSESP_DEFAULT_PUBLISH_TIME 10
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Boilers - 0x08
|
// Boilers - 0x08
|
||||||
{ 8, DeviceType::BOILER, "CS*800i, Logatherm WLW*", DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{ 8, DeviceType::BOILER, "CS5800i, CS6800i, WLW176i, WLW186i", DeviceFlags::EMS_DEVICE_FLAG_CS6800},
|
||||||
{ 12, DeviceType::BOILER, "C1200W", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 12, DeviceType::BOILER, "C1200W", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 64, DeviceType::BOILER, "BK13/BK15, Smartline, GB1*2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 64, DeviceType::BOILER, "BK13/BK15, Smartline, GB1*2", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{ 72, DeviceType::BOILER, "Logano GB1*5, Logamatic MC10", DeviceFlags::EMS_DEVICE_FLAG_EMS},
|
{ 72, DeviceType::BOILER, "Logano GB1*5, Logamatic MC10", DeviceFlags::EMS_DEVICE_FLAG_EMS},
|
||||||
|
|||||||
@@ -197,6 +197,19 @@ class EMSdevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void has_enumupdate(std::shared_ptr<const Telegram> telegram,
|
||||||
|
uint8_t & value,
|
||||||
|
const uint8_t index,
|
||||||
|
const std::vector<uint8_t> & maskIn,
|
||||||
|
const std::vector<uint8_t> & maskOut) {
|
||||||
|
uint8_t val = value < maskIn.size() ? maskIn[value] : EMS_VALUE_UINT8_NOTSET;
|
||||||
|
if (telegram->read_value(val, index)) {
|
||||||
|
value = val < maskOut.size() ? maskOut[val] : EMS_VALUE_UINT8_NOTSET;
|
||||||
|
has_update_ = true;
|
||||||
|
publish_value((void *)&value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
void has_update(std::shared_ptr<const Telegram> telegram, Value & value, const uint8_t index, uint8_t s = 0) {
|
void has_update(std::shared_ptr<const Telegram> telegram, Value & value, const uint8_t index, uint8_t s = 0) {
|
||||||
if (telegram->read_value(value, index, s)) {
|
if (telegram->read_value(value, index, s)) {
|
||||||
@@ -434,9 +447,10 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1;
|
static constexpr uint8_t EMS_DEVICE_FLAG_EMS = 1;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;
|
static constexpr uint8_t EMS_DEVICE_FLAG_EMSPLUS = 2;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 4;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HYBRID = 4;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HYBRID = 5;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HIU = 5;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HIU = 6;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 8; // use bit for subtypes
|
||||||
|
static constexpr uint8_t EMS_DEVICE_FLAG_CS6800 = 9; // subtype of heatpump
|
||||||
|
|
||||||
// Solar Module
|
// Solar Module
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;
|
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;
|
||||||
|
|||||||
@@ -627,10 +627,18 @@ bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
value_ui = 0;
|
value_ui = 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * const ** strs, const std::vector<uint8_t> & mask) {
|
||||||
|
uint8_t v = value_ui;
|
||||||
|
if (!value2enum(value, v, strs) || v >= mask.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value_ui = mask[v];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// finds the string (value) of a list vector (strs)
|
// finds the string (value) of a list vector (strs)
|
||||||
// returns true if found, and sets the value_ui to the index, else false
|
// returns true if found, and sets the value_ui to the index, else false
|
||||||
// also allow true/false for on/off
|
// also allow true/false for on/off
|
||||||
@@ -658,6 +666,15 @@ bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * co
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Helpers::value2enum(const char * value, uint8_t & value_ui, const char * const * strs, const std::vector<uint8_t> & mask) {
|
||||||
|
uint8_t v = value_ui;
|
||||||
|
if (!value2enum(value, v, strs) || v >= mask.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value_ui = mask[v];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case
|
// https://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case
|
||||||
std::string Helpers::toLower(std::string const & s) {
|
std::string Helpers::toLower(std::string const & s) {
|
||||||
std::string lc = s;
|
std::string lc = s;
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ class Helpers {
|
|||||||
static bool value2bool(const char * value, bool & value_b);
|
static bool value2bool(const char * value, bool & value_b);
|
||||||
static bool value2string(const char * value, std::string & value_s);
|
static bool value2string(const char * value, std::string & value_s);
|
||||||
static bool value2enum(const char * value, uint8_t & value_ui, const char * const ** strs);
|
static bool value2enum(const char * value, uint8_t & value_ui, const char * const ** strs);
|
||||||
|
static bool value2enum(const char * value, uint8_t & value_ui, const char * const ** strs, const std::vector<uint8_t> & mask);
|
||||||
static bool value2enum(const char * value, uint8_t & value_ui, const char * const * strs);
|
static bool value2enum(const char * value, uint8_t & value_ui, const char * const * strs);
|
||||||
|
static bool value2enum(const char * value, uint8_t & value_ui, const char * const * strs, const std::vector<uint8_t> & mask);
|
||||||
static bool value2temperature(const char * value, float & value_f, bool relative = false);
|
static bool value2temperature(const char * value, float & value_f, bool relative = false);
|
||||||
static bool value2temperature(const char * value, int & value_i, const bool relative = false, const int min = -2147483648, const int max = 2147483647);
|
static bool value2temperature(const char * value, int & value_i, const bool relative = false, const int min = -2147483648, const int max = 2147483647);
|
||||||
|
|
||||||
|
|||||||
@@ -298,6 +298,8 @@ MAKE_ENUM(enum_comfort2, FL_(eco), FL_(high_comfort))
|
|||||||
MAKE_ENUM(enum_flow, FL_(off), FL_(flow), FL_(bufferedflow), FL_(buffer), FL_(layeredbuffer))
|
MAKE_ENUM(enum_flow, FL_(off), FL_(flow), FL_(bufferedflow), FL_(buffer), FL_(layeredbuffer))
|
||||||
MAKE_ENUM(enum_reset, FL_(dash), FL_(maintenance), FL_(error), FL_(history), FL_(message))
|
MAKE_ENUM(enum_reset, FL_(dash), FL_(maintenance), FL_(error), FL_(history), FL_(message))
|
||||||
MAKE_ENUM(enum_maxHeat, FL_(0kW), FL_(2kW), FL_(3kW), FL_(4kW), FL_(6kW), FL_(9kW))
|
MAKE_ENUM(enum_maxHeat, FL_(0kW), FL_(2kW), FL_(3kW), FL_(4kW), FL_(6kW), FL_(9kW))
|
||||||
|
MAKE_ENUM(enum_maxHeat1, FL_(0kW), FL_(3kW), FL_(6kW), FL_(9kW))
|
||||||
|
MAKE_ENUM(enum_maxHeat2, FL_(3kW), FL_(6kW), FL_(9kW))
|
||||||
MAKE_ENUM(enum_pumpMode, FL_(proportional), FL_(deltaP1), FL_(deltaP2), FL_(deltaP3), FL_(deltaP4))
|
MAKE_ENUM(enum_pumpMode, FL_(proportional), FL_(deltaP1), FL_(deltaP2), FL_(deltaP3), FL_(deltaP4))
|
||||||
MAKE_ENUM(enum_pumpCharacter, FL_(proportional), FL_(pressure1), FL_(pressure2), FL_(pressure3), FL_(pressure4), FL_(pressure5), FL_(pressure6))
|
MAKE_ENUM(enum_pumpCharacter, FL_(proportional), FL_(pressure1), FL_(pressure2), FL_(pressure3), FL_(pressure4), FL_(pressure5), FL_(pressure6))
|
||||||
MAKE_ENUM(enum_hpPumpMode, FL_(auto), FL_(continuous))
|
MAKE_ENUM(enum_hpPumpMode, FL_(auto), FL_(continuous))
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ uint32_t Mqtt::publish_time_heartbeat_;
|
|||||||
bool Mqtt::mqtt_enabled_;
|
bool Mqtt::mqtt_enabled_;
|
||||||
uint8_t Mqtt::entity_format_;
|
uint8_t Mqtt::entity_format_;
|
||||||
bool Mqtt::ha_enabled_;
|
bool Mqtt::ha_enabled_;
|
||||||
|
bool Mqtt::ha_optimistic_;
|
||||||
uint8_t Mqtt::nested_format_;
|
uint8_t Mqtt::nested_format_;
|
||||||
std::string Mqtt::discovery_prefix_;
|
std::string Mqtt::discovery_prefix_;
|
||||||
uint8_t Mqtt::discovery_type_;
|
uint8_t Mqtt::discovery_type_;
|
||||||
@@ -340,6 +341,7 @@ void Mqtt::load_settings() {
|
|||||||
mqtt_retain_ = mqttSettings.mqtt_retain;
|
mqtt_retain_ = mqttSettings.mqtt_retain;
|
||||||
mqtt_enabled_ = mqttSettings.enabled;
|
mqtt_enabled_ = mqttSettings.enabled;
|
||||||
ha_enabled_ = mqttSettings.ha_enabled;
|
ha_enabled_ = mqttSettings.ha_enabled;
|
||||||
|
ha_optimistic_ = mqttSettings.ha_optimistic;
|
||||||
nested_format_ = mqttSettings.nested_format;
|
nested_format_ = mqttSettings.nested_format;
|
||||||
publish_single_ = mqttSettings.publish_single;
|
publish_single_ = mqttSettings.publish_single;
|
||||||
publish_single2cmd_ = mqttSettings.publish_single2cmd;
|
publish_single2cmd_ = mqttSettings.publish_single2cmd;
|
||||||
@@ -1114,6 +1116,9 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
|
|
||||||
doc["dev"] = dev_json;
|
doc["dev"] = dev_json;
|
||||||
|
|
||||||
|
if (ha_optimistic_) {
|
||||||
|
doc["optimistic"] = true;
|
||||||
|
}
|
||||||
return queue_ha(topic, doc.as<JsonObject>());
|
return queue_ha(topic, doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,6 +1348,9 @@ bool Mqtt::publish_ha_climate_config(const int8_t tag, const bool has_roomtemp,
|
|||||||
// device name must be different to the entity name, take the ids value we just created
|
// device name must be different to the entity name, take the ids value we just created
|
||||||
add_ha_sections_to_doc("thermostat", topic_t, doc, false, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);
|
add_ha_sections_to_doc("thermostat", topic_t, doc, false, seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);
|
||||||
|
|
||||||
|
if (ha_optimistic_) {
|
||||||
|
doc["optimistic"] = true;
|
||||||
|
}
|
||||||
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
return queue_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -206,6 +206,14 @@ class Mqtt {
|
|||||||
ha_enabled_ = ha_enabled;
|
ha_enabled_ = ha_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ha_optimistic() {
|
||||||
|
return ha_optimistic_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ha_optimistic(bool ha_optimistic) {
|
||||||
|
ha_optimistic_ = ha_optimistic;
|
||||||
|
}
|
||||||
|
|
||||||
static bool ha_climate_reset() {
|
static bool ha_climate_reset() {
|
||||||
return ha_climate_reset_;
|
return ha_climate_reset_;
|
||||||
}
|
}
|
||||||
@@ -309,6 +317,7 @@ class Mqtt {
|
|||||||
static uint32_t publish_time_heartbeat_;
|
static uint32_t publish_time_heartbeat_;
|
||||||
static bool mqtt_enabled_;
|
static bool mqtt_enabled_;
|
||||||
static bool ha_enabled_;
|
static bool ha_enabled_;
|
||||||
|
static bool ha_optimistic_;
|
||||||
static uint8_t nested_format_;
|
static uint8_t nested_format_;
|
||||||
static uint8_t entity_format_;
|
static uint8_t entity_format_;
|
||||||
static std::string discovery_prefix_;
|
static std::string discovery_prefix_;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
register_telegram_type(0x28, "WeatherComp", true, MAKE_PF_CB(process_WeatherComp));
|
register_telegram_type(0x28, "WeatherComp", true, MAKE_PF_CB(process_WeatherComp));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_HEATPUMP) {
|
if (!isHeatPump()) {
|
||||||
register_telegram_type(0x494, "UBAEnergySupplied", false, MAKE_PF_CB(process_UBAEnergySupplied));
|
register_telegram_type(0x494, "UBAEnergySupplied", false, MAKE_PF_CB(process_UBAEnergySupplied));
|
||||||
register_telegram_type(0x495, "UBAInformation", false, MAKE_PF_CB(process_UBAInformation));
|
register_telegram_type(0x495, "UBAInformation", false, MAKE_PF_CB(process_UBAInformation));
|
||||||
register_telegram_type(0x48D, "HpPower", true, MAKE_PF_CB(process_HpPower));
|
register_telegram_type(0x48D, "HpPower", true, MAKE_PF_CB(process_HpPower));
|
||||||
@@ -96,7 +96,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// some gas boilers, see #1701
|
// some gas boilers, see #1701
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_HEATPUMP) {
|
if (!isHeatPump()) {
|
||||||
register_telegram_type(0x2E, "Meters", false, MAKE_PF_CB(process_Meters));
|
register_telegram_type(0x2E, "Meters", false, MAKE_PF_CB(process_Meters));
|
||||||
register_telegram_type(0x3B, "Energy", false, MAKE_PF_CB(process_Energy));
|
register_telegram_type(0x3B, "Energy", false, MAKE_PF_CB(process_Energy));
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
DeviceValueUOM::DEGREES);
|
DeviceValueUOM::DEGREES);
|
||||||
|
|
||||||
// exclude burner related entities from heatpump and HIU
|
// exclude burner related entities from heatpump and HIU
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_HEATPUMP && model() != EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
if (!isHeatPump() && model() != EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&exhaustTemp_,
|
&exhaustTemp_,
|
||||||
DeviceValueType::UINT16,
|
DeviceValueType::UINT16,
|
||||||
@@ -411,7 +411,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
99);
|
99);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_HEATPUMP) {
|
if (!isHeatPump()) {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&meterHeat_,
|
&meterHeat_,
|
||||||
DeviceValueType::UINT24,
|
DeviceValueType::UINT24,
|
||||||
@@ -436,7 +436,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// heatpump info
|
// heatpump info
|
||||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_HEATPUMP) {
|
if (isHeatPump()) {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&nrgTotal_,
|
&nrgTotal_,
|
||||||
DeviceValueType::UINT24,
|
DeviceValueType::UINT24,
|
||||||
@@ -655,6 +655,29 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
FL_(hpIn4Opt),
|
FL_(hpIn4Opt),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_HpIn4Logic));
|
MAKE_CF_CB(set_HpIn4Logic));
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_CS6800) {
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&maxHeatComp_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_maxHeat1),
|
||||||
|
FL_(maxHeatComp),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_maxHeatComp));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&maxHeatHeat_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_maxHeat2),
|
||||||
|
FL_(maxHeatHeat),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_maxHeatHeat));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DHW1,
|
||||||
|
&maxHeatDhw_,
|
||||||
|
DeviceValueType::ENUM,
|
||||||
|
FL_(enum_maxHeat2),
|
||||||
|
FL_(maxHeatDhw),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_maxHeatDhw));
|
||||||
|
} else {
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&maxHeatComp_,
|
&maxHeatComp_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
@@ -676,6 +699,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
FL_(maxHeatDhw),
|
FL_(maxHeatDhw),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_maxHeatDhw));
|
MAKE_CF_CB(set_maxHeatDhw));
|
||||||
|
}
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&auxHeaterSource_,
|
&auxHeaterSource_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
@@ -1068,7 +1092,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
EMSESP::send_read_request(0xC6, device_id, 0, 21); // read last errorcode on start (not broadcasted)
|
EMSESP::send_read_request(0xC6, device_id, 0, 21); // read last errorcode on start (not broadcasted)
|
||||||
|
|
||||||
|
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_HEATPUMP && model() != EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
if (!isHeatPump() && model() != EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
||||||
register_telegram_type(0x04, "UBAFactory", true, MAKE_PF_CB(process_UBAFactory));
|
register_telegram_type(0x04, "UBAFactory", true, MAKE_PF_CB(process_UBAFactory));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nomPower_, DeviceValueType::UINT8, FL_(nomPower), DeviceValueUOM::KW, MAKE_CF_CB(set_nomPower));
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nomPower_, DeviceValueType::UINT8, FL_(nomPower), DeviceValueUOM::KW, MAKE_CF_CB(set_nomPower));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
@@ -1189,7 +1213,7 @@ void Boiler::check_active() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculate energy for boiler 0x08 from stored modulation an time in units of 0.01 Wh
|
// calculate energy for boiler 0x08 from stored modulation an time in units of 0.01 Wh
|
||||||
if (model() != EMSdevice::EMS_DEVICE_FLAG_HEATPUMP && model() != EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
if (!isHeatPump() && model() != EMSdevice::EMS_DEVICE_FLAG_HIU) {
|
||||||
// remember values from last call
|
// remember values from last call
|
||||||
static uint32_t powLastReadTime_ = uuid::get_uptime();
|
static uint32_t powLastReadTime_ = uuid::get_uptime();
|
||||||
static uint8_t heatBurnPow = 0;
|
static uint8_t heatBurnPow = 0;
|
||||||
@@ -1780,6 +1804,12 @@ void Boiler::process_HpCooling(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
// Boiler(0x08) -W-> Me(0x0B), HpHeaterConfig(0x0492), data: 03 00 00 04 00
|
// Boiler(0x08) -W-> Me(0x0B), HpHeaterConfig(0x0492), data: 03 00 00 04 00
|
||||||
void Boiler::process_HpHeaterConfig(std::shared_ptr<const Telegram> telegram) {
|
void Boiler::process_HpHeaterConfig(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_CS6800) {
|
||||||
|
has_enumupdate(telegram, maxHeatComp_, 2, {0, 2, 4, 5}, {0, 0, 1, 0, 2, 3});
|
||||||
|
has_enumupdate(telegram, maxHeatHeat_, 3, {2, 4, 5}, {0, 0, 0, 0, 1, 2});
|
||||||
|
has_enumupdate(telegram, maxHeatDhw_, 4, {2, 4, 5}, {0, 0, 0, 0, 1, 2});
|
||||||
|
return;
|
||||||
|
}
|
||||||
has_update(telegram, maxHeatComp_, 2);
|
has_update(telegram, maxHeatComp_, 2);
|
||||||
has_update(telegram, maxHeatHeat_, 3);
|
has_update(telegram, maxHeatHeat_, 3);
|
||||||
has_update(telegram, maxHeatDhw_, 4);
|
has_update(telegram, maxHeatDhw_, 4);
|
||||||
@@ -2080,7 +2110,7 @@ void Boiler::process_HpPump2(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// Boiler(0x08) -> All(0x00), ?(0x0491), data: 03 01 00 00 00 02 64 00 00 14 01 2C 00 0A 00 1E 00 1E 00 00 1E 0A 1E 05 05
|
// Boiler(0x08) -> All(0x00), ?(0x0491), data: 03 01 00 00 00 02 64 00 00 14 01 2C 00 0A 00 1E 00 1E 00 00 1E 0A 1E 05 05
|
||||||
void Boiler::process_HpAdditionalHeater(std::shared_ptr<const Telegram> telegram) {
|
void Boiler::process_HpAdditionalHeater(std::shared_ptr<const Telegram> telegram) {
|
||||||
has_update(telegram, auxHeaterSource_, 0); // https://github.com/emsesp/EMS-ESP32/discussions/2489
|
has_update(telegram, auxHeaterSource_, 0); // https://github.com/emsesp/EMS-ESP32/discussions/2489
|
||||||
has_update(telegram, auxHeaterOnly_, 1);
|
has_update(telegram, auxHeaterOnly_, model() == EMSdevice::EMS_DEVICE_FLAG_CS6800 ? 3 : 1);
|
||||||
has_update(telegram, auxHeaterOff_, 2);
|
has_update(telegram, auxHeaterOff_, 2);
|
||||||
has_update(telegram, auxHeatMode_, 4); // eco/comfort
|
has_update(telegram, auxHeatMode_, 4); // eco/comfort
|
||||||
has_update(telegram, tempParMode_, 5);
|
has_update(telegram, tempParMode_, 5);
|
||||||
@@ -3061,9 +3091,21 @@ bool Boiler::set_HpInLogic(const char * value, const int8_t id) {
|
|||||||
|
|
||||||
bool Boiler::set_maxHeat(const char * value, const int8_t id) {
|
bool Boiler::set_maxHeat(const char * value, const int8_t id) {
|
||||||
uint8_t v;
|
uint8_t v;
|
||||||
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_CS6800) {
|
||||||
|
if (id == 0) {
|
||||||
|
if (!Helpers::value2enum(value, v, FL_(enum_maxHeat1), {0, 2, 4, 5})) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!Helpers::value2enum(value, v, FL_(enum_maxHeat2), {2, 4, 5})) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!Helpers::value2enum(value, v, FL_(enum_maxHeat))) {
|
if (!Helpers::value2enum(value, v, FL_(enum_maxHeat))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
write_command(0x492, id, v, 0x492);
|
write_command(0x492, id, v, 0x492);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3107,7 +3149,7 @@ bool Boiler::set_minTempSilent(const char * value, const int8_t id) {
|
|||||||
bool Boiler::set_additionalHeaterOnly(const char * value, const int8_t id) {
|
bool Boiler::set_additionalHeaterOnly(const char * value, const int8_t id) {
|
||||||
bool v;
|
bool v;
|
||||||
if (Helpers::value2bool(value, v)) {
|
if (Helpers::value2bool(value, v)) {
|
||||||
write_command(0x491, 1, v ? 1 : 0, 0x491);
|
write_command(0x491, model() == EMSdevice::EMS_DEVICE_FLAG_CS6800 ? 3 : 1, v ? 1 : 0, 0x491);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ class Boiler : public EMSdevice {
|
|||||||
inline uint8_t model() const {
|
inline uint8_t model() const {
|
||||||
return (flags() & 0x0F);
|
return (flags() & 0x0F);
|
||||||
}
|
}
|
||||||
|
inline bool isHeatPump() const {
|
||||||
|
return flags() & 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
void check_active();
|
void check_active();
|
||||||
void store_energy();
|
void store_energy();
|
||||||
@@ -45,6 +48,7 @@ class Boiler : public EMSdevice {
|
|||||||
static constexpr uint8_t EMS_TYPE_UBAFunctionTest = 0x1D;
|
static constexpr uint8_t EMS_TYPE_UBAFunctionTest = 0x1D;
|
||||||
static constexpr uint8_t EMS_TYPE_UBAFlags = 0x35;
|
static constexpr uint8_t EMS_TYPE_UBAFlags = 0x35;
|
||||||
static constexpr uint8_t EMS_TYPE_UBASetPoints = 0x1A;
|
static constexpr uint8_t EMS_TYPE_UBASetPoints = 0x1A;
|
||||||
|
static constexpr uint16_t EMS_TYPE_UBASetPoints2 = 0x2E0;
|
||||||
static constexpr uint8_t EMS_TYPE_UBAParameters = 0x16;
|
static constexpr uint8_t EMS_TYPE_UBAParameters = 0x16;
|
||||||
static constexpr uint8_t EMS_TYPE_UBAParametersPlus = 0xE6;
|
static constexpr uint8_t EMS_TYPE_UBAParametersPlus = 0xE6;
|
||||||
static constexpr uint8_t EMS_TYPE_UBAParameterWWPlus = 0xEA;
|
static constexpr uint8_t EMS_TYPE_UBAParameterWWPlus = 0xEA;
|
||||||
|
|||||||
@@ -1275,30 +1275,14 @@ void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_update(telegram, dhw->wwCircPump_, 1); // FF=off, 0=on ?
|
has_update(telegram, dhw->wwCircPump_, 1); // FF=off, 0=on ?
|
||||||
|
|
||||||
if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
|
if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
|
||||||
const uint8_t modes[] = {0, 5, 1, 2, 4}; // off, eco+, eco, comfort, auto
|
has_enumupdate(telegram, dhw->wwMode_, 2, {0, 5, 1, 2, 4}, {0, 2, 3, 0, 4, 1});
|
||||||
uint8_t wwmode = dhw->wwMode_ < sizeof(modes) ? modes[dhw->wwMode_] : EMS_VALUE_UINT8_NOTSET;
|
|
||||||
telegram->read_value(wwmode, 2);
|
|
||||||
const uint8_t modes1[] = {0, 2, 3, 0, 4, 1};
|
|
||||||
has_update(dhw->wwMode_, wwmode < sizeof(modes1) ? modes1[wwmode] : EMS_VALUE_UINT8_NOTSET);
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) {
|
||||||
// https://github.com/emsesp/EMS-ESP32/pull/1722#discussion_r1582823521
|
// https://github.com/emsesp/EMS-ESP32/pull/1722#discussion_r1582823521
|
||||||
const uint8_t modes[] = {1, 2, 5}; // normal, comfort, eco+
|
has_enumupdate(telegram, dhw->wwMode_, 2, {1, 2, 5}, {0, 0, 1, 0, 0, 2}); // normal, comfort, eco+
|
||||||
uint8_t wwmode = dhw->wwMode_ < sizeof(modes) ? modes[dhw->wwMode_] : EMS_VALUE_UINT8_NOTSET;
|
|
||||||
telegram->read_value(wwmode, 2);
|
|
||||||
const uint8_t modes1[] = {0, 0, 1, 0, 0, 2}; // 0=normal (1), 1=comfort(2), 2=eco+(5)
|
|
||||||
has_update(dhw->wwMode_, wwmode < sizeof(modes1) ? modes1[wwmode] : EMS_VALUE_UINT8_NOTSET);
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_CR120) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_CR120) {
|
||||||
const uint8_t modes[] = {1, 2, 4}; //// 0=normal (1), 1=comfort(2), 2=auto(4)
|
has_enumupdate(telegram, dhw->wwMode_, 2, {1, 2, 4}, {0, 0, 1, 0, 2, 0}); // normal, comfort, auto
|
||||||
uint8_t wwmode = dhw->wwMode_ < sizeof(modes) ? modes[dhw->wwMode_] : EMS_VALUE_UINT8_NOTSET;
|
|
||||||
telegram->read_value(wwmode, 2);
|
|
||||||
const uint8_t modes1[] = {0, 0, 1, 0, 2, 0};
|
|
||||||
has_update(dhw->wwMode_, wwmode < sizeof(modes1) ? modes1[wwmode] : EMS_VALUE_UINT8_NOTSET);
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC100) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC100) {
|
||||||
const uint8_t modes[] = {0, 2, 3}; //// 0=off(0), 1=on(2), 2=auto(3)
|
has_enumupdate(telegram, dhw->wwMode_, 2, {0, 2, 3}, {0, 0, 1, 2, 0, 0}); // normal, on, auto
|
||||||
uint8_t wwmode = dhw->wwMode_ < sizeof(modes) ? modes[dhw->wwMode_] : EMS_VALUE_UINT8_NOTSET;
|
|
||||||
telegram->read_value(wwmode, 2);
|
|
||||||
const uint8_t modes1[] = {0, 0, 1, 2, 0, 0};
|
|
||||||
has_update(dhw->wwMode_, wwmode < sizeof(modes1) ? modes1[wwmode] : EMS_VALUE_UINT8_NOTSET);
|
|
||||||
} else {
|
} else {
|
||||||
has_update(telegram, dhw->wwMode_, 2); // 0=off, 1=low, 2=high, 3=auto, 4=own prog
|
has_update(telegram, dhw->wwMode_, 2); // 0=off, 1=low, 2=high, 3=auto, 4=own prog
|
||||||
}
|
}
|
||||||
@@ -2294,29 +2278,25 @@ bool Thermostat::set_wwmode(const char * value, const int8_t id) {
|
|||||||
}
|
}
|
||||||
write_command(0xB0, 2, set, 0xB0);
|
write_command(0xB0, 2, set, 0xB0);
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_BC400 || model() == EMSdevice::EMS_DEVICE_FLAG_HMC310) {
|
||||||
if (!Helpers::value2enum(value, set, FL_(enum_wwMode4))) { // off, eco+, eco, comfort, auto
|
if (!Helpers::value2enum(value, set, FL_(enum_wwMode4), {0, 5, 1, 2, 4})) { // off, eco+, eco, comfort, auto
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint8_t modes[] = {0, 5, 1, 2, 4};
|
write_command(0x02F5 + dhw->offset(), 2, set, 0x02F5 + dhw->offset());
|
||||||
write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset());
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_CR120) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_CR120) {
|
||||||
if (!Helpers::value2enum(value, set, FL_(enum_wwMode6))) { // normal, comfort, auto
|
if (!Helpers::value2enum(value, set, FL_(enum_wwMode6), {0, 2, 4})) { // normal, comfort, auto
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint8_t modes[] = {0, 2, 4};
|
write_command(0x02F5 + dhw->offset(), 2, set, 0x02F5 + dhw->offset());
|
||||||
write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset());
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC100) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC100) {
|
||||||
if (!Helpers::value2enum(value, set, FL_(enum_wwMode2))) { // off, on, auto
|
if (!Helpers::value2enum(value, set, FL_(enum_wwMode2), {0, 2, 3})) { // off, on, auto
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint8_t modes[] = {0, 2, 3};
|
write_command(0x02F5 + dhw->offset(), 2, set, 0x02F5 + dhw->offset());
|
||||||
write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset());
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) { // Rego3000 - https://github.com/emsesp/EMS-ESP32/issues/1692
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_R3000) { // Rego3000 - https://github.com/emsesp/EMS-ESP32/issues/1692
|
||||||
if (!Helpers::value2enum(value, set, FL_(enum_wwMode5))) {
|
if (!Helpers::value2enum(value, set, FL_(enum_wwMode5), {1, 2, 5})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint8_t modes[] = {1, 2, 5};
|
write_command(0x02F5 + dhw->offset(), 2, set, 0x02F5 + dhw->offset());
|
||||||
write_command(0x02F5 + dhw->offset(), 2, modes[set], 0x02F5 + dhw->offset());
|
|
||||||
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC300) {
|
} else if (model() == EMSdevice::EMS_DEVICE_FLAG_RC300) {
|
||||||
if (!Helpers::value2enum(value, set, FL_(enum_wwMode))) {
|
if (!Helpers::value2enum(value, set, FL_(enum_wwMode))) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.7.3-dev.10"
|
#define EMSESP_APP_VERSION "3.7.3-dev.11"
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject root) {
|
|||||||
ei["uom"] = entityItem.value_type == DeviceValueType::BOOL ? 0 : entityItem.uom;
|
ei["uom"] = entityItem.value_type == DeviceValueType::BOOL ? 0 : entityItem.uom;
|
||||||
ei["value_type"] = entityItem.value_type;
|
ei["value_type"] = entityItem.value_type;
|
||||||
ei["writeable"] = entityItem.writeable;
|
ei["writeable"] = entityItem.writeable;
|
||||||
|
ei["hide"] = entityItem.hide;
|
||||||
EMSESP::webCustomEntityService.render_value(ei, entityItem, true, true);
|
EMSESP::webCustomEntityService.render_value(ei, entityItem, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +95,7 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
|
|||||||
entityItem.uom = ei["uom"];
|
entityItem.uom = ei["uom"];
|
||||||
entityItem.value_type = ei["value_type"];
|
entityItem.value_type = ei["value_type"];
|
||||||
entityItem.writeable = ei["writeable"];
|
entityItem.writeable = ei["writeable"];
|
||||||
|
entityItem.hide = ei["hide"] | false;
|
||||||
entityItem.data = ei["value"].as<std::string>();
|
entityItem.data = ei["value"].as<std::string>();
|
||||||
if (entityItem.ram == 1) {
|
if (entityItem.ram == 1) {
|
||||||
entityItem.device_id = 0;
|
entityItem.device_id = 0;
|
||||||
@@ -295,8 +297,10 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd)
|
|||||||
if (!strlen(cmd) || !strcmp(cmd, F_(values)) || !strcmp(cmd, F_(info))) {
|
if (!strlen(cmd) || !strcmp(cmd, F_(values)) || !strcmp(cmd, F_(info))) {
|
||||||
// list all names
|
// list all names
|
||||||
for (CustomEntityItem & entity : *customEntityItems_) {
|
for (CustomEntityItem & entity : *customEntityItems_) {
|
||||||
|
if (!entity.hide) {
|
||||||
render_value(output, entity);
|
render_value(output, entity);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +350,7 @@ void WebCustomEntityService::get_value_json(JsonObject output, CustomEntityItem
|
|||||||
|
|
||||||
// publish single value
|
// publish single value
|
||||||
void WebCustomEntityService::publish_single(CustomEntityItem & entity) {
|
void WebCustomEntityService::publish_single(CustomEntityItem & entity) {
|
||||||
if (!Mqtt::enabled() || !Mqtt::publish_single()) {
|
if (!Mqtt::enabled() || !Mqtt::publish_single() || entity.hide) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +391,9 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
bool ha_created = ha_registered_;
|
bool ha_created = ha_registered_;
|
||||||
|
|
||||||
for (CustomEntityItem & entityItem : *customEntityItems_) {
|
for (CustomEntityItem & entityItem : *customEntityItems_) {
|
||||||
|
if (entityItem.hide) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
render_value(output, entityItem);
|
render_value(output, entityItem);
|
||||||
// create HA config
|
// create HA config
|
||||||
if (Mqtt::ha_enabled() && !ha_registered_) {
|
if (Mqtt::ha_enabled() && !ha_registered_) {
|
||||||
@@ -445,6 +452,9 @@ void WebCustomEntityService::publish(const bool force) {
|
|||||||
|
|
||||||
Mqtt::add_ha_sections_to_doc(F_(custom), stat_t, config, !ha_created, val_cond);
|
Mqtt::add_ha_sections_to_doc(F_(custom), stat_t, config, !ha_created, val_cond);
|
||||||
|
|
||||||
|
if (Mqtt::ha_optimistic()) {
|
||||||
|
config["optimistic"] = true;
|
||||||
|
}
|
||||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,7 +480,7 @@ uint8_t WebCustomEntityService::count_entities() {
|
|||||||
|
|
||||||
for (CustomEntityItem & entity : *customEntityItems_) {
|
for (CustomEntityItem & entity : *customEntityItems_) {
|
||||||
render_value(output, entity);
|
render_value(output, entity);
|
||||||
if (output[entity.name].is<JsonVariantConst>() || entity.writeable) {
|
if (!entity.hide && (output[entity.name].is<JsonVariantConst>() || entity.writeable)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -484,6 +494,9 @@ void WebCustomEntityService::generate_value_web(JsonObject output, const bool is
|
|||||||
uint8_t index = 0;
|
uint8_t index = 0;
|
||||||
|
|
||||||
for (const CustomEntityItem & entity : *customEntityItems_) {
|
for (const CustomEntityItem & entity : *customEntityItems_) {
|
||||||
|
if (entity.hide) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
bool include = false;
|
bool include = false;
|
||||||
JsonObject root_obj = nodes.add<JsonObject>(); // create the object, we know there is a value
|
JsonObject root_obj = nodes.add<JsonObject>(); // create the object, we know there is a value
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ class CustomEntityItem {
|
|||||||
std::string data;
|
std::string data;
|
||||||
uint8_t ram;
|
uint8_t ram;
|
||||||
uint8_t * raw;
|
uint8_t * raw;
|
||||||
|
bool hide;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebCustomEntity {
|
class WebCustomEntity {
|
||||||
|
|||||||
@@ -154,8 +154,6 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * attribute_s = Command::get_attribute(cmd);
|
|
||||||
|
|
||||||
if (!strcmp(cmd, F_(entities))) {
|
if (!strcmp(cmd, F_(entities))) {
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
char name[30];
|
char name[30];
|
||||||
@@ -166,6 +164,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char * attribute_s = Command::get_attribute(cmd);
|
||||||
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
for (const ScheduleItem & scheduleItem : *scheduleItems_) {
|
||||||
if (Helpers::toLower(scheduleItem.name) == cmd) {
|
if (Helpers::toLower(scheduleItem.name) == cmd) {
|
||||||
get_value_json(output, scheduleItem);
|
get_value_json(output, scheduleItem);
|
||||||
@@ -291,6 +290,9 @@ void WebSchedulerService::publish(const bool force) {
|
|||||||
Mqtt::add_ha_bool(config);
|
Mqtt::add_ha_bool(config);
|
||||||
Mqtt::add_ha_sections_to_doc(F_(scheduler), stat_t, config, !ha_created, val_cond);
|
Mqtt::add_ha_sections_to_doc(F_(scheduler), stat_t, config, !ha_created, val_cond);
|
||||||
|
|
||||||
|
if (Mqtt::ha_optimistic()) {
|
||||||
|
config["optimistic"] = true;
|
||||||
|
}
|
||||||
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
ha_created |= Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user