Merge pull request #1176 from MichaelDvP/dev

AM20, HIU, Ventilation and other
This commit is contained in:
Proddy
2023-05-27 08:39:48 +02:00
committed by GitHub
18 changed files with 468 additions and 196 deletions

View File

@@ -41,6 +41,10 @@ jobs:
run: |
platformio run -e ci
- name: Build S3 firmware
run: |
platformio run -e ci_s3
- name: Create a GH Release
id: 'automatic_releases'
uses: 'marvinpinto/action-automatic-releases@latest'

View File

@@ -17,6 +17,11 @@ There are breaking changes in 3.6.0. Please read carefully before applying the u
- Some more HM200 entities [#500](https://github.com/emsesp/EMS-ESP32/issues/500)
- Custom Scheduler [#701](https://github.com/emsesp/EMS-ESP32/issues/701)
- Custom Entities read from EMS bus
- Build S3 binary with github actions
- Greenstar HIU [#1158](https://github.com/emsesp/EMS-ESP32/issues/1158)
- AM200 code 10 [#1161](https://github.com/emsesp/EMS-ESP32/issues/1161)
- Ventilation device [#1172](https://github.com/emsesp/EMS-ESP32/issues/1172)
- Turn ETH off on wifi connect [#1167](https://github.com/emsesp/EMS-ESP32/issues/1167)
## Fixed
@@ -26,7 +31,7 @@ There are breaking changes in 3.6.0. Please read carefully before applying the u
## Changed
- Optional upgrade to platform-espressif32 6.1.0 (after 5.3.0) [#862](https://github.com/emsesp/EMS-ESP32/issues/862)
- Optional upgrade to platform-espressif32 6.3.0 (after 5.3.0) [#862](https://github.com/emsesp/EMS-ESP32/issues/862)
- Use byte 3 for detection RC30 active heatingcircuit [#786](https://github.com/emsesp/EMS-ESP32/issues/786)
- Write repeated selflowtemp if tx-queue is empty without verify [#954](https://github.com/emsesp/EMS-ESP32/issues/954)
- HA discovery recreate after disconnect by device [#1067](https://github.com/emsesp/EMS-ESP32/issues/1067)

View File

@@ -71,6 +71,18 @@ board_build.filesystem = littlefs
build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
; for github Actions actually standard platform is buggy, use dev-platform
[env:ci_s3]
platform = https://github.com/platformio/platform-espressif32.git
framework = arduino
extra_scripts = scripts/rename_fw.py
board = lolin_s3
board_build.f_cpu = 240000000L
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
build_flags = ${common.build_flags} -O2
build_unflags = ${common.unbuild_flags}
[env:esp32_4M]
platform = espressif32@5.2.0
framework = arduino

View File

@@ -48,7 +48,7 @@
{208, DeviceType::BOILER, "Logamax Plus/GB192/Condens GC9000/Greenstar ErP", DeviceFlags::EMS_DEVICE_FLAG_NONE},
{210, DeviceType::BOILER, "Cascade MC400", DeviceFlags::EMS_DEVICE_FLAG_NONE},
{211, DeviceType::BOILER, "EasyControl Adapter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
{219, DeviceType::BOILER, "Greenstar HIU", DeviceFlags::EMS_DEVICE_FLAG_NONE},
{219, DeviceType::BOILER, "Greenstar HIU", DeviceFlags::EMS_DEVICE_FLAG_HIU},
{234, DeviceType::BOILER, "Logamax Plus GB122/Condense 2300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Controllers - 0x09 / 0x10 / 0x50
@@ -97,6 +97,7 @@
{158, DeviceType::THERMOSTAT, "RC300/RC310/Moduline 3000/1010H/CW400/Sense II/HPC410", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
{165, DeviceType::THERMOSTAT, "RC100/Moduline 1000/1010", DeviceFlags::EMS_DEVICE_FLAG_RC100}, // 0x18, 0x38
{172, DeviceType::THERMOSTAT, "Rego 2000/3000", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
{215, DeviceType::THERMOSTAT, "Comfort RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
{216, DeviceType::THERMOSTAT, "CRF200S", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
{246, DeviceType::THERMOSTAT, "Comfort+2RF", DeviceFlags::EMS_DEVICE_FLAG_CRF | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE}, // 0x18
{253, DeviceType::THERMOSTAT, "Rego 3000/UI800", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10
@@ -149,6 +150,9 @@
// Heat Pumps - 0x53
{248, DeviceType::HEATPUMP, "Hybrid Manager HM200", DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Ventilation - 0x51
{231, DeviceType::VENTILATION, "Logavent HRV176", DeviceFlags::EMS_DEVICE_FLAG_NONE},
// Heatsource - 0x60
{228, DeviceType::HEATSOURCE, "AM200", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // alternative heatsource

View File

@@ -86,6 +86,26 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
register_telegram_type(0x49D, "HPSettings3", true, MAKE_PF_CB(process_HpSettings3));
}
if (model() == EMSdevice::EMS_DEVICE_FLAG_HIU) {
register_telegram_type(0x772, "HIUSettings", false, MAKE_PF_CB(process_HIUSettings));
register_telegram_type(0x779, "HIUMonitor", false, MAKE_PF_CB(process_HIUMonitor));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&keepWarmTemp_,
DeviceValueType::UINT,
FL_(keepWarmTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_keepWarmTemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&setReturnTemp_,
DeviceValueType::UINT,
FL_(setReturnTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_returnTemp));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cwFlowRate_, DeviceValueType::USHORT, FL_(cwFlowRate), DeviceValueUOM::LMIN);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &netFlowTemp_, DeviceValueType::USHORT, FL_(netFlowTemp), DeviceValueUOM::DEGREES);
}
/*
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
* thermostat always overwrites settings in boiler
@@ -1291,28 +1311,36 @@ void Boiler::process_HpInput(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, hpInput[3].state, 5);
}
// Heatpump inputs settings- type 0x486
// Heatpump inputs settings- type 0x486 (https://github.com/emsesp/EMS-ESP32/issues/600)
// Boiler(0x08) -> All(0x00), ?(0x0486), data: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// Boiler(0x08) -> All(0x00), ?(0x0486), data: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00 00 00 00 (offset 25)
// Boiler(0x08) -> All(0x00), ?(0x0486), data: 00 00 (offset 51)
void Boiler::process_HpInConfig(std::shared_ptr<const Telegram> telegram) {
char option[12];
for (uint8_t i = 0; i < 2; i++) {
for (uint8_t j = 0; j < 11; j++) {
char option[16];
// inputs 1,2,3 <inv>[<evu1><evu2><evu3><comp><aux><cool><heat><dhw><pv><prot><pres><mod>]
uint8_t index[] = {0, 3, 6, 9, 12, 15, 18, 21, 24, 39, 36, 30, 27};
for (uint8_t i = 0; i < 3; i++) {
for (uint8_t j = 0; j < 12; j++) {
option[j] = hpInput[i].option[j] - '0';
telegram->read_value(option[j], j * 4 + i);
option[j] = option[j] ? '1' : '0';
telegram->read_value(option[j], index[j] + i);
option[j] = option[j] == 1 ? '1' : '0';
}
option[11] = '\0'; // terminate string
has_update(hpInput[i].option, option, 12);
option[12] = atoi(&hpInput[i].option[12]);
telegram->read_value(option[12], 27 + i); // modulation
Helpers::smallitoa(&option[12], (uint16_t)option[12]);
has_update(hpInput[i].option, option, 16);
}
// input 4 <inv>[<comp><aux><cool><heat><dhw><pv><prot><pres><mod>]
uint8_t index4[] = {42, 43, 44, 45, 46, 47, 52, 50, 49, 48};
for (uint8_t j = 0; j < 9; j++) {
option[j] = hpInput[3].option[j] - '0';
telegram->read_value(option[j], 42 + j);
option[j] = option[j] ? '1' : '0';
telegram->read_value(option[j], index4[j]);
option[j] = option[j] == 1 ? '1' : '0';
}
option[9] = '\0'; // terminate string
has_update(hpInput[3].option, option, 12);
option[9] = atoi(&hpInput[3].option[9]);
telegram->read_value(option[9], 48); // modulation
Helpers::smallitoa(&option[9], (uint16_t)option[9]);
has_update(hpInput[3].option, option, 13);
}
// Boiler(0x08) -W-> Me(0x0B), HpHeaterConfig(0x0485)
@@ -1562,6 +1590,39 @@ void Boiler::process_HpSettings3(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, elHeatStep3_, 9);
}
// HIU unit
// boiler(0x08) -B-> All(0x00), ?(0x0779), data: 06 05 01 01 AD 02 EF FF FF 00 00 7F FF
void Boiler::process_HIUMonitor(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, netFlowTemp_, 5); // is * 10
has_update(telegram, cwFlowRate_, 9); // is * 10
}
// Boiler(0x08) -W-> ME(0x0x), ?(0x0772), data: 00 00 00 00 00
void Boiler::process_HIUSettings(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, keepWarmTemp_, 1);
has_update(telegram, setReturnTemp_, 2);
}
// HIU Settings
bool Boiler::set_keepWarmTemp(const char * value, const int8_t id) {
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x772, 1, v, 0x772);
return true;
}
bool Boiler::set_returnTemp(const char * value, const int8_t id) {
int v;
if (!Helpers::value2temperature(value, v)) {
return false;
}
write_command(0x772, 2, v, 0x772);
return true;
}
/*
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
* thermostat always overwrites settings in boiler
@@ -2303,38 +2364,41 @@ bool Boiler::set_emergency_ops(const char * value, const int8_t id) {
}
bool Boiler::set_HpInLogic(const char * value, const int8_t id) {
if (id == 0 || id > 4) {
if (id == 0 || id > 4 || strlen(value) > 15) {
return false;
}
bool v;
if (Helpers::value2bool(value, v)) {
if (strlen(value) == 1 && Helpers::value2bool(value, v)) {
write_command(0x486, id == 4 ? 42 : id - 1, v ? 1 : 0, 0x486);
return true;
}
if (strlen(value) == 11 && id != 4) {
uint8_t v[11];
for (uint8_t i = 0; i < 11; i++) {
v[i] = value[i] - '0';
if (v[i] > 1) {
return false;
char option[] = {"xxxxxxxxxxxxxxx"};
strncpy(option, value, strlen(value)); // copy without termination
// inputs 1,2,3 <inv>[<evu1><evu2><evu3><comp><aux><cool><heat><dhw><pv><prot><pres><mod>]
if (id < 4) {
uint8_t index[] = {0, 3, 6, 9, 12, 15, 18, 21, 24, 39, 36, 30};
for (uint8_t i = 0; i < 12; i++) {
if (option[i] == '0' || option[i] == '1') {
write_command(0x486, index[i] + id - 1, option[i] - '0');
}
write_command(0x486, i * 3 + id - 1, v[i]);
}
if (option[12] >= '0' && option[12] <= '9') {
write_command(0x486, 27, (uint8_t)atoi(&option[12]));
}
return true;
}
// input 4
if (strlen(value) == 8 && id == 4) {
uint8_t v[11];
for (uint8_t i = 0; i < 8; i++) {
v[i] = value[i] - '0';
if (v[i] > 1) {
return false;
}
write_command(0x486, 42 + i, v[i]);
// input 4: <inv>[<comp><aux><cool><heat><dhw><pv><prot><pres><mod>]
uint8_t index4[] = {42, 43, 44, 45, 46, 47, 52, 50, 49};
for (uint8_t i = 0; i < 9; i++) {
if (option[i] == '0' || option[i] == '1') {
write_command(0x486, index4[i], option[i] - '0');
}
return true;
}
return false;
if (option[9] >= '0' && option[9] <= '9') {
write_command(0x486, 48, (uint8_t)atoi(&option[9]));
}
return true;
}
bool Boiler::set_maxHeat(const char * value, const int8_t id) {

View File

@@ -208,7 +208,7 @@ class Boiler : public EMSdevice {
// Inputs
struct {
uint8_t state;
char option[12]; // logic, block_comp, block_dhw, block_heat, block_cool, overheat_protect, evu_blocktime1,2,3, block_heater, Solar
char option[16]; // logic, block_comp, block_dhw, block_heat, block_cool, overheat_protect, evu_blocktime1,2,3, block_heater, Solar, brine lowpressure, brine pump modulation
} hpInput[4];
// Heater limits
@@ -252,6 +252,12 @@ class Boiler : public EMSdevice {
uint8_t elHeatStep2_;
uint8_t elHeatStep3_;
// HIU
uint16_t cwFlowRate_; // cold water flow rate *10
uint16_t netFlowTemp_; // heat network flow temperature *10
uint8_t keepWarmTemp_;
uint8_t setReturnTemp_;
/*
// Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
// thermostat always overwrites settings in boiler
@@ -306,6 +312,12 @@ class Boiler : public EMSdevice {
void process_HpDhwSettings(std::shared_ptr<const Telegram> telegram);
void process_HpSettings2(std::shared_ptr<const Telegram> telegram);
void process_HpSettings3(std::shared_ptr<const Telegram> telegram);
// HIU
void process_HIUSettings(std::shared_ptr<const Telegram> telegram);
void process_HIUMonitor(std::shared_ptr<const Telegram> telegram);
bool set_keepWarmTemp(const char * value, const int8_t id);
bool set_returnTemp(const char * value, const int8_t id);
// commands - none of these use the additional id parameter
bool set_ww_mode(const char * value, const int8_t id);

View File

@@ -24,155 +24,54 @@ REGISTER_FACTORY(Heatsource, EMSdevice::DeviceType::HEATSOURCE);
Heatsource::Heatsource(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
if (device_id >= EMSdevice::EMS_DEVICE_ID_AHS1 && device_id < EMSdevice::EMS_DEVICE_ID_HS1) {
uint8_t ahs = device_id - EMSdevice::EMS_DEVICE_ID_AHS1; // heating source id, count from 0
// AM200 alternative heatsource
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER || (device_id >= EMSdevice::EMS_DEVICE_ID_AHS1 && device_id < EMSdevice::EMS_DEVICE_ID_HS1)) {
uint8_t tag = device_id == EMSdevice::EMS_DEVICE_ID_BOILER
? DeviceValueTAG::TAG_DEVICE_DATA
: DeviceValueTAG::TAG_AHS1 + device_id - EMSdevice::EMS_DEVICE_ID_AHS1; // heating source id, count from 0
register_telegram_type(0x54D, "AmTemperatures", false, MAKE_PF_CB(process_amTempMessage));
register_telegram_type(0x54E, "AmStatus", false, MAKE_PF_CB(process_amStatusMessage));
register_telegram_type(0x54F, "AmCommand", false, MAKE_PF_CB(process_amCommandMessage)); // not broadcasted, but actually not used
register_telegram_type(0x550, "AmExtra", false, MAKE_PF_CB(process_amExtraMessage));
register_telegram_type(0x54C, "AmSettings", true, MAKE_PF_CB(process_amSettingMessage)); // not broadcasted
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&curFlowTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(sysFlowTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&retTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(sysRetTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&aFlowTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(aFlowTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&aRetTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(aRetTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&cylTopTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(aCylTopTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&cylCenterTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(aCylCenterTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&cylBottomTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(aCylBottomTemp),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&flueGasTemp_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(flueGasTemp),
DeviceValueUOM::DEGREES);
// register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &valveByPass_, DeviceValueType::BOOL, nullptr, FL_(valveByPass), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &valveBuffer_, DeviceValueType::UINT, FL_(valveBuffer), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &valveReturn_, DeviceValueType::UINT, FL_(valveReturn), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &aPumpMod_, DeviceValueType::UINT, FL_(aPumpMod), DeviceValueUOM::PERCENT);
// register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &heatSource_, DeviceValueType::BOOL, nullptr, FL_(heatSource), DeviceValueUOM::NONE);
register_device_value(tag, &curFlowTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(sysFlowTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &retTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(sysRetTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &aFlowTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(aFlowTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &aRetTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(aRetTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &cylTopTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(aCylTopTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &cylCenterTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(aCylCenterTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &cylBottomTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(aCylBottomTemp), DeviceValueUOM::DEGREES);
register_device_value(tag, &flueGasTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flueGasTemp), DeviceValueUOM::DEGREES);
// register_device_value(tag, &valveByPass_, DeviceValueType::BOOL, nullptr, FL_(valveByPass), DeviceValueUOM::NONE);
register_device_value(tag, &valveBuffer_, DeviceValueType::UINT, FL_(valveBuffer), DeviceValueUOM::PERCENT);
register_device_value(tag, &valveReturn_, DeviceValueType::UINT, FL_(valveReturn), DeviceValueUOM::PERCENT);
register_device_value(tag, &aPumpMod_, DeviceValueType::UINT, FL_(aPumpMod), DeviceValueUOM::PERCENT);
// register_device_value(tag, &heatSource_, DeviceValueType::BOOL, nullptr, FL_(heatSource), DeviceValueUOM::NONE);
// Settings:
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&vr2Config_,
DeviceValueType::ENUM,
FL_(enum_vr2Config),
FL_(vr2Config),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_vr2Config));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&ahsActivated_,
DeviceValueType::BOOL,
FL_(ahsActivated),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_ahsActivated));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&aPumpConfig_,
DeviceValueType::BOOL,
FL_(aPumpConfig),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_aPumpConfig));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&aPumpSignal_,
DeviceValueType::ENUM,
FL_(enum_aPumpSignal),
FL_(aPumpSignal),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_aPumpSignal));
register_device_value(
DeviceValueTAG::TAG_AHS1 + ahs, &aPumpMin_, DeviceValueType::UINT, FL_(aPumpMin), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_aPumpMin), 12, 50);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &tempRise_, DeviceValueType::BOOL, FL_(tempRise), DeviceValueUOM::NONE, MAKE_CF_CB(set_tempRise));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&setReturnTemp_,
DeviceValueType::UINT,
FL_(setReturnTemp),
DeviceValueUOM::DEGREES,
MAKE_CF_CB(set_setReturnTemp),
40,
75);
register_device_value(
DeviceValueTAG::TAG_AHS1 + ahs, &mixRuntime_, DeviceValueType::USHORT, FL_(mixRuntime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_mixRuntime), 0, 600);
register_device_value(
DeviceValueTAG::TAG_AHS1 + ahs, &setFlowTemp_, DeviceValueType::UINT, FL_(setFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_setFlowTemp), 40, 75);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&bufBypass_,
DeviceValueType::ENUM,
FL_(enum_bufBypass),
FL_(bufBypass),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_bufBypass));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&bufMixRuntime_,
DeviceValueType::USHORT,
FL_(bufMixRuntime),
DeviceValueUOM::SECONDS,
MAKE_CF_CB(set_bufMixRuntime),
0,
600);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&bufConfig_,
DeviceValueType::ENUM,
FL_(enum_bufConfig),
FL_(bufConfig),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_bufConfig));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&blockMode_,
DeviceValueType::ENUM,
FL_(enum_blockMode),
FL_(blockMode),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_blockMode));
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs,
&blockTerm_,
DeviceValueType::ENUM,
FL_(enum_blockTerm),
FL_(blockTerm),
DeviceValueUOM::NONE,
MAKE_CF_CB(set_blockTerm));
register_device_value(
DeviceValueTAG::TAG_AHS1 + ahs, &blockHyst_, DeviceValueType::INT, FL_(blockHyst), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_blockHyst), 0, 50);
register_device_value(
DeviceValueTAG::TAG_AHS1 + ahs, &releaseWait_, DeviceValueType::UINT, FL_(releaseWait), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_releaseWait), 0, 240);
register_device_value(tag, &vr2Config_, DeviceValueType::ENUM, FL_(enum_vr2Config), FL_(vr2Config), DeviceValueUOM::NONE, MAKE_CF_CB(set_vr2Config));
register_device_value(tag, &ahsActivated_, DeviceValueType::BOOL, FL_(ahsActivated), DeviceValueUOM::NONE, MAKE_CF_CB(set_ahsActivated));
register_device_value(tag, &aPumpConfig_, DeviceValueType::BOOL, FL_(aPumpConfig), DeviceValueUOM::NONE, MAKE_CF_CB(set_aPumpConfig));
register_device_value(tag, &aPumpSignal_, DeviceValueType::ENUM, FL_(enum_aPumpSignal), FL_(aPumpSignal), DeviceValueUOM::NONE, MAKE_CF_CB(set_aPumpSignal));
register_device_value(tag, &aPumpMin_, DeviceValueType::UINT, FL_(aPumpMin), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_aPumpMin), 12, 50);
register_device_value(tag, &tempRise_, DeviceValueType::BOOL, FL_(tempRise), DeviceValueUOM::NONE, MAKE_CF_CB(set_tempRise));
register_device_value(tag, &setReturnTemp_, DeviceValueType::UINT, FL_(setReturnTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_setReturnTemp), 40, 75);
register_device_value(tag, &mixRuntime_, DeviceValueType::USHORT, FL_(mixRuntime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_mixRuntime), 0, 600);
register_device_value(tag, &setFlowTemp_, DeviceValueType::UINT, FL_(setFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_setFlowTemp), 40, 75);
register_device_value(tag, &bufBypass_, DeviceValueType::ENUM, FL_(enum_bufBypass), FL_(bufBypass), DeviceValueUOM::NONE, MAKE_CF_CB(set_bufBypass));
register_device_value(tag, &bufMixRuntime_, DeviceValueType::USHORT, FL_(bufMixRuntime), DeviceValueUOM::SECONDS, MAKE_CF_CB(set_bufMixRuntime), 0, 600);
register_device_value(tag, &bufConfig_, DeviceValueType::ENUM, FL_(enum_bufConfig), FL_(bufConfig), DeviceValueUOM::NONE, MAKE_CF_CB(set_bufConfig));
register_device_value(tag, &blockMode_, DeviceValueType::ENUM, FL_(enum_blockMode), FL_(blockMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_blockMode));
register_device_value(tag, &blockTerm_, DeviceValueType::ENUM, FL_(enum_blockTerm), FL_(blockTerm), DeviceValueUOM::NONE, MAKE_CF_CB(set_blockTerm));
register_device_value(tag, &blockHyst_, DeviceValueType::INT, FL_(blockHyst), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_blockHyst), 0, 50);
register_device_value(tag, &releaseWait_, DeviceValueType::UINT, FL_(releaseWait), DeviceValueUOM::MINUTES, MAKE_CF_CB(set_releaseWait), 0, 240);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &burner_, DeviceValueType::BOOL, FL_(burner), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &aPump_, DeviceValueType::BOOL, FL_(aPump), DeviceValueUOM::NONE);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &heatRequest_, DeviceValueType::UINT, FL_(heatRequest), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &blockRemain_, DeviceValueType::UINT, FL_(blockRemain), DeviceValueUOM::MINUTES);
register_device_value(DeviceValueTAG::TAG_AHS1 + ahs, &blockRemainWw_, DeviceValueType::UINT, FL_(blockRemainWw), DeviceValueUOM::MINUTES);
register_device_value(tag, &burner_, DeviceValueType::BOOL, FL_(burner), DeviceValueUOM::NONE);
register_device_value(tag, &aPump_, DeviceValueType::BOOL, FL_(aPump), DeviceValueUOM::NONE);
register_device_value(tag, &heatRequest_, DeviceValueType::UINT, FL_(heatRequest), DeviceValueUOM::PERCENT);
register_device_value(tag, &blockRemain_, DeviceValueType::UINT, FL_(blockRemain), DeviceValueUOM::MINUTES);
register_device_value(tag, &blockRemainWw_, DeviceValueType::UINT, FL_(blockRemainWw), DeviceValueUOM::MINUTES);
}
// cascaded heating sources, only some values per individual heatsource (hs)

102
src/devices/ventilation.cpp Normal file
View File

@@ -0,0 +1,102 @@
/*
* EMS-ESP - https://github.com/emsesp/EMS-ESP
* Copyright 2020-2023 Paul Derbyshire
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ventilation.h"
namespace emsesp {
REGISTER_FACTORY(Ventilation, EMSdevice::DeviceType::VENTILATION);
Ventilation::Ventilation(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
// HRV176 module, device_id 0x51
register_telegram_type(0x56B, "VentilationMode", true, MAKE_PF_CB(process_ModeMessage));
register_telegram_type(0x585, "Blowerspeed", false, MAKE_PF_CB(process_BlowerMessage));
register_telegram_type(0x583, "VentilationMonitor", false, MAKE_PF_CB(process_MonitorMessage));
register_telegram_type(0x5D9, "Airquality", false, MAKE_PF_CB(process_VOCMessage));
// register_telegram_type(0x5, "VentilationSet", true, MAKE_PF_CB(process_SetMessage));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
&outFresh_,
DeviceValueType::SHORT,
DeviceValueNumOp::DV_NUMOP_DIV10,
FL_(outFresh),
DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &inFresh_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(inFresh), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &outEx_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(outEx), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &inEx_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(inEx), DeviceValueUOM::DEGREES);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ventInSpeed_, DeviceValueType::UINT, FL_(ventInSpeed), DeviceValueUOM::PERCENT);
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &ventOutSpeed_, DeviceValueType::UINT, FL_(ventOutSpeed), DeviceValueUOM::PERCENT);
register_device_value(
DeviceValueTAG::TAG_DEVICE_DATA, &mode_, DeviceValueType::ENUM, FL_(enum_ventMode), FL_(ventInSpeed), DeviceValueUOM::NONE, MAKE_CF_CB(set_ventMode));
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &voc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(airquality), DeviceValueUOM::NONE);
}
// message
void Ventilation::process_SetMessage(std::shared_ptr<const Telegram> telegram) {
}
// message 583
void Ventilation::process_MonitorMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, outEx_, 0); // Fortluft
has_update(telegram, inEx_, 7); // Abluft
has_update(telegram, outFresh_, 13); // Außenluft
has_update(telegram, inFresh_, 15); // Zuluft
}
// message 575 10 bytes
// data: 02 02 46 46 00 00 FF 80 00 01
// 0-level out, 1-level in, 2-mod out, 3-mod in, 9-mode:1-manual/2-auto/3-prog
// message 585 26 bytes long
// Data: 46 46 00 00 00 77 00 03 F4 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
void Ventilation::process_BlowerMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, ventOutSpeed_, 0);
has_update(telegram, ventInSpeed_, 1);
}
// message 0x05D9, data: 03 9C FF
void Ventilation::process_VOCMessage(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, voc_, 0);
}
// message 0x56B
// level 0=0, 1=1, 2=2, 3=3, 4= 4, Auto 0xFF, demand 5, sleep 6, intense 7, bypass-8, party 9, fireplace 0A
void Ventilation::process_ModeMessage(std::shared_ptr<const Telegram> telegram) {
has_enumupdate(telegram, mode_, 0, -1);
}
bool Ventilation::set_ventMode(const char * value, const int8_t id) {
uint8_t v;
if (!Helpers::value2enum(value, v, FL_(enum_ventMode))) {
return false;
}
write_command(0x56B, 0, v - 1, 0x56B);
return true;
}
bool Ventilation::set_filter(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {
return false;
}
// write_command(0x5xx, 0, v, 0x5xx);
return true;
}
} // namespace emsesp

117
src/devices/ventilation.h Normal file
View File

@@ -0,0 +1,117 @@
/*
* EMS-ESP - https://github.com/emsesp/EMS-ESP
* Copyright 2020-2023 Paul Derbyshire
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EMSESP_VENTILATION_H
#define EMSESP_VENTILATION_H
#include "emsesp.h"
namespace emsesp {
class Ventilation : public EMSdevice {
public:
Ventilation(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand);
private:
uint8_t mode_;
int16_t outFresh_;
int16_t inFresh_;
int16_t inEx_;
int16_t outEx_;
uint16_t voc_;
uint8_t bypass_;
uint16_t filterRemain_;
uint8_t ventInSpeed_;
uint8_t ventOutSpeed_;
// handlers: 0x056B 0x0575 0x0583 0x0585 0x0586 0x0587 0x0588 0x058D 0x058E 0x058F 0x0590 0x05CF 0x05D9 0x05E3
void process_SetMessage(std::shared_ptr<const Telegram> telegram);
void process_MonitorMessage(std::shared_ptr<const Telegram> telegram);
void process_ModeMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
void process_BlowerMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
void process_VOCMessage(std::shared_ptr<const Telegram> telegram); // 0x56B
bool set_ventMode(const char * value, const int8_t id);
bool set_filter(const char * value, const int8_t id);
/* Sensors:
outdoor air temp (außenluft)
supply air temp (zuluft)
extract air temp (abluft)
away air temp (fortluft)
supply blower (zuluftgebläse)
supply blower mod (zuluftebläse drehzahl)
away blower (abluftgebläse)
away blower mod (abluftgebläse drehzahl)
Anschlussvariante
el. vorheizer
ext. el. vorheizreg.
nachheiz zulufttemp
mischer öffnen
mischer schließen
mischerposition
zuluft temp soll
zuluft temp ist
leistung nachheizreg.
erdwärmetauscher klappe
solekreispumpe
abluftfeuchte
abluftqualität
raumluftfechte
raumluftqualität
luftfeuchte fernbed. 1..4
*/
/* Parameters:
Gerätetyp,
Nennvolumentstrom,
Filterlaufzeit 1-6-12 m
Filterwechsel confirm CMD
Lüftungsfrostschutz: _el._preheat_, Disballance | Interval
Ext. Frostschutz: on/_off_
Bypass _on_, off
min. outdoortemp 12 15 19 °C
max. outdoortemp 21-24-30 C
Enthalpie Wärmetauscher instaliert nein-ja
Feuchteschutz AUs/ 1-24 h
Lüfterstufe 1-4, Drehzahlanpassung
ext. Luftfeuchtefühler inst.? _nein_, ja
Abluftfeuchtefühler inst.? _nein_, ja
Luftfeuchte Fernbed. _nein_, ja
Luftfeuchte: trocken, _normal_, feucht
Abluftqualitätsfühler inst. _ja_, nein
ext. Luftqualfühl? _nein_, ja
Lufqualität: ausreichend, _normal_, hoch
el. Nachheizregister inst. _nein_, ja
Nachheiz-Zuluft temp: 10-22-30 °C
Erdwärmetauscher inst? _nein_, Luft, Sole
Taster Funktion: nein, einschlafen, intensiv, bypass, party, kamin
ext. Störung aktivieren: _nein_, ja, invertiert
Dauer einschlafen: 15-60-120 min
Dauer Intensiv: 5-15-60 min
Dauer Bypass Abluft: 1-8-12 h
Dauer Bypass: 1-8-12 h
Dauer PArty 1-8-12 h
Dauer Kamin: 5-10-15 min
Volumenstromabgleich 90-100-110 %
*/
};
} // namespace emsesp
#endif

View File

@@ -137,6 +137,8 @@ const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) {
return F_(heatsource);
case DeviceType::CUSTOM:
return F_(custom);
case DeviceType::VENTILATION:
return F_(ventilation);
default:
return Helpers::translated_word(FL_(unknown), true);
}
@@ -170,6 +172,8 @@ const char * EMSdevice::device_type_2_device_name_translated() {
return Helpers::translated_word(FL_(pump_device));
case DeviceType::HEATSOURCE:
return Helpers::translated_word(FL_(heatsource_device));
case DeviceType::VENTILATION:
return Helpers::translated_word(FL_(ventilation_device));
default:
break;
}
@@ -234,6 +238,9 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
if (!strcmp(lowtopic, F_(custom))) {
return DeviceType::CUSTOM;
}
if (!strcmp(lowtopic, F_(ventilation))) {
return DeviceType::VENTILATION;
}
return DeviceType::UNKNOWN;
}

View File

@@ -155,7 +155,7 @@ class EMSdevice {
}
}
inline void has_enumupdate(std::shared_ptr<const Telegram> telegram, uint8_t & value, const uint8_t index, uint8_t s = 0) {
inline void has_enumupdate(std::shared_ptr<const Telegram> telegram, uint8_t & value, const uint8_t index, int8_t s = 0) {
if (telegram->read_enumvalue(value, index, s)) {
has_update_ = true;
publish_value((void *)&value);
@@ -337,6 +337,7 @@ class EMSdevice {
GENERIC,
HEATSOURCE,
CUSTOM,
VENTILATION,
UNKNOWN
};
@@ -380,6 +381,7 @@ class EMSdevice {
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 = 5;
static constexpr uint8_t EMS_DEVICE_FLAG_HIU = 6;
// Solar Module
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;

View File

@@ -99,6 +99,7 @@ MAKE_WORD(pump)
MAKE_WORD(heatsource)
MAKE_WORD(scheduler)
MAKE_WORD(custom)
MAKE_WORD(ventilation)
// brands
MAKE_WORD_CUSTOM(bosch, "Bosch")
@@ -192,6 +193,10 @@ MAKE_NOTRANSLATION(3kW, "3 kW")
MAKE_NOTRANSLATION(4kW, "4 kW")
MAKE_NOTRANSLATION(6kW, "6 kW")
MAKE_NOTRANSLATION(9kW, "9 kW")
MAKE_NOTRANSLATION(L1, "L1")
MAKE_NOTRANSLATION(L2, "L2")
MAKE_NOTRANSLATION(L3, "L3")
MAKE_NOTRANSLATION(L4, "L4")
// templates - this are not translated and will be saved under options_single
MAKE_NOTRANSLATION(tpl_datetime, "< NTP | dd.mm.yyyy-hh:mm:ss-day(0-6)-dst(0/1) >")
@@ -343,6 +348,9 @@ MAKE_ENUM(enum_blockMode, FL_(off), FL_(auto), FL_(blocking))
MAKE_ENUM(enum_bufConfig, FL_(off), FL_(monovalent), FL_(bivalent))
MAKE_ENUM(enum_blockTerm, FL_(n_o), FL_(n_c))
// Ventilation
MAKE_ENUM(enum_ventMode, FL_(auto), FL_(off), FL_(L1), FL_(L2), FL_(L3), FL_(L4), FL_(demand), FL_(sleep), FL_(intense), FL_(bypass), FL_(partymode), FL_(fireplace))
#pragma GCC diagnostic pop
// clang-format on

View File

@@ -49,8 +49,9 @@ MAKE_WORD_TRANSLATION(pump_device, "Pump Module", "Pumpenmodul", "Pump Module",
MAKE_WORD_TRANSLATION(heatsource_device, "Heatsource", "Heizquelle", "Heatsource", "Värmekälla", "Źródło ciepła", "Varmekilde", "", "Isı Kaynağı") // TODO translate
MAKE_WORD_TRANSLATION(sensors_device, "Sensors", "Sensoren", "Sensoren", "Sensorer", "Czujniki", "Sensorer", "Capteurs", "Sensör Cihazı")
MAKE_WORD_TRANSLATION(unknown_device, "Unknown", "Unbekannt", "Onbekend", "Okänt", "Nieznane urządzenie", "Ukjent", "Inconnu", "") // TODO translate
MAKE_WORD_TRANSLATION(custom_device, "Custom", "", "", "", "Niestandardowe", "", "", "") // TODO translate
MAKE_WORD_TRANSLATION(custom_device, "Custom", "Nutzerdefiniert", "", "", "Niestandardowe", "", "", "") // TODO translate
MAKE_WORD_TRANSLATION(custom_device_name, "User defined entities", "Nutzer deklarierte Entitäten", "", "", "Encje zdefiniowane przez użytkownika", "", "", "") // TODO translate
MAKE_WORD_TRANSLATION(ventilation_device, "Ventilation", "Lüftung", "", "", "", "", "", "") // TODO translate
// commands
// TODO translate
@@ -61,8 +62,8 @@ MAKE_WORD_TRANSLATION(send_cmd, "send a telegram", "Sende EMS-Telegramm", "", ""
MAKE_WORD_TRANSLATION(setiovalue_cmd, "set io value", "Setze Wertevorgabe", "", "", "ustaw wartość", "sett en io verdi", "", "Giriş/Çıkış değerlerini ayarla") // TODO translate
MAKE_WORD_TRANSLATION(changeloglevel_cmd, "change log level", "Ändere Sysloglevel", "", "", "zmień poziom log-u", "endre loggnivå", "", "Kayıt seviyesini değiştir") // TODO translate
MAKE_WORD_TRANSLATION(fetch_cmd, "refresh all EMS values", "Lese alle EMS-Werte neu", "", "", "odśwież wszystkie wartości EMS", "oppfrisk alle EMS verdier", "", "Bütün EMS değerlerini yenile") // TODO translate
MAKE_WORD_TRANSLATION(restart_cmd, "restart EMS-ESP", "Neustart", "", "", "uruchom ponownie EMS-ESP", "restart EMS-ESP", "", "EMS-ESPyi yeniden başlat") // TODO translate
MAKE_WORD_TRANSLATION(watch_cmd, "watch incoming telegrams", "Watch auf eingehende Telegramme", "", "", "obserwuj przychodzące telegramy", "se innkommende telegrammer", "", "Gelen telegramları ") // TODO translate
MAKE_WORD_TRANSLATION(restart_cmd, "restart EMS-ESP", "Neustart", "", "", "uruchom ponownie EMS-ESP", "restart EMS-ESP", "redémarrer EMS-ESP", "EMS-ESPyi yeniden başlat") // TODO translate
MAKE_WORD_TRANSLATION(watch_cmd, "watch incoming telegrams", "Watch auf eingehende Telegramme", "", "", "obserwuj przyczodzące telegramy", "se innkommende telegrammer", "", "Gelen telegramları ") // TODO translate
MAKE_WORD_TRANSLATION(publish_cmd, "publish all to MQTT", "Publiziere MQTT", "", "", "opublikuj wszystko na MQTT", "Publiser alt til MQTT", "", "Hepsini MQTTye gönder") // TODO translate
MAKE_WORD_TRANSLATION(system_info_cmd, "show system status", "Zeige System-Status", "", "", "pokaż status systemu", "vis system status", "", "Sistem Durumunu Göster") // TODO translate
MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplan", "", "", "aktywuj wybrany harmonogram", "", "", "") // TODO translate
@@ -266,10 +267,17 @@ MAKE_WORD_TRANSLATION(close, "close", "geschlossen", "Gesloten", "Stängd", "zam
MAKE_WORD_TRANSLATION(cyl1, "cyl 1", "Zyl_1", "Cil 1", "Cyl 1", "cyl 1", "cyl 1", "cyl 1", "cly 1")
MAKE_WORD_TRANSLATION(cyl2, "cyl 2", "Zyl_2", "Cil 2", "Cyl 2", "cyl 2", "cyl 2", "cyl 2", "cly 1")
// Entity translations
// ventilation
MAKE_WORD_TRANSLATION(demand, "demand", "Bedarf")
MAKE_WORD_TRANSLATION(intense, "intense", "Intensiv")
MAKE_WORD_TRANSLATION(sleep, "sleep", "Einschlafen")
MAKE_WORD_TRANSLATION(partymode, "party", "Party")
MAKE_WORD_TRANSLATION(fireplace, "fireplace", "Kamin")
// MQTT Discovery - this is special device entity for 'climate'
MAKE_TRANSLATION(haclimate, "haclimate", "Discovery current room temperature", "Discovery Temperatur", "", "", "termostat w HA", "HA Avlest temp", "", "") // TODO translate
// Entity translations
// Boiler
MAKE_TRANSLATION(wwtapactivated, "wwtapactivated", "turn on/off", "Durchlauferhitzer aktiv", "zet aan/uit", "på/av", "system przygotowywania", "Varmtvann active", "ecs activée", "")
MAKE_TRANSLATION(reset, "reset", "Reset", "Reset", "Reset", "Nollställ", "kasowanie komunikatu", "nullstill", "reset", "")
@@ -487,6 +495,11 @@ MAKE_TRANSLATION(blockTerm, "blockterm", "config of block terminal", "Konfig. Sp
MAKE_TRANSLATION(blockHyst, "blockhyst", "hyst. for boiler block", "Hysterese Sperrmodus", "Hysterese blokeerterminal", "Hysteres Blockeringsmodul", "tryb blokowania histerezy", "hystrese blokkeringsmodus", "hyst. Blocage chaudière", "")
MAKE_TRANSLATION(releaseWait, "releasewait", "boiler release wait time", "Wartezeit Kessel-Freigabe", "Wachttijd ketel vrijgave", "Väntetid Frisläppning", "czas oczekiwania na zwolnienie kotła", "kjele frigjøringsventetid", "temps attente libération chaudière", "")
// HIU
MAKE_TRANSLATION(netFlowTemp, "netflowtemp", "heat network flow temp")
MAKE_TRANSLATION(cwFlowRate, "cwflowrate", "cold water flow rate")
MAKE_TRANSLATION(keepWarmTemp, "keepwarmtemp", "keep warm temperature")
// the following are dhw for the boiler and automatically tagged with 'dhw'
MAKE_TRANSLATION(wwSelTemp, "wwseltemp", "selected temperature", "gewählte Temperatur", "Geselecteerd temperatuur", "Vald Temperatur", "temperatura wyższa/komfort", "valgt temperatur", "température sélectionnée", "")
MAKE_TRANSLATION(wwSelTempLow, "wwseltemplow", "selected lower temperature", "untere Solltemperatur", "Onderste streeftemperatuur", "Vald lägstatemperatur", "temperatura niższa/eko", "valgt nedre temperatur", "température basse sélectionnée", "")
@@ -753,6 +766,16 @@ MAKE_TRANSLATION(status, "status", "status", "Status", "Status", "Status", "stat
// RF sensor, id 0x40, telegram 0x435
MAKE_TRANSLATION(RFTemp, "rftemp", "RF room temperature sensor", "RF Raumtemperatur Sensor", "RF ruimtetemperatuur sensor", "RF Rumsgivare Temp", "bezprzewodowy czujnik temperatury pomieszczenia", "RF romsgiver temp", "capteur de température de pièce RF", "")
// ventilation
MAKE_TRANSLATION(outFresh, "outfresh", "outdoor fresh air", "Außenlufttemp.")
MAKE_TRANSLATION(inFresh, "infresh", "indoor fresh air", "Zulufttemp.")
MAKE_TRANSLATION(outEx, "outexhaust", "outdoor exhaust air", "Fortlufttemp.")
MAKE_TRANSLATION(inEx, "inexhaust", "indoor exhaust air", "Ablufttemp.")
MAKE_TRANSLATION(ventMode, "ventmode", "ventilation mode", "Belüftungsmodus")
MAKE_TRANSLATION(ventInSpeed, "ventinspeed", "in blower speed", "Zuluft-Drehzahl")
MAKE_TRANSLATION(ventOutSpeed, "ventoutspeed", "out blower speed", "Abluft-Drehzahl")
MAKE_TRANSLATION(airquality, "airquality", "air quality (voc)", "Luftqualität (VOC)")
/*
// unknown fields to track (SM10), only for testing
// **** NO TRANSLATION NEEDED ****

View File

@@ -657,10 +657,15 @@ void System::network_init(bool refresh) {
last_system_check_ = 0; // force the LED to go from fast flash to pulse
// no ethernet present
if (phy_type_ == PHY_type::PHY_TYPE_NONE) {
bool disableEth;
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & settings) {
disableEth = settings.ssid.length() > 0;
});
// no ethernet present or disabled
if (phy_type_ == PHY_type::PHY_TYPE_NONE || disableEth) {
return;
}
} // no ethernet present
// configure Ethernet
int mdc = 23; // Pin# of the I²C clock signal for the Ethernet PHY - hardcoded

View File

@@ -137,7 +137,7 @@ class Telegram {
return (val != value);
}
bool read_enumvalue(uint8_t & value, const uint8_t index, uint8_t start = 0) const {
bool read_enumvalue(uint8_t & value, const uint8_t index, int8_t start = 0) const {
if ((index < this->offset) || ((index - this->offset) >= this->message_length)) {
return false;
}

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.0-dev.11"
#define EMSESP_APP_VERSION "3.6.0-dev.12"

View File

@@ -49,7 +49,7 @@ void WebEntity::read(WebEntity & webEntity, JsonObject & root) {
ei["uom"] = entityItem.uom;
ei["value_type"] = entityItem.value_type;
ei["writeable"] = entityItem.writeable;
EMSESP::webEntityService.render_value(ei, entityItem, true);
EMSESP::webEntityService.render_value(ei, entityItem, true, true);
}
}
@@ -114,7 +114,7 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
if (!Helpers::value2bool(value, v)) {
return false;
}
EMSESP::send_write_request(entityItem.type_id, entityItem.device_id, entityItem.offset, v ? 0xFF : 0, 0);
EMSESP::send_write_request(entityItem.type_id, entityItem.device_id, entityItem.offset, v ? entityItem.type_id > 0xFF ? 1 : 0xFF : 0, 0);
} else {
float f;
if (!Helpers::value2float(value, f)) {
@@ -143,13 +143,15 @@ bool WebEntityService::command_setvalue(const char * value, const std::string na
}
// output of a single value
void WebEntityService::render_value(JsonObject & output, EntityItem entity, const bool useVal) {
void WebEntityService::render_value(JsonObject & output, EntityItem entity, const bool useVal, const bool web) {
char payload[12];
std::string name = useVal ? "value" : entity.name;
switch (entity.value_type) {
case DeviceValueType::BOOL:
if ((uint8_t)entity.value != EMS_VALUE_BOOL_NOTSET) {
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
if (web) {
output[name] = Helpers::render_boolean(payload, (uint8_t)entity.value, true);
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
output[name] = (uint8_t)entity.value ? true : false;
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
output[name] = (uint8_t)entity.value ? 1 : 0;
@@ -330,7 +332,7 @@ void WebEntityService::publish(const bool force) {
// EMSESP::logger().debug("publish %d custom entities", output.size());
}
// count only entities with valid value
// count only entities with valid value or command to show in dashboard
uint8_t WebEntityService::count_entities() {
EMSESP::webEntityService.read([&](WebEntity & webEntity) { entityItems = &webEntity.entityItems; });
if (entityItems->size() == 0) {
@@ -339,11 +341,12 @@ uint8_t WebEntityService::count_entities() {
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE);
JsonObject output = doc.to<JsonObject>();
uint8_t count = 0;
for (const EntityItem & entity : *entityItems) {
render_value(output, entity);
count += (output.containsKey(entity.name) || entity.writeable) ? 1 : 0;
}
return output.size();
return count;
}
// send to dashboard, msgpack don't like serialized, use number
@@ -352,7 +355,7 @@ void WebEntityService::generate_value_web(JsonObject & output) {
output["label"] = (std::string) "Custom Entities";
JsonArray data = output.createNestedArray("data");
uint8_t index = 0;
for (const EntityItem & entity : *entityItems) {
JsonObject obj = data.createNestedObject(); // create the object, we know there is a value
obj["id"] = "00" + entity.name;
@@ -364,7 +367,7 @@ void WebEntityService::generate_value_web(JsonObject & output) {
switch (entity.value_type) {
case DeviceValueType::BOOL: {
char s[12];
obj["v"] = Helpers::render_boolean(s, (uint8_t)entity.value);
obj["v"] = Helpers::render_boolean(s, (uint8_t)entity.value, true);
JsonArray l = obj.createNestedArray("l");
l.add(Helpers::render_boolean(s, false, true));
l.add(Helpers::render_boolean(s, true, true));
@@ -399,6 +402,11 @@ void WebEntityService::generate_value_web(JsonObject & output) {
default:
break;
}
if (!obj.containsKey("v") && !obj.containsKey("c")) {
data.remove(index);
} else {
index++;
}
}
}

View File

@@ -58,7 +58,7 @@ class WebEntityService : public StatefulService<WebEntity> {
bool get_value_info(JsonObject & output, const char * cmd);
bool get_value(std::shared_ptr<const Telegram> telegram);
void fetch();
void render_value(JsonObject & output, EntityItem entity, const bool useVal = false);
void render_value(JsonObject & output, EntityItem entity, const bool useVal = false, const bool web = false);
uint8_t count_entities();
void generate_value_web(JsonObject & output);