mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
Merge pull request #1176 from MichaelDvP/dev
AM20, HIU, Ventilation and other
This commit is contained in:
4
.github/workflows/pre_release.yml
vendored
4
.github/workflows/pre_release.yml
vendored
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
102
src/devices/ventilation.cpp
Normal 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
117
src/devices/ventilation.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ****
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.6.0-dev.11"
|
||||
#define EMSESP_APP_VERSION "3.6.0-dev.12"
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user