diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 734d7bff2..d87aee0b3 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -28,6 +28,11 @@ - Settings for heatpump silent mode and additional heater [[#802](https://github.com/emsesp/EMS-ESP32/issues/802)] [[#803](https://github.com/emsesp/EMS-ESP32/issues/803)] - Zone module MZ100 [#826](https://github.com/emsesp/EMS-ESP32/issues/826) - Default MQTT hostname is blank [#829](https://github.com/emsesp/EMS-ESP32/issues/829) +- wwCurFlow for ems+ devices [#829](https://github.com/emsesp/EMS-ESP32/issues/829) +- Add Rego 3000, TR120RF thermostats [#917](https://github.com/emsesp/EMS-ESP32/issues/917) +- Add config for ESP32-S3 +- Add heatpump silent mode and other entities [#896](https://github.com/emsesp/EMS-ESP32/issues/896) +- Allow reboot to other partition (factory or asymmetric OTA) ## Fixed @@ -36,6 +41,10 @@ - Commands for multiple thermostats [#826](https://github.com/emsesp/EMS-ESP32/issues/826) - API queries for multiple devices [#865](https://github.com/emsesp/EMS-ESP32/issues/865) - Console crash when using call with command `hcx` only. [#841](https://github.com/emsesp/EMS-ESP32/issues/841) +- heatingPump2Mod was wrong, changed to absBurnPow [[#908](https://github.com/emsesp/EMS-ESP32/issues/908) +- rounding of web input values +- analog sensor with single gpio number [#915](https://github.com/emsesp/EMS-ESP32/issues/915) +- HA dallas and analog configs: remove/rebuild on change [#888](https://github.com/emsesp/EMS-ESP32/issues/888) ## Changed @@ -47,5 +56,5 @@ - analog/dallas values command as list like ems-devices - analog/dallas HA-entities based on id - MQTT Base is a mandatory field. Removed MQTT topic length from settings -- HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822 -- AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857 +- HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822) +- AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857) diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 64848203c..acaa91fc3 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -275,9 +275,9 @@ const SettingsCustomization: FC = () => { if (devices && deviceEntities && selectedDevice !== -1) { const masked_entities = getChanges(); - // check size in bytes to match buffer in CPP, which is 4096 + // check size in bytes to match buffer in CPP, which is 2048 const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length; - if (bytes > 4000) { + if (bytes > 2000) { enqueueSnackbar(LL.CUSTOMIZATIONS_FULL(), { variant: 'warning' }); return; } diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index cad7c94fa..e2817af79 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -252,7 +252,8 @@ export const BOARD_PROFILES: BoardProfiles = { OLIMEX: 'Olimex ESP32-EVB', OLIMEXPOE: 'Olimex ESP32-POE', C3MINI: 'Wemos C3 Mini', - S2MINI: 'Wemos S2 Mini' + S2MINI: 'Wemos S2 Mini', + S3MINI: 'Liligo S3' }; export interface BoardProfileName { diff --git a/lib/framework/RestartService.cpp b/lib/framework/RestartService.cpp index cb12fc841..afa42ef16 100644 --- a/lib/framework/RestartService.cpp +++ b/lib/framework/RestartService.cpp @@ -17,11 +17,24 @@ void RestartService::restart(AsyncWebServerRequest * request) { void RestartService::partition(AsyncWebServerRequest * request) { const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); - if (!factory_partition) { + if (factory_partition) { + esp_ota_set_boot_partition(factory_partition); + request->onDisconnect(RestartService::restartNow); + request->send(200); + return; + } + const esp_partition_t * ota_partition = esp_ota_get_next_update_partition(NULL); + if (!ota_partition) { request->send(400); // bad request return; } - esp_ota_set_boot_partition(factory_partition); + uint64_t buffer; + esp_partition_read(ota_partition, 0, &buffer, 8); + if (buffer == 0xFFFFFFFFFFFFFFFF) { // partition empty + request->send(400); // bad request + return; + } + esp_ota_set_boot_partition(ota_partition); request->onDisconnect(RestartService::restartNow); request->send(200); } diff --git a/lib/framework/SystemStatus.cpp b/lib/framework/SystemStatus.cpp index 61e347211..2f19bf4d6 100644 --- a/lib/framework/SystemStatus.cpp +++ b/lib/framework/SystemStatus.cpp @@ -31,12 +31,24 @@ void SystemStatus::systemStatus(AsyncWebServerRequest * request) { root["fs_used"] = FSused; root["fs_free"] = emsesp::EMSESP::system_.FStotal() - FSused; root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3); + if (emsesp::EMSESP::system_.PSram()) { root["psram_size"] = emsesp::EMSESP::system_.PSram(); root["free_psram"] = ESP.getFreePsram() / 1024; } - const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); - root["has_loader"] = factory_partition != NULL; + + const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + if (partition != NULL) { // factory partition found + root["has_loader"] = true; + } else { // check for not empty, smaller OTA partition + partition = esp_ota_get_next_update_partition(NULL); + if (partition) { + uint64_t buffer; + esp_partition_read(partition, 0, &buffer, 8); + const esp_partition_t * running = esp_ota_get_running_partition(); + root["has_loader"] = (buffer != 0xFFFFFFFFFFFFFFFF && running->size != partition->size); + } + } response->setLength(); request->send(response); diff --git a/lib/framework/UploadFileService.cpp b/lib/framework/UploadFileService.cpp index 440d9a074..9ab97c683 100644 --- a/lib/framework/UploadFileService.cpp +++ b/lib/framework/UploadFileService.cpp @@ -62,6 +62,11 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri handleError(request, 503); // service unavailable return; } +#elif CONFIG_IDF_TARGET_ESP32S3 + if (len > 12 && (data[0] != 0xE9 || data[12] != 3)) { + handleError(request, 503); // service unavailable + return; + } #endif // it's firmware - initialize the ArduinoOTA updater if (Update.begin(fsize)) { diff --git a/mock-api/server.js b/mock-api/server.js index e74b8c6d8..39c8f6054 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -1198,6 +1198,17 @@ rest_server.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => { data.eth_power = 0 data.eth_phy_addr = 0 data.eth_clock_mode = 0 + } else if (board_profile == 'S3MINI') { + // Liligo S3 mini + data.led_gpio = 17 + data.dallas_gpio = 18 + data.rx_gpio = 8 + data.tx_gpio = 5 + data.pbutton_gpio = 0 + data.phy_type = 0 + data.eth_power = 0 + data.eth_phy_addr = 0 + data.eth_clock_mode = 0 } console.log('boardProfile POST. Sending back, profile: ' + board_profile + ', ' + 'data: ' + JSON.stringify(data)) diff --git a/platformio.ini b/platformio.ini index 1423f56be..e61f42d20 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,6 +39,12 @@ build_flags = unbuild_flags = ${common.core_unbuild_flags} +[espressi32_base] +platform = espressif32@5.2.0 +; platform = espressif32@5.3.0 +; platform = espressif32@6.0.0 +framework = arduino + [env] monitor_speed = 115200 monitor_raw = yes @@ -55,46 +61,42 @@ check_flags = ; build for GitHub Actions CI ; the Web interface is built seperately [env:ci] +extends = espressi32_base extra_scripts = scripts/rename_fw.py board = esp32dev -framework = arduino -platform = espressif32 board_build.partitions = esp32_partition_4M.csv board_build.filesystem = littlefs build_flags = ${common.build_flags} build_unflags = ${common.unbuild_flags} [env:esp32_4M] +extends = espressi32_base extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = esp32dev -framework = arduino -platform = espressif32 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} build_unflags = ${common.unbuild_flags} [env:esp32_16M] +extends = espressi32_base extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = esp32dev -framework = arduino -platform = espressif32 board_upload.flash_size = 16MB board_build.partitions = esp32_partition_16M.csv build_flags = ${common.build_flags} build_unflags = ${common.unbuild_flags} [env:lolin_c3_mini] +extends = espressi32_base extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = lolin_c3_mini -framework = arduino -platform = espressif32 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} @@ -103,29 +105,39 @@ build_unflags = ${common.unbuild_flags} ; lolin C3 mini v1 needs special wifi init. ; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi [env:lolin_c3_mini_v1] +extends = espressi32_base extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = lolin_c3_mini -framework = arduino -platform = espressif32 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} -DBOARD_C3_MINI_V1 build_unflags = ${common.unbuild_flags} [env:lolin_s2_mini] +extends = espressi32_base extra_scripts = pre:scripts/build_interface.py scripts/rename_fw.py board = lolin_s2_mini -framework = arduino -platform = espressif32 board_upload.flash_size = 4MB board_build.partitions = esp32_partition_4M.csv build_flags = ${common.build_flags} build_unflags = ${common.unbuild_flags} +[env:esp32s3] +extends = espressi32_base +extra_scripts = + pre:scripts/build_interface.py + scripts/rename_fw.py +board = lolin_s3 +board_upload.flash_size = 16MB +board_build.partitions = esp32_partition_16M.csv +build_flags = ${common.build_flags} +build_unflags = ${common.unbuild_flags} +upload_protocol = esptool + ; see https://docs.platformio.org/en/latest/platforms/native.html#id1 ; to build: pio run -e standalone ; to run and build: pio run -e standalone -t exec diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index fccaf23a5..0c015b4af 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -67,6 +67,10 @@ void AnalogSensor::reload() { #if defined(EMSESP_STANDALONE) analog_enabled_ = true; // for local offline testing #endif + for (auto sensor : sensors_) { + remove_ha_topic(sensor.gpio()); + sensor.ha_registered = false; + } if (!analog_enabled_) { sensors_.clear(); return; @@ -137,12 +141,12 @@ void AnalogSensor::reload() { for (auto & sensor : sensors_) { sensor.ha_registered = false; // force HA configs to be re-created if (sensor.type() == AnalogType::ADC) { - LOG_DEBUG("Adding analog ADC sensor on GPIO%d", sensor.gpio()); + LOG_DEBUG("Adding analog ADC sensor on GPIO %02d", sensor.gpio()); // analogSetPinAttenuation does not work with analogReadMilliVolts sensor.analog_ = 0; // initialize sensor.last_reading_ = 0; } else if (sensor.type() == AnalogType::COUNTER) { - LOG_DEBUG("Adding analog I/O Counter sensor on GPIO%d", sensor.gpio()); + LOG_DEBUG("Adding analog I/O Counter sensor on GPIO %02d", sensor.gpio()); pinMode(sensor.gpio(), INPUT_PULLUP); #if CONFIG_IDF_TARGET_ESP32 if (sensor.gpio() == 25 || sensor.gpio() == 26) { @@ -157,7 +161,7 @@ void AnalogSensor::reload() { sensor.poll_ = digitalRead(sensor.gpio()); publish_sensor(sensor); } else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) { - LOG_DEBUG("Adding analog Timer/Rate sensor on GPIO%d", sensor.gpio()); + LOG_DEBUG("Adding analog Timer/Rate sensor on GPIO %02d", sensor.gpio()); pinMode(sensor.gpio(), INPUT_PULLUP); sensor.polltime_ = uuid::get_uptime(); sensor.last_polltime_ = uuid::get_uptime(); @@ -166,7 +170,7 @@ void AnalogSensor::reload() { sensor.set_value(0); publish_sensor(sensor); } else if (sensor.type() == AnalogType::DIGITAL_IN) { - LOG_DEBUG("Adding analog Read sensor on GPIO%d", sensor.gpio()); + LOG_DEBUG("Adding analog Read sensor on GPIO %02d", sensor.gpio()); pinMode(sensor.gpio(), INPUT_PULLUP); sensor.set_value(digitalRead(sensor.gpio())); // initial value sensor.set_uom(0); // no uom, just for safe measures @@ -174,7 +178,7 @@ void AnalogSensor::reload() { sensor.poll_ = digitalRead(sensor.gpio()); publish_sensor(sensor); } else if (sensor.type() == AnalogType::DIGITAL_OUT) { - LOG_DEBUG("Adding analog Write sensor on GPIO%d", sensor.gpio()); + LOG_DEBUG("Adding analog Write sensor on GPIO %02d", sensor.gpio()); pinMode(sensor.gpio(), OUTPUT); #if CONFIG_IDF_TARGET_ESP32 if (sensor.gpio() == 25 || sensor.gpio() == 26) { @@ -204,7 +208,7 @@ void AnalogSensor::reload() { sensor.set_uom(0); // no uom, just for safe measures publish_sensor(sensor); } else if (sensor.type() >= AnalogType::PWM_0) { - LOG_DEBUG("Adding PWM output sensor on GPIO%d", sensor.gpio()); + LOG_DEBUG("Adding PWM output sensor on GPIO %02d", sensor.gpio()); uint channel = sensor.type() - AnalogType::PWM_0; ledcSetup(channel, sensor.factor(), 13); ledcAttachPin(sensor.gpio(), channel); @@ -309,7 +313,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, found_sensor = true; // found the record // see if it's marked for deletion if (type == AnalogType::MARK_DELETED) { - LOG_DEBUG("Removing analog sensor GPIO %d", gpio); + LOG_DEBUG("Removing analog sensor GPIO %02d", gpio); settings.analogCustomizations.remove(AnalogCustomization); } else { // update existing record @@ -318,7 +322,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, AnalogCustomization.factor = factor; AnalogCustomization.uom = uom; AnalogCustomization.type = type; - LOG_DEBUG("Customizing existing analog GPIO %d", gpio); + LOG_DEBUG("Customizing existing analog GPIO %02d", gpio); } return StateUpdateResult::CHANGED; // persist the change } @@ -344,7 +348,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, newSensor.uom = uom; newSensor.type = type; settings.analogCustomizations.push_back(newSensor); - LOG_DEBUG("Adding new customization for analog sensor GPIO %d", gpio); + LOG_DEBUG("Adding new customization for analog sensor GPIO %02d", gpio); return StateUpdateResult::CHANGED; // persist the change }, "local"); @@ -385,10 +389,10 @@ void AnalogSensor::remove_ha_topic(const uint8_t gpio) const { return; } #ifdef EMSESP_DEBUG - LOG_DEBUG("Removing HA config for analog sensor GPIO %d", gpio); + LOG_DEBUG("Removing HA config for analog sensor GPIO %02d", gpio); #endif char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; - snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%d/config", Mqtt::basename().c_str(), gpio); + snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio); Mqtt::publish_ha(topic); } @@ -435,7 +439,7 @@ void AnalogSensor::publish_values(const bool force) { // create HA config if (Mqtt::ha_enabled() && (!sensor.ha_registered || force)) { - LOG_DEBUG("Recreating HA config for analog sensor GPIO %d", sensor.gpio()); + LOG_DEBUG("Recreating HA config for analog sensor GPIO %02d", sensor.gpio()); StaticJsonDocument config; @@ -445,7 +449,7 @@ void AnalogSensor::publish_values(const bool force) { char str[50]; if (Mqtt::is_nested()) { - snprintf(str, sizeof(str), "{{value_json['%d'].value}}", sensor.gpio()); + snprintf(str, sizeof(str), "{{value_json['%02d'].value}}", sensor.gpio()); } else { snprintf(str, sizeof(str), "{{value_json['%s']}", sensor.name().c_str()); } @@ -453,9 +457,9 @@ void AnalogSensor::publish_values(const bool force) { char uniq_s[70]; if (Mqtt::entity_format() == 2) { - snprintf(uniq_s, sizeof(uniq_s), "%s_analogsensor_%d", Mqtt::basename().c_str(), sensor.gpio()); + snprintf(uniq_s, sizeof(uniq_s), "%s_analogsensor_%02d", Mqtt::basename().c_str(), sensor.gpio()); } else { - snprintf(uniq_s, sizeof(uniq_s), "analogsensor_%d", sensor.gpio()); + snprintf(uniq_s, sizeof(uniq_s), "analogsensor_%02d", sensor.gpio()); } config["object_id"] = uniq_s; @@ -473,7 +477,7 @@ void AnalogSensor::publish_values(const bool force) { ids.add("ems-esp"); char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; - snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%d/config", Mqtt::basename().c_str(), sensor.gpio()); + snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio()); Mqtt::publish_ha(topic, config.as()); @@ -601,17 +605,21 @@ AnalogSensor::Sensor::Sensor(const uint8_t gpio, const std::string & name, const std::string AnalogSensor::Sensor::name() const { if (name_.empty()) { char name[50]; - snprintf(name, sizeof(name), "Analog Sensor GPIO%d", gpio_); + snprintf(name, sizeof(name), "Analog Sensor GPIO %02d", gpio_); return name; } return name_; } -// set the counter value, id is gpio-no +// set the dig_out/counter/DAC/PWM value, id is gpio-no bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { float val; if (!Helpers::value2float(value, val)) { - return false; + bool b; + if (!Helpers::value2bool(value, b)) { + return false; + } + val = b ? 1 : 0; } for (auto & sensor : sensors_) { if (sensor.gpio() == gpio) { @@ -691,4 +699,4 @@ void AnalogSensor::test() { } #endif -} // namespace emsesp +} // namespace emsesp \ No newline at end of file diff --git a/src/console.cpp b/src/console.cpp index a809562b0..db912259b 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -339,7 +339,7 @@ static void setup_commands(std::shared_ptr & commands) { std::vector data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode std::string board_profile = Helpers::toUpper(arguments.front()); if (!to_app(shell).system_.load_board_profile(data, board_profile)) { - shell.println("Invalid board profile (S32, E32, MH-ET, NODEMCU, OLIMEX, OLIMEXPOE, C3MINI, S2MINI, CUSTOM)"); + shell.println("Invalid board profile (S32, E32, MH-ET, NODEMCU, OLIMEX, OLIMEXPOE, C3MINI, S2MINI, S3MINI, CUSTOM)"); return; } to_app(shell).webSettingsService.update( diff --git a/src/dallassensor.cpp b/src/dallassensor.cpp index 05cebb605..f3dd5c04f 100644 --- a/src/dallassensor.cpp +++ b/src/dallassensor.cpp @@ -75,6 +75,7 @@ void DallasSensor::reload() { }); for (auto & sensor : sensors_) { + remove_ha_topic(sensor.id()); sensor.ha_registered = false; // force HA configs to be re-created } } @@ -498,7 +499,10 @@ void DallasSensor::publish_values(const bool force) { // create the HA MQTT config // to e.g. homeassistant/sensor/ems-esp/dallassensor_28-233D-9497-0C03/config if (Mqtt::ha_enabled()) { - if (!sensor.ha_registered || force) { + if (!has_value && sensor.ha_registered) { + remove_ha_topic(sensor.id()); + sensor.ha_registered = false; + } else if (!sensor.ha_registered || force) { LOG_DEBUG("Recreating HA config for sensor ID %s", sensor.id().c_str()); StaticJsonDocument config; @@ -626,4 +630,4 @@ void DallasSensor::test() { } #endif -} // namespace emsesp +} // namespace emsesp \ No newline at end of file diff --git a/src/default_settings.h b/src/default_settings.h index 4366eb4c7..83e426435 100644 --- a/src/default_settings.h +++ b/src/default_settings.h @@ -236,6 +236,8 @@ enum { #define EMSESP_PLATFORM "ESP32-C3"; #elif CONFIG_IDF_TARGET_ESP32S2 #define EMSESP_PLATFORM "ESP32-S2"; +#elif CONFIG_IDF_TARGET_ESP32S3 +#define EMSESP_PLATFORM "ESP32-S3"; #elif CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE #define EMSESP_PLATFORM "ESP32"; #else diff --git a/src/device_library.h b/src/device_library.h index 351c1709a..5a92603fc 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -32,7 +32,7 @@ {115, DeviceType::BOILER, "Topline/GB162", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {121, DeviceType::BOILER, "Cascade MCM10", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {122, DeviceType::BOILER, "Proline", DeviceFlags::EMS_DEVICE_FLAG_NONE}, -{123, DeviceType::BOILER, "GBx72/Trendline/Cerapur/Greenstar Si/27i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, +{123, DeviceType::BOILER, "GBx72/Trendline/Cerapur/Greenstar Si/27i-30i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {131, DeviceType::BOILER, "GB212", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {132, DeviceType::BOILER, "GC7000F", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {133, DeviceType::BOILER, "Logano GB125/KB195i/Logamatic MC110", DeviceFlags::EMS_DEVICE_FLAG_NONE}, @@ -98,6 +98,7 @@ {172, DeviceType::THERMOSTAT, "Rego 2000/3000", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10 {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", DeviceFlags::EMS_DEVICE_FLAG_RC300}, // 0x10 // Thermostat - Sieger - 0x10 / 0x17 { 66, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote @@ -120,6 +121,7 @@ // Thermostat remote - 0x38 { 3, DeviceType::THERMOSTAT, "RT800", DeviceFlags::EMS_DEVICE_FLAG_RC100H}, {200, DeviceType::THERMOSTAT, "RC100H", DeviceFlags::EMS_DEVICE_FLAG_RC100H}, +{249, DeviceType::THERMOSTAT, "TR120RF", DeviceFlags::EMS_DEVICE_FLAG_RC100H}, // Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww) { 73, DeviceType::SOLAR, "SM10", DeviceFlags::EMS_DEVICE_FLAG_SM10}, @@ -140,6 +142,7 @@ {204, DeviceType::MIXER, "MP100", DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool // Heat Pumps - 0x38? This is a thermostat like RC100H +// also prod-id of wifi module and wireless base {252, DeviceType::HEATPUMP, "HP Module", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // Heat Pumps - 0x53 diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 59fae76d4..e940e78a9 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -83,6 +83,8 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_telegram_type(0x48B, "HPPumps", true, MAKE_PF_CB(process_HpPumps)); register_telegram_type(0x491, "HPAdditionalHeater", true, MAKE_PF_CB(process_HpAdditionalHeater)); register_telegram_type(0x499, "HPDhwSettings", true, MAKE_PF_CB(process_HpDhwSettings)); + register_telegram_type(0x49C, "HPSettings2", true, MAKE_PF_CB(process_HpSettings2)); + register_telegram_type(0x49D, "HPSettings3", true, MAKE_PF_CB(process_HpSettings3)); } /* @@ -103,7 +105,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &tapwaterActive_, DeviceValueType::BOOL, FL_(tapwaterActive), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &selFlowTemp_, DeviceValueType::UINT, FL_(selFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flow_temp)); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingPumpMod_, DeviceValueType::UINT, FL_(heatingPumpMod), DeviceValueUOM::PERCENT); - register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingPump2Mod_, DeviceValueType::UINT, FL_(heatingPump2Mod), DeviceValueUOM::PERCENT); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &outdoorTemp_, DeviceValueType::SHORT, @@ -180,6 +181,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const DeviceValueTAG::TAG_DEVICE_DATA, &boil2HystOff_, DeviceValueType::INT, FL_(boil2HystOff), DeviceValueUOM::DEGREES_R, MAKE_CF_CB(set_hyst2_off), 0, 20); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setFlowTemp_, DeviceValueType::UINT, FL_(setFlowTemp), DeviceValueUOM::DEGREES); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &setBurnPow_, DeviceValueType::UINT, FL_(setBurnPow), DeviceValueUOM::PERCENT); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &absBurnPow_, DeviceValueType::UINT, FL_(absBurnPow), DeviceValueUOM::PERCENT); register_device_value( DeviceValueTAG::TAG_DEVICE_DATA, &selBurnPow_, DeviceValueType::UINT, FL_(selBurnPow), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_burn_power), 0, 254); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &curBurnPow_, DeviceValueType::UINT, FL_(curBurnPow), DeviceValueUOM::PERCENT); @@ -475,12 +477,21 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const 10, 1000); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, - &auxMaxTemp_, + &auxMaxLimit_, DeviceValueType::UINT, - DeviceValueNumOp::DV_NUMOP_MUL10, - FL_(auxMaxTemp), + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(auxMaxLimit), DeviceValueUOM::K, - MAKE_CF_CB(set_auxMaxTemp), + MAKE_CF_CB(set_auxMaxLimit), + 0, + 10); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &auxLimitStart_, + DeviceValueType::UINT, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(auxLimitStart), + DeviceValueUOM::K, + MAKE_CF_CB(set_auxLimitStart), 0, 10); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, @@ -524,6 +535,20 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const FL_(silentMode), DeviceValueUOM::NONE, MAKE_CF_CB(set_silentMode)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &silentFrom_, + DeviceValueType::UINT, + DeviceValueNumOp::DV_NUMOP_MUL15, + FL_(silentFrom), + DeviceValueUOM::MINUTES, + MAKE_CF_CB(set_silentFrom)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &silentTo_, + DeviceValueType::UINT, + DeviceValueNumOp::DV_NUMOP_MUL15, + FL_(silentTo), + DeviceValueUOM::MINUTES, + MAKE_CF_CB(set_silentTo)); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &minTempSilent_, DeviceValueType::INT, @@ -555,6 +580,40 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const MAKE_CF_CB(set_tempDiffCool), 3, 10); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &vp_cooling_, DeviceValueType::BOOL, FL_(vp_cooling), DeviceValueUOM::NONE, MAKE_CF_CB(set_vp_cooling)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatCable_, DeviceValueType::BOOL, FL_(heatCable), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatCable)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &VC0valve_, DeviceValueType::BOOL, FL_(VC0valve), DeviceValueUOM::NONE, MAKE_CF_CB(set_VC0valve)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &primePump_, DeviceValueType::BOOL, FL_(primePump), DeviceValueUOM::NONE, MAKE_CF_CB(set_primePump)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &primePumpMod_, + DeviceValueType::UINT, + FL_(primePumpMod), + DeviceValueUOM::PERCENT, + MAKE_CF_CB(set_primePumpMod)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &hp3wayValve_, + DeviceValueType::BOOL, + FL_(hp3wayValve), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_hp3wayValve)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &elHeatStep1_, + DeviceValueType::BOOL, + FL_(elHeatStep1), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_elHeatStep1)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &elHeatStep2_, + DeviceValueType::BOOL, + FL_(elHeatStep2), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_elHeatStep2)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &elHeatStep3_, + DeviceValueType::BOOL, + FL_(elHeatStep3), + DeviceValueUOM::NONE, + MAKE_CF_CB(set_elHeatStep3)); // heatpump DHW settings register_device_value(DeviceValueTAG::TAG_BOILER_DATA_WW, &wwAlternatingOper_, @@ -901,11 +960,11 @@ void Boiler::process_UBAParameterWW(std::shared_ptr telegram) { // has_bitupdate(telegram, wwEquipt_,0,3); // 8=boiler has ww has_update(telegram, wwActivated_, 1); // 0xFF means on has_update(telegram, wwSelTemp_, 2); - has_update(telegram, wwHystOn_, 3); // Hyst on (default -5) - has_update(telegram, wwHystOff_, 4); // Hyst off (default -1) - has_update(telegram, wwFlowTempOffset_, 5); // default 40 - has_update(telegram, wwCircPump_, 6); // 0xFF means on - has_enumupdate(telegram, wwCircMode_, 7, 1); // 1=1x3min 6=6x3min 7=continuous + has_update(telegram, wwHystOn_, 3); // Hyst on (default -5) + has_update(telegram, wwHystOff_, 4); // Hyst off (default -1) + has_update(telegram, wwFlowTempOffset_, 5); // default 40 + has_update(telegram, wwCircPump_, 6); // 0xFF means on + has_update(telegram, wwCircMode_, 7); // 0=off, 1=1x3min 6=6x3min 7=continuous has_update(telegram, wwDisinfectionTemp_, 8); has_bitupdate(telegram, wwChargeType_, 10, 0); // 0 = charge pump, 0xff = 3-way valve @@ -1018,9 +1077,11 @@ void Boiler::process_UBAMonitorSlow(std::shared_ptr telegram) { /* * UBAMonitorSlowPlus2 - type 0xE3 * 88 00 E3 00 04 00 00 00 00 01 00 00 00 00 00 02 22 2B 64 46 01 00 00 61 + * https://github.com/Th3M3/buderus_ems-wiki/blob/master/Quelle_08.md + * https://github.com/emsesp/EMS-ESP32/issues/908 */ void Boiler::process_UBAMonitorSlowPlus2(std::shared_ptr telegram) { - has_update(telegram, heatingPump2Mod_, 13); // Heat Pump Modulation + has_update(telegram, absBurnPow_, 13); // current burner absolute power (percent of rating plate power) } /* @@ -1078,7 +1139,7 @@ void Boiler::process_UBAParameterWWPlus(std::shared_ptr telegram has_update(telegram, wwHystOff_, 8); has_update(telegram, wwFlowTempOffset_, 9); has_update(telegram, wwCircPump_, 10); // 0x01 means yes - has_enumupdate(telegram, wwCircMode_, 11, 1); // 1=1x3min... 6=6x3min, 7=continuous + has_update(telegram, wwCircMode_, 11); // 0=off, 1=1x3min... 6=6x3min, 7=continuous has_update(telegram, wwDisinfectionTemp_, 12); // setting here, status in E9 has_update(telegram, wwAlternatingOper_, 14); // 0x01 means enabled has_update(telegram, wwSelTempSingle_, 16); @@ -1105,6 +1166,7 @@ void Boiler::process_UBAMonitorWWPlus(std::shared_ptr telegram) has_update(telegram, wwSetTemp_, 0); has_update(telegram, wwCurTemp_, 1); has_update(telegram, wwCurTemp2_, 3); + has_update(telegram, wwCurFlow_, 11); has_update(telegram, wwWorkM_, 14, 3); // force to 3 bytes has_update(telegram, wwStarts_, 17, 3); // force to 3 bytes @@ -1391,8 +1453,7 @@ void Boiler::process_UBAErrorMessage2(std::shared_ptr telegram) snprintf(&code[3], sizeof(code) - 3, "(%d) %02d.%02d.%04d %02d:%02d - now", codeNo, start_day, start_month, start_year, start_hour, start_min); } } else { // no clock, the uptime is stored https://github.com/emsesp/EMS-ESP32/issues/121 - uint32_t starttime = 0; - uint32_t endtime = 0; + uint32_t starttime, endtime; telegram->read_value(starttime, 11, 3); telegram->read_value(endtime, 16, 3); snprintf(&code[3], sizeof(code) - 3, "(%d) @uptime %d - %d min", codeNo, starttime, endtime); @@ -1440,6 +1501,8 @@ void Boiler::process_HpSilentMode(std::shared_ptr telegram) { has_update(telegram, hpHystCool_, 35); // is / 5, maybe offset swapped with pool has_update(telegram, hpHystPool_, 33); // is / 5 has_update(telegram, hpCircPumpWw_, 46); + has_update(telegram, silentFrom_, 52); // in steps of 15 min + has_update(telegram, silentTo_, 53); // in steps of 15 min } // Boiler(0x08) -B-> All(0x00), ?(0x0488), data: 8E 00 00 00 00 00 01 03 @@ -1462,7 +1525,8 @@ void Boiler::process_HpAdditionalHeater(std::shared_ptr telegram has_update(telegram, auxHeaterOff_, 2); has_update(telegram, auxHeatMode_, 4); // eco/comfort has_update(telegram, tempParMode_, 5); - has_update(telegram, auxMaxTemp_, 14); // is *10 + has_update(telegram, auxMaxLimit_, 14); // is * 10 + has_update(telegram, auxLimitStart_, 15); // is * 10 has_update(telegram, auxHeaterDelay_, 16); // is / 10 } @@ -1474,6 +1538,25 @@ void Boiler::process_HpDhwSettings(std::shared_ptr telegram) { has_update(telegram, wwEcoPlusOffTemp_, 5); } +// 0x49C: +// Boiler(0x08) -B-> All(0x00), ?(0x049C), data: 00 00 00 00 +void Boiler::process_HpSettings2(std::shared_ptr telegram) { + has_update(telegram, vp_cooling_, 3); +} + +// 0x49D +// Boiler(0x08) -B-> All(0x00), ?(0x049D), data: 00 00 00 00 00 00 00 00 00 00 00 00 +void Boiler::process_HpSettings3(std::shared_ptr telegram) { + has_update(telegram, heatCable_, 2); + has_update(telegram, VC0valve_, 3); + has_update(telegram, primePump_, 4); + has_update(telegram, primePumpMod_, 5); + has_update(telegram, hp3wayValve_, 6); + has_update(telegram, elHeatStep1_, 7); + has_update(telegram, elHeatStep2_, 8); + has_update(telegram, elHeatStep3_, 9); +} + /* * Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat * thermostat always overwrites settings in boiler @@ -1900,13 +1983,15 @@ bool Boiler::set_pump_delay(const char * value, const int8_t id) { // note some boilers do not have this setting, than it's done by thermostat // on a RC35 it's by EMSESP::send_write_request(0x37, 0x10, 2, &set, 1, 0); (set is 1,2,3) 1=hot, 2=eco, 3=intelligent // on a RC310 it's 1=high, 2=eco +// eco key on controller: tele.05, offset 70: 0xAA =eco, 0x55= comfort, https://github.com/emsesp/EMS-ESP32/issues/908 bool Boiler::set_ww_mode(const char * value, const int8_t id) { uint8_t set; - uint8_t comfort[] = {0x00, 0xD8, 0xEC}; + uint8_t comfort[] = {0x00, 0xD8, 0xEC}; // heat, eco, intelligent if (is_fetch(EMS_TYPE_UBAParameterWWPlus)) { if (Helpers::value2enum(value, set, FL_(enum_comfort1))) { write_command(EMS_TYPE_UBAParameterWWPlus, 13, comfort[set], EMS_TYPE_UBAParameterWWPlus); + write_command(0x05, 70, set ? 0xAA : 0x55); // return true; } } else { @@ -2043,7 +2128,7 @@ bool Boiler::set_ww_circulation_pump(const char * value, const int8_t id) { } // Set the mode of circulation, 1x3min, ... 6x3min, continuous -// true = on, false = off +// if 0-off, switching is not possibe, if 1-7 switching to off is not possible bool Boiler::set_ww_circulation_mode(const char * value, const int8_t id) { uint8_t v; if (!Helpers::value2enum(value, v, FL_(enum_freq))) { @@ -2051,9 +2136,9 @@ bool Boiler::set_ww_circulation_mode(const char * value, const int8_t id) { } if (is_fetch(EMS_TYPE_UBAParameterWWPlus)) { - write_command(EMS_TYPE_UBAParameterWWPlus, 11, v + 1, EMS_TYPE_UBAParameterWWPlus); + write_command(EMS_TYPE_UBAParameterWWPlus, 11, v, EMS_TYPE_UBAParameterWWPlus); } else { - write_command(EMS_TYPE_UBAParameterWW, 7, v + 1, EMS_TYPE_UBAParameterWW); + write_command(EMS_TYPE_UBAParameterWW, 7, v, EMS_TYPE_UBAParameterWW); } return true; @@ -2255,6 +2340,24 @@ bool Boiler::set_silentMode(const char * value, const int8_t id) { return true; } +bool Boiler::set_silentFrom(const char * value, const int8_t id) { + int v; + if (!Helpers::value2number(value, v)) { + return false; + } + write_command(0x484, 52, v / 15, 0x484); + return true; +} + +bool Boiler::set_silentTo(const char * value, const int8_t id) { + int v; + if (!Helpers::value2number(value, v)) { + return false; + } + write_command(0x484, 53, v / 15, 0x484); + return true; +} + bool Boiler::set_minTempSilent(const char * value, const int8_t id) { int v; if (Helpers::value2temperature(value, v)) { @@ -2311,10 +2414,10 @@ bool Boiler::set_auxHeatMode(const char * value, const int8_t id) { return false; } -bool Boiler::set_auxMaxTemp(const char * value, const int8_t id) { +bool Boiler::set_auxLimit(const char * value, const int8_t id) { float v; if (Helpers::value2float(value, v)) { - write_command(0x491, 14, (uint8_t)(v * 10), 0x491); + write_command(0x491, id, (uint8_t)(v * 10), 0x491); return true; } return false; @@ -2376,17 +2479,76 @@ bool Boiler::set_hpCircPumpWw(const char * value, const int8_t id) { return false; } +bool Boiler::set_vp_cooling(const char * value, const int8_t id) { + bool v; + if (Helpers::value2bool(value, v)) { + write_command(0x49C, 3, v ? 1 : 0, 0x49C); + return true; + } + return false; +} + +bool Boiler::set_heatCable(const char * value, const int8_t id) { + bool v; + if (Helpers::value2bool(value, v)) { + write_command(0x49D, 2, v ? 1 : 0, 0x49D); + return true; + } + return false; +} + +bool Boiler::set_VC0valve(const char * value, const int8_t id) { + bool v; + if (Helpers::value2bool(value, v)) { + write_command(0x49D, 3, v ? 1 : 0, 0x49D); + return true; + } + return false; +} + +bool Boiler::set_primePump(const char * value, const int8_t id) { + bool v; + if (Helpers::value2bool(value, v)) { + write_command(0x49D, 4, v ? 1 : 0, 0x49D); + return true; + } + return false; +} + +bool Boiler::set_primePumpMod(const char * value, const int8_t id) { + int v; + if (Helpers::value2number(value, v)) { + write_command(0x49D, 5, v, 0x49D); + return true; + } + return false; +} + +bool Boiler::set_hp3wayValve(const char * value, const int8_t id) { + bool v; + if (Helpers::value2bool(value, v)) { + write_command(0x49D, 6, v ? 1 : 0, 0x49D); + return true; + } + return false; +} + +bool Boiler::set_elHeatStep(const char * value, const int8_t id) { + bool v; + if (Helpers::value2bool(value, v)) { + write_command(0x49D, 6 + id, v ? 1 : 0, 0x49D); + return true; + } + return false; +} + // dhw alternating operation, turn on/off; heatpumps only? bool Boiler::set_wwAlternatingOper(const char * value, const int8_t id) { bool v; if (!Helpers::value2bool(value, v)) { return false; } - // if (is_fetch(EMS_TYPE_UBAParameterWWPlus)) { // do we need/want this? write_command(EMS_TYPE_UBAParameterWWPlus, 14, v ? 1 : 0, EMS_TYPE_UBAParameterWWPlus); - // } else { - // write_command(EMS_TYPE_UBAParameterWW, 14, v ? 0xFF : 0, EMS_TYPE_UBAParameterWW); - // } return true; } @@ -2400,4 +2562,4 @@ bool Boiler::set_wwAltOpPrio(const char * value, const int8_t id) { return false; } -} // namespace emsesp \ No newline at end of file +} // namespace emsesp diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 796c08563..fc1a906ac 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -101,7 +101,7 @@ class Boiler : public EMSdevice { uint8_t tapwaterActive_; // Hot tap water is on/off uint8_t selFlowTemp_; // Selected flow temperature uint8_t selBurnPow_; // Burner max power % (can be > 100%) - uint8_t heatingPump2Mod_; // heatpump modulation from 0xE3 (heatpumps) + uint8_t absBurnPow_; // absolute burner power in % of rating plate uint8_t heatingPumpMod_; // Pump modulation % int16_t outdoorTemp_; // Outside temperature uint16_t curFlowTemp_; // Current flow temperature @@ -218,13 +218,16 @@ class Boiler : public EMSdevice { uint8_t pvCooling_; uint8_t manDefrost_; uint8_t auxHeatMode_; - uint8_t auxMaxTemp_; + uint8_t auxMaxLimit_; + uint8_t auxLimitStart_; uint8_t auxHeaterOnly_; uint8_t auxHeaterOff_; uint8_t auxHeaterStatus_; uint16_t auxHeaterDelay_; uint8_t silentMode_; int8_t minTempSilent_; + uint8_t silentFrom_; + uint8_t silentTo_; int8_t tempParMode_; int8_t auxHeatMixValve_; uint16_t hpHystHeat_; @@ -238,6 +241,16 @@ class Boiler : public EMSdevice { uint8_t wwEcoOffTemp_; uint8_t wwEcoPlusOffTemp_; + uint8_t vp_cooling_; + uint8_t heatCable_; + uint8_t VC0valve_; + uint8_t primePump_; + uint8_t primePumpMod_; + uint8_t hp3wayValve_; + uint8_t elHeatStep1_; + uint8_t elHeatStep2_; + uint8_t elHeatStep3_; + /* // Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat // thermostat always overwrites settings in boiler @@ -290,6 +303,8 @@ class Boiler : public EMSdevice { void process_HpValve(std::shared_ptr telegram); void process_HpPumps(std::shared_ptr telegram); void process_HpDhwSettings(std::shared_ptr telegram); + void process_HpSettings2(std::shared_ptr telegram); + void process_HpSettings3(std::shared_ptr telegram); // commands - none of these use the additional id parameter bool set_ww_mode(const char * value, const int8_t id); @@ -361,16 +376,25 @@ class Boiler : public EMSdevice { } bool set_silentMode(const char * value, const int8_t id); bool set_minTempSilent(const char * value, const int8_t id); + bool set_silentFrom(const char * value, const int8_t id); + bool set_silentTo(const char * value, const int8_t id); bool set_additionalHeaterOnly(const char * value, const int8_t id); bool set_additionalHeater(const char * value, const int8_t id); bool set_additionalHeaterDelay(const char * value, const int8_t id); bool set_tempParMode(const char * value, const int8_t id); bool set_auxHeatMode(const char * value, const int8_t id); - bool set_auxMaxTemp(const char * value, const int8_t id); bool set_manDefrost(const char * value, const int8_t id); bool set_pvCooling(const char * value, const int8_t id); bool set_hpCircPumpWw(const char * value, const int8_t id); + bool set_auxLimit(const char * value, const int8_t id); + inline bool set_auxMaxLimit(const char * value, const int8_t id) { + return set_auxLimit(value, 14); + } + inline bool set_auxLimitStart(const char * value, const int8_t id) { + return set_auxLimit(value, 15); + } + bool set_hpHyst(const char * value, const int8_t id); inline bool set_hpHystHeat(const char * value, const int8_t id) { return set_hpHyst(value, 37); @@ -398,6 +422,22 @@ class Boiler : public EMSdevice { inline bool set_wwEcoPlusOffTemp(const char * value, const int8_t id) { return set_wwOffTemp(value, 5); } + bool set_vp_cooling(const char * value, const int8_t id); + bool set_heatCable(const char * value, const int8_t id); + bool set_VC0valve(const char * value, const int8_t id); + bool set_primePump(const char * value, const int8_t id); + bool set_primePumpMod(const char * value, const int8_t id); + bool set_hp3wayValve(const char * value, const int8_t id); + bool set_elHeatStep(const char * value, const int8_t id); + inline bool set_elHeatStep1(const char * value, const int8_t id) { + return set_elHeatStep(value, 1); + } + inline bool set_elHeatStep2(const char * value, const int8_t id) { + return set_elHeatStep(value, 2); + } + inline bool set_elHeatStep3(const char * value, const int8_t id) { + return set_elHeatStep(value, 3); + } bool set_wwAlternatingOper(const char * value, const int8_t id); bool set_wwAltOpPrio(const char * value, const int8_t id); inline bool set_wwAltOpPrioHeat(const char * value, const int8_t id) { diff --git a/src/devices/heatsource.cpp b/src/devices/heatsource.cpp index b9b0812a9..f0b8b20c6 100644 --- a/src/devices/heatsource.cpp +++ b/src/devices/heatsource.cpp @@ -74,6 +74,12 @@ Heatsource::Heatsource(uint8_t device_type, uint8_t device_id, uint8_t product_i 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); @@ -161,6 +167,12 @@ Heatsource::Heatsource(uint8_t device_type, uint8_t device_id, uint8_t product_i 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(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); } // cascaded heating sources, only some values per individual heatsource (hs) @@ -214,6 +226,7 @@ void Heatsource::process_UBAMonitorFastPlus(std::shared_ptr tele void Heatsource::process_amTempMessage(std::shared_ptr telegram) { has_update(telegram, curFlowTemp_, 0); // TB4 has_update(telegram, retTemp_, 2); // TR2 + has_update(telegram, flueGasTemp_, 4); has_update(telegram, aFlowTemp_, 6); has_update(telegram, aRetTemp_, 8); has_update(telegram, cylTopTemp_, 10); @@ -226,14 +239,11 @@ void Heatsource::process_amTempMessage(std::shared_ptr telegram) void Heatsource::process_amStatusMessage(std::shared_ptr telegram) { has_update(telegram, aPumpMod_, 0); // PR1 // offset 1: bitfield 01-pump on, 02-VR1 opening, 04-VR1 closing, 08-VB1 opening, 10-VB1 closing - // uint8_t stat = aPump_ | setValveBuffer_ << 3 | setValveReturn_ << 1; - // if (telegram->read_value(stat, 1)) { - // has_update(aPump_, stat & 0x01); - // has_update(valveBuffer_, (stat >> 3) & 0x03); - // has_update(valveReturn_, (stat >> 1) & 0x03); - // } // actually we dont know the offset of VR2 // has_update(telegram, valveBypass_, ?); // VR2 + has_bitupdate(telegram, burner_, 1, 5); + has_bitupdate(telegram, aPump_, 1, 0); + has_update(telegram, heatRequest_, 2); // percent has_update(telegram, valveReturn_, 4); // VR1, percent has_update(telegram, valveBuffer_, 5); // VB1, percent } @@ -275,6 +285,8 @@ void Heatsource::process_amCommandMessage(std::shared_ptr telegr // Rx: 60 00 FF 00 04 50 00 FF 00 FF FF 00 0D 00 01 00 00 00 00 01 03 01 00 03 00 2D 19 C8 02 94 00 4A // Rx: 60 00 FF 19 04 50 00 FF FF 39 void Heatsource::process_amExtraMessage(std::shared_ptr telegram) { + has_update(telegram, blockRemain_, 24); // minutes + has_update(telegram, blockRemainWw_, 25); // minutes } #pragma GCC diagnostic pop diff --git a/src/devices/heatsource.h b/src/devices/heatsource.h index 209c3cb0e..3c52417cc 100644 --- a/src/devices/heatsource.h +++ b/src/devices/heatsource.h @@ -44,9 +44,16 @@ class Heatsource : public EMSdevice { uint8_t aPumpMod_; // PR1 - percent uint8_t valveBuffer_; // VB1 uint8_t valveReturn_; // VR1 + uint16_t flueGasTemp_; // uint8_t valveBypass_; // VR2 position unknown // uint8_t heatSource_; // OEV + uint8_t burner_; // bit 5, offset 1, 54E + uint8_t aPump_; // bit 0, offset 1, 54E + uint8_t heatRequest_; // offset 2, percent + uint8_t blockRemain_; // offset 24, 550 min + uint8_t blockRemainWw_; // offset 25, 550 min + // Settings: uint8_t vr2Config_; // pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone) uint8_t ahsActivated_; // pos 00: Alternate heat source activation: No(00),Yes(01) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 68bd3116c..f95b6d9fa 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -496,6 +496,7 @@ void EMSdevice::add_device_value(uint8_t tag, std::string custom_fullname = std::string(""); // custom fullname auto short_name = name[0]; // entity name bool has_cmd = (f != nullptr); // is it a command? + bool ignore = false; // ignore this entity? // get fullname, getting translation if it exists const char * const * fullname; @@ -532,7 +533,8 @@ void EMSdevice::add_device_value(uint8_t tag, if (shortname == entity) { // get Mask uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); - state = mask << 4; // set state high bits to flag, turn off active and ha flags + state = mask << 4; // set state high bits to flag, turn off active and ha flags + ignore = (mask & 0x80) == 0x80; // do not register // see if there is a custom name in the entity string if (has_custom_name) { custom_fullname = entity_id.substr(custom_name_pos + 1); @@ -544,6 +546,10 @@ void EMSdevice::add_device_value(uint8_t tag, } }); + if (ignore) { + return; + } + // add the device entity devicevalues_.emplace_back( device_type_, tag, value_p, type, options, options_single, numeric_operator, short_name, fullname, custom_fullname, uom, has_cmd, min, max, state); diff --git a/src/emsesp.cpp b/src/emsesp.cpp index a898c445a..bc036898b 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -1034,12 +1034,6 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const device_p->device_type = DeviceType::HEATSOURCE; break; } - } else if (device.device_type == DeviceType::HEATSOURCE) { - device_p = &device; - if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) { // AHS as only heatsource on d 0x08 - device_p->device_type = DeviceType::BOILER; - } - break; } else { // it's not a boiler, but we have a match device_p = &device; @@ -1060,6 +1054,17 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const auto device_type = device_p->device_type; auto flags = device_p->flags; + // check for integrated modules with same product id + if (device_type == DeviceType::HEATPUMP) { + if (device_id == EMSdevice::EMS_DEVICE_ID_MODEM) { + device_type = DeviceType::GATEWAY; + name = "WiFi module"; + } else if (device_id == EMSdevice::EMS_DEVICE_ID_RFBASE) { + device_type = DeviceType::CONNECT; + name = "Wireless sensor base"; + } + } + // empty reply to version, read a generic device from database if (product_id == 0) { // check for known device IDs diff --git a/src/helpers.cpp b/src/helpers.cpp index 41d90861d..b50b76c38 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -249,10 +249,11 @@ char * Helpers::render_value(char * result, const double value, const int8_t for return nullptr; } - uint32_t p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000}; + uint32_t p[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000}; char * ret = result; - auto whole = (int32_t)value; + double v = value < 0 ? value - 1.0 / (2 * p[format]) : value + 1.0 / (2 * p[format]); + auto whole = (int32_t)v; itoa(whole, result, 10); @@ -261,7 +262,7 @@ char * Helpers::render_value(char * result, const double value, const int8_t for } *result++ = '.'; - auto decimal = abs((int32_t)((value - whole) * p[format])); + auto decimal = abs((int32_t)((v - whole) * p[format])); for (int8_t i = 1; i < format; i++) { if (decimal < p[i]) { *result++ = '0'; // add leading zeros @@ -776,7 +777,7 @@ const char * Helpers::translated_word(const char * const * strings, const bool f } // see how many translations we have for this entity. if there is no translation for this, revert to EN - if (force_en || (Helpers::count_items(strings) >= language_index + 1 && strlen(strings[language_index]))) { + if (!force_en && (Helpers::count_items(strings) >= language_index + 1 && strlen(strings[language_index]))) { index = language_index; } return strings[index]; diff --git a/src/locale_common.h b/src/locale_common.h index 26dac940a..ecc91faa9 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -241,7 +241,7 @@ MAKE_PSTR_ENUM(enum_progMode, FL_(prog1), FL_(prog2)) MAKE_PSTR_ENUM(enum_progMode4, FL_(proga), FL_(progb), FL_(progc), FL_(progd), FL_(proge), FL_(progf)) MAKE_PSTR_ENUM(enum_climate, FL_(seltemp), FL_(roomtemp)) MAKE_PSTR_ENUM(enum_charge, FL_(chargepump), FL_(3wayvalve)) -MAKE_PSTR_ENUM(enum_freq, FL_(1x3min), FL_(2x3min), FL_(3x3min), FL_(4x3min), FL_(5x3min), FL_(6x3min), FL_(continuous)) +MAKE_PSTR_ENUM(enum_freq, FL_(off), FL_(1x3min), FL_(2x3min), FL_(3x3min), FL_(4x3min), FL_(5x3min), FL_(6x3min), FL_(continuous)) MAKE_PSTR_ENUM(enum_off_time_date_manual, FL_(off), FL_(time), FL_(date), FL_(manual)) MAKE_PSTR_ENUM(enum_comfort, FL_(hot), FL_(eco), FL_(intelligent)) MAKE_PSTR_ENUM(enum_comfort1, FL_(high_comfort), FL_(eco)) diff --git a/src/locale_translations.h b/src/locale_translations.h index 91b25dc2a..a463239e0 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -34,18 +34,18 @@ // device types, as display in Web and Console // TODO translate -MAKE_PSTR_LIST(boiler_device, "Boiler", "Kessel", "Boiler") -MAKE_PSTR_LIST(thermostat_device, "Thermostat", "Thermostat", "Thermostaat") -MAKE_PSTR_LIST(heatpump_device, "Heat Pump", "Wärmepumpe", "Warmtepomp") -MAKE_PSTR_LIST(solar_device, "Solar Module", "Solarmodul", "Solar Module") -MAKE_PSTR_LIST(connect_device, "Connect Module", "Verbindungsmodul", "Connect Module") -MAKE_PSTR_LIST(mixer_device, "Mixer Module", "Mischermodul", "Mixer Module") -MAKE_PSTR_LIST(controller_device, "Controller Module", "Kontrollmodul", "Controller Module") -MAKE_PSTR_LIST(switch_device, "Switch Module", "Schaltmodul", "Switch Module") -MAKE_PSTR_LIST(gateway_device, "Gateway Module", "Gateway Modul", "Gateway Module") -MAKE_PSTR_LIST(alert_device, "Alert Module", "Alarmmodul", "Alert Module") -MAKE_PSTR_LIST(pump_device, "Pump Module", "Pumpenmodul", "Pump Module") -MAKE_PSTR_LIST(heatsource_device, "Heatsource", "Heizquelle", "Heatsource") +MAKE_PSTR_LIST(boiler_device, "Boiler", "Kessel", "Boiler", "Värmeanna") +MAKE_PSTR_LIST(thermostat_device, "Thermostat", "Thermostat", "Thermostaat", "Termostat") +MAKE_PSTR_LIST(heatpump_device, "Heat Pump", "Wärmepumpe", "Warmtepomp", "Värmepump") +MAKE_PSTR_LIST(solar_device, "Solar Module", "Solarmodul", "Solar Module", "Solmodul") +MAKE_PSTR_LIST(connect_device, "Connect Module", "Verbindungsmodul", "Connect Module", "Uppkopplingsmodul") +MAKE_PSTR_LIST(mixer_device, "Mixer Module", "Mischermodul", "Mixer Module", "Blandningsmodul") +MAKE_PSTR_LIST(controller_device, "Controller Module", "Kontrollmodul", "Controller Module", "Styrmodul") +MAKE_PSTR_LIST(switch_device, "Switch Module", "Schaltmodul", "Switch Module", "Relämodul") +MAKE_PSTR_LIST(gateway_device, "Gateway Module", "Gateway Modul", "Gateway Module", "Gateway") +MAKE_PSTR_LIST(alert_device, "Alert Module", "Alarmmodul", "Alert Module", "Larmmodul") +MAKE_PSTR_LIST(pump_device, "Pump Module", "Pumpenmodul", "Pump Module", "Pumpmodul") +MAKE_PSTR_LIST(heatsource_device, "Heatsource", "Heizquelle", "Heatsource", "Värmekälla") MAKE_PSTR_LIST(sensors_device, "Sensors", "Sensoren", "Sensoren", "Sensorer", "czujniki", "Sensorer", "Capteurs") // commands @@ -157,7 +157,7 @@ MAKE_PSTR_LIST(blocking, "blocking", "Blockierung", "Blokkering", "Blockering", MAKE_PSTR_LIST(extern, "extern", "extern", "extern", "extern", "zewnętrzny", "ekstern", "externe") MAKE_PSTR_LIST(intern, "intern", "intern", "intern", "intern", "wewnętrzny", "intern", "interne") MAKE_PSTR_LIST(lower, "lower", "niedirger", "lager", "lägre", "mniejszy", "nedre", "inférieur") -MAKE_PSTR_LIST(error, "error", "Fehler", "error", "error", "błąd", "", "erreur") // TODO translate +MAKE_PSTR_LIST(error, "error", "Fehler", "error", "Fel", "błąd", "", "erreur") // TODO translate MAKE_PSTR_LIST(na, "n/a", "n/a", "n/a", "n/a", "nd.", "", "n/c") // TODO translate // boiler @@ -187,13 +187,13 @@ MAKE_PSTR_LIST(valve, "valve", "Ventil", "Klep", "Ventil", "zawór", "ventil", " MAKE_PSTR_LIST(none, "none", "keine", "geen", "ingen", "brak", "ingen", "aucun") MAKE_PSTR_LIST(hot_water, "hot water", "Warmwasser", "warm water", "varmvatten", "c.w.u.", "varmtvann", "eau chaude") MAKE_PSTR_LIST(pool, "pool", "Pool", "zwembad", "pool", "basen", "basseng", "piscine") -MAKE_PSTR_LIST(outside_temp_alt, "outside temperature alt.", "Außentemp. alternativ", "", "", "temp. zewn. alternat.", "", "température extérieure alternative") // TODO translate -MAKE_PSTR_LIST(outside_temp_par, "outside temperature parallel", "Außentemp. parallel", "", "", "temp. zewn. równoległa", "", "température extérieure parallèle") // TODO translate -MAKE_PSTR_LIST(hp_prefered, "heatpump prefered", "Wärmepumpe bevorzugt", "", "", "preferowana pompa ciepła", "", "pompe à chaleur préférée") // TODO translate -MAKE_PSTR_LIST(boiler_only, "boiler only", "nur Kessel", "", "", "tylko kocioł", "", "chaudière uniquement") // TODO translate -MAKE_PSTR_LIST(reduced_output, "reduced output", "Reduzierte Leistung", "", "", "zmniejszona wydajność", "", "sortie réduite") // TODO translate -MAKE_PSTR_LIST(switchoff, "switch off hp", "WP ausschalten", "", "", "wyłącz pompę ciepła", "", "éteindre la PAC") // TODO translate -MAKE_PSTR_LIST(perm, "perm. reduced", "perm. reduziert", "", "", "stale zmniejszona wydajność", "", "réduction permanente") // TODO translate +MAKE_PSTR_LIST(outside_temp_alt, "outside temperature alt.", "Außentemp. alternativ", "", "Alternativ utomhustemp.", "temp. zewn. alternat.", "", "température extérieure alternative") // TODO translate +MAKE_PSTR_LIST(outside_temp_par, "outside temperature parallel", "Außentemp. parallel", "", "Parallell utomhustemp.", "temp. zewn. równoległa", "", "température extérieure parallèle") // TODO translate +MAKE_PSTR_LIST(hp_prefered, "heatpump prefered", "Wärmepumpe bevorzugt", "", "Värmepump föredraget", "preferowana pompa ciepła", "", "pompe à chaleur préférée") // TODO translate +MAKE_PSTR_LIST(boiler_only, "boiler only", "nur Kessel", "", "Värmepanna enbart", "tylko kocioł", "", "chaudière uniquement") // TODO translate +MAKE_PSTR_LIST(reduced_output, "reduced output", "Reduzierte Leistung", "", "Reducerad produktion", "zmniejszona wydajność", "", "sortie réduite") // TODO translate +MAKE_PSTR_LIST(switchoff, "switch off hp", "WP ausschalten", "", "Värmepump avstängd", "wyłącz pompę ciepła", "", "éteindre la PAC") // TODO translate +MAKE_PSTR_LIST(perm, "perm. reduced", "perm. reduziert", "", "Permanent reducerad", "stale zmniejszona wydajność", "", "réduction permanente") // TODO translate // thermostat MAKE_PSTR_LIST(seltemp, "selTemp", "Solltemperatur", "Doeltemperatuur", "Börtemperatur", "temperatura zadana", "innstilt temperatur", "consigne température") @@ -270,8 +270,8 @@ MAKE_PSTR_LIST(heatingActive, "heatingactive", "heating active", "Heizen aktiv", MAKE_PSTR_LIST(tapwaterActive, "tapwateractive", "tapwater active", "Warmwasser aktiv", "Warm water actief", "Varmvatten aktiv", "c.w.u. aktywne", "varmtvann aktiv", "eau chaude active") MAKE_PSTR_LIST(selFlowTemp, "selflowtemp", "selected flow temperature", "Sollwert Vorlauftemperatur", "Ingestelde aanvoertemperatuur", "Börvärde Flödestemperatur", "wybrana temperatura zasilania", "valgt turtemperatur", "température de flux selectionnée") MAKE_PSTR_LIST(selBurnPow, "selburnpow", "burner selected max power", "Sollwert Brennerleistung", "Ingestelde maximale brandervermogen", "Brännare vald maxeffekt", "wybrana moc źródła ciepła", "settpunkt brennerkapasitet", "puissance max du brûleur selectionnée") +MAKE_PSTR_LIST(absBurnPow, "absburnpow", "burner current power (absolute)", "Brennerleistung (absolut)", "Brandervermogen (abs)", "Värmepanna aktuell effekt (abs)", "aktualna moc źródła ciepła (abs)", "brennereffekt", "puissance du brûleur actuelle (abs)") MAKE_PSTR_LIST(heatingPumpMod, "heatingpumpmod", "heating pump modulation", "Heizungspumpe 1 Modulation", "Modulatie verwarmingspomp", "Modulering Värmepump", "wysterowanie pompy c.o.", "varmepumpemodulering", "modulation de la pompe à chaleur") -MAKE_PSTR_LIST(heatingPump2Mod, "heatingpump2mod", "heating pump 2 modulation", "Heizungspumpe 2 Modulation", "Modulatie verwarmingspomp 2", "Modulering Värmepump 2", "wysterowanie pompy c.o. 2", "varmepumpe 2 modulering", "modulation de la pompe à chaleur 2") MAKE_PSTR_LIST(outdoorTemp, "outdoortemp", "outside temperature", "Aussentemperatur", "Buitentemperatuur", "Utomhustemperatur", "temperatura zewnętrzna", "utetemperatur", "température extérieure") MAKE_PSTR_LIST(curFlowTemp, "curflowtemp", "current flow temperature", "aktuelle Vorlauftemperatur", "Huidige aanvoertemperatuur", "Flödestemperatur", "temperatura zasilania", "aktuell strømmetemperatur", "température actuelle du flux") MAKE_PSTR_LIST(retTemp, "rettemp", "return temperature", "Rücklauftemperatur", "Retourtemperatuur", "Returtemperatur", "temperatura powrotu", "returtemperatur", "température de retour") @@ -395,16 +395,27 @@ MAKE_PSTR_LIST(hpHystCool, "hphystcool", "on/off hyst cool", "Schalthysterese K MAKE_PSTR_LIST(hpHystPool, "hphystpool", "on/off hyst pool", "Schalthysterese Pool", "an/uit-hysteresis in zwembadbedri", "Hystereses Pool", "histereza wł./wył. podgrzewania basenu", "", "Hystérésis Marche en mode piscine") // TODO translate MAKE_PSTR_LIST(tempDiffHeat, "tempdiffheat", "temp. diff. TC3/TC0 heat", "Temp.diff. TC3/TC0 Heizen", "Temp.vers. TC3/TC0 verw", "Delta(T) TC3/TC0 Uppvärm.", "różnica temperatur TC3/TC0 w trakcie ogrzewania", "", "Delta T TC3/TC0 Chauff") // TODO translate MAKE_PSTR_LIST(tempDiffCool, "tempdiffcool", "temp. diff. TC3/TC0 cool", "Temp.diff. TC3/TC0 Kühlen", "Temp.vers. TC3/TC0 koel.", "Delta(T) TC3/TC0 Kyla", "różnica temperatur TC3/TC0 w trakcie chłodzenia", "", "Delta T TC3/TC0 Refroid.") // TODO translate +MAKE_PSTR_LIST(silentFrom, "silentfrom", "silent mode from", "Silentmodus Start") // TODO translate +MAKE_PSTR_LIST(silentTo, "silentto", "silent mode to", "Silentmodus Ende") // TODO translate MAKE_PSTR_LIST(wwComfOffTemp, "wwcomfoff", "comfort switch off", "Komfort Ausschalttemp", "Comfort Uitschakeltemp.", "Komfortläge avstängingstemp.", "temperatura wyłączania w trybie komfort", "", "Confort Temp. d'arrêt") // TODO translate MAKE_PSTR_LIST(wwEcoOffTemp, "wwecooff", "eco switch off", "ECO Ausschalttemp", "Eco Uitschakeltemp.", "Ekoläge avstängningstemp.", "temperatura wyłączania w trybie eko", "", "Eco Temp. d'arrêt") // TODO translate MAKE_PSTR_LIST(wwEcoPlusOffTemp, "wwecoplusoff", "eco+ switch off", "ECO+ Ausschalttemp", "Eco+ Uitschakeltemp.", "Eko+ avstängningstemp.", "temperatura wyłączania w trybie eko+", "", "Eco+ Temp. d'arrêt") // TODO translate MAKE_PSTR_LIST(auxHeatMode, "auxheatrmode", "aux heater mode", "Modus Zusatzheizer", "", "", "", "", "") // TODO translate -MAKE_PSTR_LIST(auxMaxTemp, "auxmaxtemp", "aux heater max temperature", "Zusatzheizer Maximaltemp.", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(auxMaxLimit, "auxmaxlimit", "aux heater max limit", "Zusatzheizer max. Grenze", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(auxLimitStart, "auxlimitstart", "aux heater limit start", "Zusatzheizer Grenze Start", "", "", "", "", "") // TODO translate MAKE_PSTR_LIST(manDefrost, "mandefrost", "manual defrost", "Manuelle Enteisung", "", "", "", "", "") // TODO translate -MAKE_PSTR_LIST(pvCooling, "pvcooling", "cooling only with PV", "Kühlen nur mit PV", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(pvCooling, "pvcooling", "Cooling only with PV", "Kühlen nur mit PV", "", "", "", "", "") // TODO translate MAKE_PSTR_LIST(hpCircPumpWw, "hpcircpumpww", "circulation pump available during dhw", "", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(vp_cooling, "vpcooling", "valve/pump cooling") // TODO translate +MAKE_PSTR_LIST(VC0valve, "vc0valve", "VC0 valve") // TODO translate +MAKE_PSTR_LIST(primePump, "primepump", "primary heatpump") // TODO translate +MAKE_PSTR_LIST(primePumpMod, "primepumpmod", "primary heatpump modulation") // TODO translate +MAKE_PSTR_LIST(hp3wayValve, "hp3way", "3-way valve") // TODO translate +MAKE_PSTR_LIST(elHeatStep1, "elheatstep1", "el. heater step 1") // TODO translate +MAKE_PSTR_LIST(elHeatStep2, "elheatstep2", "el. heater step 2") // TODO translate +MAKE_PSTR_LIST(elHeatStep3, "elheatstep3", "el. heater step 3") // TODO translate MAKE_PSTR_LIST(wwAlternatingOper, "wwalternatingop", "alternating operation", "", "", "", "praca naprzemienna", "", "") // TODO translate MAKE_PSTR_LIST(wwAltOpPrioHeat, "wwaltopprioheat", "prioritise heating during dhw", "", "", "", "czas na ogrzewanie w trakcie c.w.u", "", "") // TODO translate MAKE_PSTR_LIST(wwAltOpPrioWw, "wwaltopprioww", "prioritise dhw during heating", "", "", "", "czas na c.w.u w trakcie ogrzewania", "", "") // TODO translate @@ -442,8 +453,14 @@ MAKE_PSTR_LIST(sysRetTemp, "sysrettemp", "system return temperature", "System R MAKE_PSTR_LIST(valveByPass, "valvebypass", "bypass valve", "Bypass-Ventil", "Bypass klep", "Bypassventil", "zawór obejścia", "", "vanne dérivation") // TODO translate MAKE_PSTR_LIST(valveBuffer, "valvebuffer", "buffer valve", "Puffer-Ventil", "Bufferklep", "Buffertventil", "zawór bufora", "", "vanne tampon") // TODO translate MAKE_PSTR_LIST(valveReturn, "valvereturn", "return valve", "Rückfluss-Ventil", "Retourklep", "Returventil", "zawór powrotu", "", "vanne retour") // TODO translate -MAKE_PSTR_LIST(aPumpMod, "altpumpmod", "alternative hs pump modulation", "Alternativer WE Pumpenmodulation", "Alternatieve warmtebron pomp modulatie", "Alternativ Pumpmodulering Värmekälla", "modulacja pompy alternatywnego źródła ciepła", "alternativ pumpemodulering varmekilde", "modulation alternative pompe hs") +MAKE_PSTR_LIST(aPumpMod, "apumpmod", "alternative hs pump modulation", "Alternativer WE Pumpenmodulation", "Alternatieve warmtebron pomp modulatie", "Alternativ Pumpmodulering Värmekälla", "modulacja pompy alternatywnego źródła ciepła", "alternativ pumpemodulering varmekilde", "modulation alternative pompe hs") MAKE_PSTR_LIST(heatSource, "heatsource", "alternative heating active", "Alternativer Wärmeerzeuger aktiv", "Alternatieve warmtebron aktief", "Alternativ Värmekälla aktiv", "aktywne alternatywne źródło ciepła", "alternativ varmekilde aktiv", "chauffage alternatif actif") +MAKE_PSTR_LIST(aPump, "apump", "alternative hs pump", "Alternativer WE Pumpe", "Alternatieve warmtebron pomp", "Alternativ Pump Värmekälla", "pompy alternatywnego źródła ciepła", "alternativ pumpe varmekilde", "alternative pompe hs") +MAKE_PSTR_LIST(burner, "burner", "burner", "Brenner", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(heatRequest, "heatrequest", "heat request", "Wärmeanforderung", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(blockRemain, "blockremain", "remaining blocktime", "verbleibende Blockzeit", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(blockRemainWw, "blockremainww", "remaining blocktime dhw", "verbleibende Blockzeit WW", "", "", "", "", "") // TODO translate +MAKE_PSTR_LIST(flueGasTemp, "fluegastemp", "flue gas temperature", "Abgastemperatur", "", "", "", "", "") // TODO translate MAKE_PSTR_LIST(vr2Config, "vr2config", "vr2 configuration", "VR2 Konfiguration", "VR2 configuratie", "VR2 Konfiguration", "konfiguracja VR2", "vr2 konfigurasjon", "configuration vr2") MAKE_PSTR_LIST(ahsActivated, "ahsactivated", "alternate heat source activation", "Alt. Wärmeerzeuger aktiviert", "Altenatieve warmtebron geactiveerd", "Alternativ värmekälla aktivering", "aktywacja alternatywnego źródła ciepła", "alternativ varmekilde aktivering", "activation source chaleur alternative") diff --git a/src/system.cpp b/src/system.cpp index 75891a2da..a6b733a99 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -33,6 +33,8 @@ #include "../esp32s2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C3 #include "../esp32c3/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "../esp32s3/rom/rtc.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif @@ -375,6 +377,8 @@ bool System::is_valid_gpio(uint8_t pin) { #elif CONFIG_IDF_TARGET_ESP32C3 // https://www.wemos.cc/en/latest/c3/c3_mini.html if ((pin >= 11 && pin <= 19) || (pin > 21)) { +#elif CONFIG_IDF_TARGET_ESP32S3 + if ((pin >= 19 && pin <= 20) || (pin >= 22 && pin <= 37) || (pin >= 39 && pin <= 42) || (pin > 48)) { #endif return false; // bad pin } @@ -1430,7 +1434,9 @@ bool System::load_board_profile(std::vector & data, const std::string & } else if (board_profile == "C3MINI") { data = {7, 1, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini } else if (board_profile == "S2MINI") { - data = {15, 7, 11, 12, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; //Lolin S2 Mini + data = {15, 7, 11, 12, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin S2 Mini + } else if (board_profile == "S3MINI") { + data = {17, 18, 8, 5, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Liligo S3 } else if (board_profile == "CUSTOM") { // send back current values data = {(int8_t)EMSESP::system_.led_gpio_, diff --git a/src/version.h b/src/version.h index 83cb84b89..0a271aaf2 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.5.0-tec.0" +#define EMSESP_APP_VERSION "3.5.0-tec.1" diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 451d14000..1d9e33e5b 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -91,6 +91,8 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) settings.board_profile = root["board_profile"] | "C3MINI"; #elif CONFIG_IDF_TARGET_ESP32S2 settings.board_profile = root["board_profile"] | "S2MINI"; +#elif CONFIG_IDF_TARGET_ESP32S3 + settings.board_profile = root["board_profile"] | "S3MINI"; #elif CONFIG_IDF_TARGET_ESP32 settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE; #endif