diff --git a/.github/workflows/pre_release.yml b/.github/workflows/pre_release.yml index 421bcab1a..9da1351c0 100644 --- a/.github/workflows/pre_release.yml +++ b/.github/workflows/pre_release.yml @@ -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' diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 6bf09662c..b40755b3d 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -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) diff --git a/platformio.ini b/platformio.ini index e0e7bed85..27eea1101 100644 --- a/platformio.ini +++ b/platformio.ini @@ -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 diff --git a/src/device_library.h b/src/device_library.h index 80e5c47fe..84bc0fa66 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -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 diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index f8b50d0dc..e6d92501d 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -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 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 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 [] + 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 [] + 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 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 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 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 [] + 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: [] + 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) { diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 3e5988d05..264d00d39 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -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 telegram); void process_HpSettings2(std::shared_ptr telegram); void process_HpSettings3(std::shared_ptr telegram); + // HIU + void process_HIUSettings(std::shared_ptr telegram); + void process_HIUMonitor(std::shared_ptr 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); diff --git a/src/devices/heatsource.cpp b/src/devices/heatsource.cpp index c7f180878..72f3cb574 100644 --- a/src/devices/heatsource.cpp +++ b/src/devices/heatsource.cpp @@ -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) diff --git a/src/devices/ventilation.cpp b/src/devices/ventilation.cpp new file mode 100644 index 000000000..18d2d1579 --- /dev/null +++ b/src/devices/ventilation.cpp @@ -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 . + */ + +#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 telegram) { +} + +// message 583 +void Ventilation::process_MonitorMessage(std::shared_ptr 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 telegram) { + has_update(telegram, ventOutSpeed_, 0); + has_update(telegram, ventInSpeed_, 1); +} + +// message 0x05D9, data: 03 9C FF +void Ventilation::process_VOCMessage(std::shared_ptr 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 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 diff --git a/src/devices/ventilation.h b/src/devices/ventilation.h new file mode 100644 index 000000000..0d0b2a304 --- /dev/null +++ b/src/devices/ventilation.h @@ -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 . + */ + +#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 telegram); + void process_MonitorMessage(std::shared_ptr telegram); + void process_ModeMessage(std::shared_ptr telegram); // 0x56B + void process_BlowerMessage(std::shared_ptr telegram); // 0x56B + void process_VOCMessage(std::shared_ptr 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 diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 891aca0e0..97d74f6dc 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -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; } diff --git a/src/emsdevice.h b/src/emsdevice.h index c1f3f811e..00ab27f1c 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -155,7 +155,7 @@ class EMSdevice { } } - inline void has_enumupdate(std::shared_ptr telegram, uint8_t & value, const uint8_t index, uint8_t s = 0) { + inline void has_enumupdate(std::shared_ptr 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; diff --git a/src/locale_common.h b/src/locale_common.h index edc2a4d3e..afab14406 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -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 diff --git a/src/locale_translations.h b/src/locale_translations.h index 4639bf451..f614cf7f0 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -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 **** diff --git a/src/system.cpp b/src/system.cpp index ed3f1b6ad..44698d252 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -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 diff --git a/src/telegram.h b/src/telegram.h index 00ec4d305..5f873e159 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -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; } diff --git a/src/version.h b/src/version.h index 8afdc2259..f49ccbca4 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.0-dev.11" +#define EMSESP_APP_VERSION "3.6.0-dev.12" diff --git a/src/web/WebEntityService.cpp b/src/web/WebEntityService.cpp index e377a8ace..a52d8fc1b 100644 --- a/src/web/WebEntityService.cpp +++ b/src/web/WebEntityService.cpp @@ -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(); - + 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++; + } } } diff --git a/src/web/WebEntityService.h b/src/web/WebEntityService.h index 37a94e15f..9010cacf1 100644 --- a/src/web/WebEntityService.h +++ b/src/web/WebEntityService.h @@ -58,7 +58,7 @@ class WebEntityService : public StatefulService { bool get_value_info(JsonObject & output, const char * cmd); bool get_value(std::shared_ptr 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);