diff --git a/.github/workflows/pio-dependabot.yaml b/.github/workflows/pio-dependabot.yaml deleted file mode 100644 index 7f1513d..0000000 --- a/.github/workflows/pio-dependabot.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: PlatformIO Dependabot -on: - workflow_dispatch: # option to manually trigger the workflow - schedule: - # Runs every day at 00:00 - - cron: "0 0 * * *" - -permissions: - contents: write - pull-requests: write - -jobs: - dependabot: - runs-on: ubuntu-latest - name: run PlatformIO Dependabot - steps: - - name: Checkout - uses: actions/checkout@v5 - - name: run PlatformIO Dependabot - uses: peterus/platformio_dependabot@v1.2.0 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/lib/HomeAssistantHelper/HomeAssistantHelper.h b/lib/HomeAssistantHelper/HomeAssistantHelper.h index c7417c8..990cda1 100644 --- a/lib/HomeAssistantHelper/HomeAssistantHelper.h +++ b/lib/HomeAssistantHelper/HomeAssistantHelper.h @@ -147,8 +147,19 @@ public: return topic; } + template + String getEntityIdWithPrefix(DT domain, VT value, char separator = '_') { + String topic = ""; + topic.concat(domain); + topic.concat('.'); + topic.concat(this->devicePrefix); + topic.concat(separator); + topic.concat(value); + return topic; + } + template - String getObjectIdWithPrefix(T value, char separator = '_') { + String getUniqueIdWithPrefix(T value, char separator = '_') { String topic = ""; topic.concat(this->devicePrefix); topic.concat(separator); diff --git a/lib/HomeAssistantHelper/strings.h b/lib/HomeAssistantHelper/strings.h index da99954..6b95d01 100644 --- a/lib/HomeAssistantHelper/strings.h +++ b/lib/HomeAssistantHelper/strings.h @@ -12,66 +12,67 @@ const char HA_ENTITY_SELECT[] PROGMEM = "select"; const char HA_ENTITY_SENSOR[] PROGMEM = "sensor"; const char HA_ENTITY_SWITCH[] PROGMEM = "switch"; -const char HA_DEVICE[] PROGMEM = "device"; -const char HA_IDENTIFIERS[] PROGMEM = "identifiers"; -const char HA_SW_VERSION[] PROGMEM = "sw_version"; -const char HA_MANUFACTURER[] PROGMEM = "manufacturer"; -const char HA_MODEL[] PROGMEM = "model"; +// https://www.home-assistant.io/integrations/mqtt/#supported-abbreviations-in-mqtt-discovery-messages +const char HA_DEFAULT_ENTITY_ID[] PROGMEM = "def_ent_id"; // "default_entity_id " +const char HA_DEVICE[] PROGMEM = "dev"; // "device" +const char HA_IDENTIFIERS[] PROGMEM = "ids"; // "identifiers" +const char HA_SW_VERSION[] PROGMEM = "sw"; // "sw_version" +const char HA_MANUFACTURER[] PROGMEM = "mf"; // "manufacturer" +const char HA_MODEL[] PROGMEM = "mdl"; // "model" const char HA_NAME[] PROGMEM = "name"; -const char HA_CONF_URL[] PROGMEM = "configuration_url"; -const char HA_COMMAND_TOPIC[] PROGMEM = "command_topic"; -const char HA_COMMAND_TEMPLATE[] PROGMEM = "command_template"; -const char HA_ENABLED_BY_DEFAULT[] PROGMEM = "enabled_by_default"; -const char HA_UNIQUE_ID[] PROGMEM = "unique_id"; -const char HA_OBJECT_ID[] PROGMEM = "object_id"; -const char HA_ENTITY_CATEGORY[] PROGMEM = "entity_category"; +const char HA_CONF_URL[] PROGMEM = "cu"; // "configuration_url" +const char HA_COMMAND_TOPIC[] PROGMEM = "cmd_t"; // "command_topic" +const char HA_COMMAND_TEMPLATE[] PROGMEM = "cmd_tpl"; // "command_template" +const char HA_ENABLED_BY_DEFAULT[] PROGMEM = "en"; // "enabled_by_default" +const char HA_UNIQUE_ID[] PROGMEM = "uniq_id"; // "unique_id" +const char HA_ENTITY_CATEGORY[] PROGMEM = "ent_cat"; // "entity_category" const char HA_ENTITY_CATEGORY_DIAGNOSTIC[] PROGMEM = "diagnostic"; const char HA_ENTITY_CATEGORY_CONFIG[] PROGMEM = "config"; -const char HA_STATE_TOPIC[] PROGMEM = "state_topic"; -const char HA_VALUE_TEMPLATE[] PROGMEM = "value_template"; -const char HA_OPTIONS[] PROGMEM = "options"; -const char HA_AVAILABILITY[] PROGMEM = "availability"; -const char HA_AVAILABILITY_MODE[] PROGMEM = "availability_mode"; -const char HA_TOPIC[] PROGMEM = "topic"; -const char HA_DEVICE_CLASS[] PROGMEM = "device_class"; -const char HA_UNIT_OF_MEASUREMENT[] PROGMEM = "unit_of_measurement"; +const char HA_STATE_TOPIC[] PROGMEM = "stat_t"; // "state_topic" +const char HA_VALUE_TEMPLATE[] PROGMEM = "val_tpl"; // "value_template" +const char HA_OPTIONS[] PROGMEM = "ops"; // "options" +const char HA_AVAILABILITY[] PROGMEM = "avty"; // "availability" +const char HA_AVAILABILITY_MODE[] PROGMEM = "avty_mode"; // "availability_mode" +const char HA_TOPIC[] PROGMEM = "t"; // "topic" +const char HA_DEVICE_CLASS[] PROGMEM = "dev_cla"; // "device_class" +const char HA_UNIT_OF_MEASUREMENT[] PROGMEM = "unit_of_meas"; // "unit_of_measurement" const char HA_UNIT_OF_MEASUREMENT_C[] PROGMEM = "°C"; const char HA_UNIT_OF_MEASUREMENT_F[] PROGMEM = "°F"; const char HA_UNIT_OF_MEASUREMENT_PERCENT[] PROGMEM = "%"; const char HA_UNIT_OF_MEASUREMENT_L_MIN[] PROGMEM = "L/min"; const char HA_UNIT_OF_MEASUREMENT_GAL_MIN[] PROGMEM = "gal/min"; -const char HA_ICON[] PROGMEM = "icon"; +const char HA_ICON[] PROGMEM = "ic"; // "icon" const char HA_MIN[] PROGMEM = "min"; const char HA_MAX[] PROGMEM = "max"; const char HA_STEP[] PROGMEM = "step"; const char HA_MODE[] PROGMEM = "mode"; const char HA_MODE_BOX[] PROGMEM = "box"; -const char HA_STATE_ON[] PROGMEM = "state_on"; -const char HA_STATE_OFF[] PROGMEM = "state_off"; -const char HA_PAYLOAD_ON[] PROGMEM = "payload_on"; -const char HA_PAYLOAD_OFF[] PROGMEM = "payload_off"; -const char HA_STATE_CLASS[] PROGMEM = "state_class"; +const char HA_STATE_ON[] PROGMEM = "stat_on"; // "state_on" +const char HA_STATE_OFF[] PROGMEM = "stat_off"; // "state_off" +const char HA_PAYLOAD_ON[] PROGMEM = "pl_on"; // "payload_on" +const char HA_PAYLOAD_OFF[] PROGMEM = "pl_off"; // "payload_off" +const char HA_STATE_CLASS[] PROGMEM = "stat_cla"; // "state_class" const char HA_STATE_CLASS_MEASUREMENT[] PROGMEM = "measurement"; -const char HA_EXPIRE_AFTER[] PROGMEM = "expire_after"; -const char HA_CURRENT_TEMPERATURE_TOPIC[] PROGMEM = "current_temperature_topic"; -const char HA_CURRENT_TEMPERATURE_TEMPLATE[] PROGMEM = "current_temperature_template"; -const char HA_TEMPERATURE_COMMAND_TOPIC[] PROGMEM = "temperature_command_topic"; -const char HA_TEMPERATURE_COMMAND_TEMPLATE[] PROGMEM = "temperature_command_template"; -const char HA_TEMPERATURE_STATE_TOPIC[] PROGMEM = "temperature_state_topic"; -const char HA_TEMPERATURE_STATE_TEMPLATE[] PROGMEM = "temperature_state_template"; -const char HA_TEMPERATURE_UNIT[] PROGMEM = "temperature_unit"; -const char HA_MODE_COMMAND_TOPIC[] PROGMEM = "mode_command_topic"; -const char HA_MODE_COMMAND_TEMPLATE[] PROGMEM = "mode_command_template"; -const char HA_MODE_STATE_TOPIC[] PROGMEM = "mode_state_topic"; -const char HA_MODE_STATE_TEMPLATE[] PROGMEM = "mode_state_template"; +const char HA_EXPIRE_AFTER[] PROGMEM = "exp_aft"; // "expire_after" +const char HA_CURRENT_TEMPERATURE_TOPIC[] PROGMEM = "curr_temp_t"; // "current_temperature_topic" +const char HA_CURRENT_TEMPERATURE_TEMPLATE[] PROGMEM = "curr_temp_tpl"; // "current_temperature_template" +const char HA_TEMPERATURE_COMMAND_TOPIC[] PROGMEM = "temp_cmd_t"; // "temperature_command_topic" +const char HA_TEMPERATURE_COMMAND_TEMPLATE[] PROGMEM = "temp_cmd_tpl"; // "temperature_command_template" +const char HA_TEMPERATURE_STATE_TOPIC[] PROGMEM = "temp_stat_t"; // "temperature_state_topic" +const char HA_TEMPERATURE_STATE_TEMPLATE[] PROGMEM = "temp_stat_tpl"; // "temperature_state_template" +const char HA_TEMPERATURE_UNIT[] PROGMEM = "temp_unit"; // "temperature_unit" +const char HA_MODE_COMMAND_TOPIC[] PROGMEM = "mode_cmd_t"; // "mode_command_topic" +const char HA_MODE_COMMAND_TEMPLATE[] PROGMEM = "mode_cmd_tpl"; // "mode_command_template" +const char HA_MODE_STATE_TOPIC[] PROGMEM = "mode_stat_t"; // "mode_state_topic" +const char HA_MODE_STATE_TEMPLATE[] PROGMEM = "mode_stat_tpl"; // "mode_state_template" const char HA_MODES[] PROGMEM = "modes"; -const char HA_ACTION_TOPIC[] PROGMEM = "action_topic"; -const char HA_ACTION_TEMPLATE[] PROGMEM = "action_template"; +const char HA_ACTION_TOPIC[] PROGMEM = "act_t"; // "action_topic" +const char HA_ACTION_TEMPLATE[] PROGMEM = "act_tpl"; // "action_template" const char HA_MIN_TEMP[] PROGMEM = "min_temp"; const char HA_MAX_TEMP[] PROGMEM = "max_temp"; const char HA_TEMP_STEP[] PROGMEM = "temp_step"; -const char HA_PRESET_MODE_COMMAND_TOPIC[] PROGMEM = "preset_mode_command_topic"; -const char HA_PRESET_MODE_COMMAND_TEMPLATE[] PROGMEM = "preset_mode_command_template"; -const char HA_PRESET_MODE_STATE_TOPIC[] PROGMEM = "preset_mode_state_topic"; -const char HA_PRESET_MODE_VALUE_TEMPLATE[] PROGMEM = "preset_mode_value_template"; -const char HA_PRESET_MODES[] PROGMEM = "preset_modes"; +const char HA_PRESET_MODE_COMMAND_TOPIC[] PROGMEM = "pr_mode_cmd_t"; // "preset_mode_command_topic" +const char HA_PRESET_MODE_COMMAND_TEMPLATE[] PROGMEM = "pr_mode_cmd_tpl"; // "preset_mode_command_template" +const char HA_PRESET_MODE_STATE_TOPIC[] PROGMEM = "pr_mode_stat_t"; // "preset_mode_state_topic" +const char HA_PRESET_MODE_VALUE_TEMPLATE[] PROGMEM = "pr_mode_val_tpl"; // "preset_mode_value_template" +const char HA_PRESET_MODES[] PROGMEM = "pr_modes"; // "preset_modes" diff --git a/platformio.ini b/platformio.ini index 18ff224..ce6ad17 100644 --- a/platformio.ini +++ b/platformio.ini @@ -92,13 +92,13 @@ check_flags = ${env.check_flags} ;platform_packages = ; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.5 ; framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.1/esp32-arduino-libs-idf-release_v5.1-33fbade6.zip -platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.31/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.34/platform-espressif32.zip platform_packages = ${env.platform_packages} board_build.partitions = esp32_partitions.csv lib_deps = ${env.lib_deps} laxilef/ESP32Scheduler@^1.0.1 -nimble_lib = h2zero/NimBLE-Arduino@^2.3.6 +nimble_lib = h2zero/NimBLE-Arduino@2.3.3 lib_ignore = extra_scripts = post:tools/esp32.py diff --git a/src/HaHelper.h b/src/HaHelper.h index 3f9e390..59bd285 100644 --- a/src/HaHelper.h +++ b/src/HaHelper.h @@ -261,8 +261,13 @@ public: } // object id's - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(objId.c_str()); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(objId.c_str()); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix( + sSensor.type == Sensors::Type::MANUAL + ? FPSTR(HA_ENTITY_NUMBER) + : FPSTR(HA_ENTITY_SENSOR), + objId.c_str() + ); const String& configTopic = this->makeConfigTopic( sSensor.type == Sensors::Type::MANUAL ? FPSTR(HA_ENTITY_NUMBER) : FPSTR(HA_ENTITY_SENSOR), @@ -323,8 +328,8 @@ public: String objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("connected")); // object id's - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(objId.c_str()); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(objId.c_str()); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), objId.c_str()); // state topic doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic( @@ -370,8 +375,8 @@ public: String objId = Sensors::makeObjectIdWithSuffix(sSensor.name, F("signal_quality")); // object id's - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(objId.c_str()); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(objId.c_str()); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SENSOR), objId.c_str()); // state topic doc[FPSTR(HA_STATE_TOPIC)] = this->getDeviceTopic( @@ -407,7 +412,6 @@ public: } bool deleteSignalQualityDynamicSensor(Sensors::Settings& sSensor) { - JsonDocument doc; const String& configTopic = this->makeConfigTopic( FPSTR(HA_ENTITY_SENSOR), Sensors::makeObjectIdWithSuffix(sSensor.name, F("signal_quality")).c_str() @@ -421,8 +425,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_turbo")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating_turbo")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SWITCH), F("heating_turbo")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("Turbo heating"); doc[FPSTR(HA_ICON)] = F("mdi:rocket-launch-outline"); @@ -465,8 +469,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_hysteresis")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating_hysteresis")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("heating_hysteresis")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -497,8 +501,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_turbo_factor")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating_turbo_factor")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("heating_turbo_factor")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = F("power_factor"); doc[FPSTR(HA_NAME)] = F("Heating turbo factor"); @@ -521,8 +525,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_min_temp")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating_min_temp")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("heating_min_temp")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -555,8 +559,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating_max_temp")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating_max_temp")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("heating_max_temp")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -590,8 +594,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw_min_temp")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("dhw_min_temp")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("dhw_min_temp")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -624,8 +628,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw_max_temp")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("dhw_max_temp")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("dhw_max_temp")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -659,8 +663,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SWITCH), F("pid")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("PID"); doc[FPSTR(HA_ICON)] = F("mdi:chart-bar-stacked"); @@ -681,8 +685,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_p")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid_p")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("pid_p")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("PID factor P"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-p-circle-outline"); @@ -704,8 +708,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_i")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid_i")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("pid_i")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("PID factor I"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-i-circle-outline"); @@ -727,8 +731,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_d")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid_d")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("pid_d")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("PID factor D"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-d-circle-outline"); @@ -750,8 +754,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_dt")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid_dt")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("pid_dt")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = F("duration"); doc[FPSTR(HA_UNIT_OF_MEASUREMENT)] = F("s"); @@ -775,8 +779,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_min_temp")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid_min_temp")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("pid_min_temp")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -809,8 +813,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("pid_max_temp")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("pid_max_temp")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("pid_max_temp")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_TEMPERATURE); @@ -844,8 +848,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("equitherm")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SWITCH), F("equitherm")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("Equitherm"); doc[FPSTR(HA_ICON)] = F("mdi:sun-snowflake-variant"); @@ -866,8 +870,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_n")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("equitherm_n")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("equitherm_n")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("Equitherm factor N"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-n-circle-outline"); @@ -889,8 +893,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_k")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("equitherm_k")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("equitherm_k")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("Equitherm factor K"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-k-circle-outline"); @@ -915,8 +919,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.pid.enabled, 'offline', 'online') }}"); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("equitherm_t")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("equitherm_t")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_NUMBER), F("equitherm_t")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_NAME)] = F("Equitherm factor T"); doc[FPSTR(HA_ICON)] = F("mdi:alpha-t-circle-outline"); @@ -938,8 +942,8 @@ public: bool publishStatusState(bool enabledByDefault = true) { JsonDocument doc; doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("status")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("status")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("status")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("problem"); doc[FPSTR(HA_NAME)] = F("Status"); @@ -956,8 +960,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("emergency")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("emergency")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("emergency")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("problem"); doc[FPSTR(HA_NAME)] = F("Emergency"); @@ -974,8 +978,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("ot_status")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("ot_status")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("ot_status")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("connectivity"); doc[FPSTR(HA_NAME)] = F("Opentherm status"); @@ -995,9 +999,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; - //doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("heating")); doc[FPSTR(HA_DEVICE_CLASS)] = F("running"); doc[FPSTR(HA_NAME)] = F("Heating"); doc[FPSTR(HA_ICON)] = F("mdi:radiator"); @@ -1016,9 +1019,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; - //doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("dhw")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("dhw")); doc[FPSTR(HA_DEVICE_CLASS)] = F("running"); doc[FPSTR(HA_NAME)] = F("DHW"); doc[FPSTR(HA_ICON)] = F("mdi:faucet"); @@ -1037,9 +1039,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("flame")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; - //doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("flame")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("flame")); doc[FPSTR(HA_DEVICE_CLASS)] = F("running"); doc[FPSTR(HA_NAME)] = F("Flame"); doc[FPSTR(HA_ICON)] = F("mdi:gas-burner"); @@ -1058,8 +1059,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("fault")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("fault")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("problem"); doc[FPSTR(HA_NAME)] = F("Fault"); @@ -1079,8 +1080,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = JsonString(AVAILABILITY_OT_CONN, true); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC)); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC)); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC)); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("problem"); doc[FPSTR(HA_NAME)] = F("Diagnostic"); @@ -1097,8 +1098,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("ext_pump")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("ext_pump")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BINARY_SENSOR), F("ext_pump")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("running"); doc[FPSTR(HA_NAME)] = F("External pump"); @@ -1118,8 +1119,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.connected and value_json.slave.fault.active, 'online', 'offline') }}"); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("fault_code")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("fault_code")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SENSOR), F("fault_code")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_NAME)] = F("Fault code"); doc[FPSTR(HA_ICON)] = F("mdi:cog-box"); @@ -1138,8 +1139,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.connected and value_json.slave.fault.active or value_json.slave.diag.active, 'online', 'offline') }}"); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("diagnostic_code")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("diagnostic_code")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SENSOR), F("diagnostic_code")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_NAME)] = F("Diagnostic code"); doc[FPSTR(HA_ICON)] = F("mdi:information-box"); @@ -1155,8 +1156,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(S_RSSI)); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(FPSTR(S_RSSI)); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SENSOR), FPSTR(S_RSSI)); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("signal_strength"); doc[FPSTR(HA_STATE_CLASS)] = FPSTR(HA_STATE_CLASS_MEASUREMENT); @@ -1175,8 +1176,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("uptime")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("uptime")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_SENSOR), F("uptime")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_DIAGNOSTIC); doc[FPSTR(HA_DEVICE_CLASS)] = F("duration"); doc[FPSTR(HA_STATE_CLASS)] = F("total_increasing"); @@ -1196,8 +1197,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("heating")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("heating")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_CLIMATE), F("heating")); doc[FPSTR(HA_NAME)] = F("Heating"); doc[FPSTR(HA_ICON)] = F("mdi:radiator"); @@ -1248,8 +1249,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("dhw")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("dhw")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_CLIMATE), F("dhw")); doc[FPSTR(HA_NAME)] = F("DHW"); doc[FPSTR(HA_ICON)] = F("mdi:faucet"); @@ -1293,8 +1294,8 @@ public: JsonDocument doc; doc[FPSTR(HA_AVAILABILITY)][FPSTR(HA_TOPIC)] = this->statusTopic.c_str(); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(FPSTR(S_RESTART)); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(FPSTR(S_RESTART)); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BUTTON), FPSTR(S_RESTART)); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_RESTART); doc[FPSTR(HA_NAME)] = F("Restart"); @@ -1313,8 +1314,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.fault.active, 'online', 'offline') }}"); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("reset_fault")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("reset_fault")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BUTTON), F("reset_fault")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_RESTART); doc[FPSTR(HA_NAME)] = F("Reset fault"); @@ -1333,8 +1334,8 @@ public: doc[FPSTR(HA_AVAILABILITY)][1][FPSTR(HA_VALUE_TEMPLATE)] = F("{{ iif(value_json.slave.diag.active, 'online', 'offline') }}"); doc[FPSTR(HA_AVAILABILITY_MODE)] = F("all"); doc[FPSTR(HA_ENABLED_BY_DEFAULT)] = enabledByDefault; - doc[FPSTR(HA_UNIQUE_ID)] = this->getObjectIdWithPrefix(F("reset_diagnostic")); - doc[FPSTR(HA_OBJECT_ID)] = doc[FPSTR(HA_UNIQUE_ID)]; + doc[FPSTR(HA_UNIQUE_ID)] = this->getUniqueIdWithPrefix(F("reset_diagnostic")); + doc[FPSTR(HA_DEFAULT_ENTITY_ID)] = this->getEntityIdWithPrefix(FPSTR(HA_ENTITY_BUTTON), F("reset_diagnostic")); doc[FPSTR(HA_ENTITY_CATEGORY)] = FPSTR(HA_ENTITY_CATEGORY_CONFIG); doc[FPSTR(HA_DEVICE_CLASS)] = FPSTR(S_RESTART); doc[FPSTR(HA_NAME)] = F("Reset diagnostic"); diff --git a/src/MainTask.h b/src/MainTask.h index af02b60..8d746e0 100644 --- a/src/MainTask.h +++ b/src/MainTask.h @@ -609,7 +609,12 @@ protected: if (GPIO_IS_VALID(settings.externalPump.gpio)) { configuredGpio = settings.externalPump.gpio; pinMode(configuredGpio, OUTPUT); - digitalWrite(configuredGpio, LOW); + digitalWrite( + configuredGpio, + settings.externalPump.invertState + ? HIGH + : LOW + ); } else if (configuredGpio != GPIO_IS_NOT_CONFIGURED) { configuredGpio = GPIO_IS_NOT_CONFIGURED; @@ -637,7 +642,12 @@ protected: if (!settings.externalPump.use) { if (vars.externalPump.state) { - digitalWrite(configuredGpio, LOW); + digitalWrite( + configuredGpio, + settings.externalPump.invertState + ? HIGH + : LOW + ); vars.externalPump.state = false; vars.externalPump.lastEnabledTime = millis(); @@ -650,7 +660,12 @@ protected: if (vars.externalPump.state && !this->heatingEnabled) { if (this->extPumpStartReason == MainTask::PumpStartReason::HEATING && millis() - this->heatingDisabledTime > (settings.externalPump.postCirculationTime * 1000u)) { - digitalWrite(configuredGpio, LOW); + digitalWrite( + configuredGpio, + settings.externalPump.invertState + ? HIGH + : LOW + ); vars.externalPump.state = false; vars.externalPump.lastEnabledTime = millis(); @@ -658,7 +673,12 @@ protected: Log.sinfoln(FPSTR(L_EXTPUMP), F("Disabled: expired post circulation time")); } else if (this->extPumpStartReason == MainTask::PumpStartReason::ANTISTUCK && millis() - this->externalPumpStartTime >= (settings.externalPump.antiStuckTime * 1000u)) { - digitalWrite(configuredGpio, LOW); + digitalWrite( + configuredGpio, + settings.externalPump.invertState + ? HIGH + : LOW + ); vars.externalPump.state = false; vars.externalPump.lastEnabledTime = millis(); @@ -674,7 +694,12 @@ protected: this->externalPumpStartTime = millis(); this->extPumpStartReason = MainTask::PumpStartReason::HEATING; - digitalWrite(configuredGpio, HIGH); + digitalWrite( + configuredGpio, + settings.externalPump.invertState + ? LOW + : HIGH + ); Log.sinfoln(FPSTR(L_EXTPUMP), F("Enabled: heating on")); @@ -683,7 +708,12 @@ protected: this->externalPumpStartTime = millis(); this->extPumpStartReason = MainTask::PumpStartReason::ANTISTUCK; - digitalWrite(configuredGpio, HIGH); + digitalWrite( + configuredGpio, + settings.externalPump.invertState + ? LOW + : HIGH + ); Log.sinfoln(FPSTR(L_EXTPUMP), F("Enabled: anti stuck")); } diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index 4b8dc67..c609597 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -236,7 +236,7 @@ protected: vars.slave.heating.active = CustomOpenTherm::isCentralHeatingActive(response); vars.slave.dhw.active = settings.opentherm.options.dhwSupport ? CustomOpenTherm::isHotWaterActive(response) : false; vars.slave.flame = CustomOpenTherm::isFlameOn(response); - vars.slave.cooling = CustomOpenTherm::isCoolingActive(response); + vars.slave.cooling.active = CustomOpenTherm::isCoolingActive(response); vars.slave.ch2.active = CustomOpenTherm::isCh2Active(response); vars.slave.fault.active = CustomOpenTherm::isFault(response); @@ -250,7 +250,7 @@ protected: Log.snoticeln( FPSTR(L_OT), F("Received boiler status. Heating: %hhu; DHW: %hhu; flame: %hhu; cooling: %hhu; channel 2: %hhu; fault: %hhu; diag: %hhu"), vars.slave.heating.active, vars.slave.dhw.active, - vars.slave.flame, vars.slave.cooling, vars.slave.ch2.active, vars.slave.fault.active, vars.slave.diag.active + vars.slave.flame, vars.slave.cooling.active, vars.slave.ch2.active, vars.slave.fault.active, vars.slave.diag.active ); } @@ -318,6 +318,8 @@ protected: vars.slave.dhw.enabled = false; vars.slave.dhw.active = false; vars.slave.flame = false; + vars.slave.cooling.active = false; + vars.slave.cooling.setpoint = 0; vars.slave.fault.active = false; vars.slave.fault.code = 0; vars.slave.diag.active = false; @@ -688,6 +690,22 @@ protected: this->prevUpdateNonEssentialVars = millis(); } + // Set cooling setpoint = heating max modulation + if (settings.opentherm.options.coolingSupport) { + if (this->setCoolingSetpoint(settings.heating.maxModulation)) { + Log.snoticeln( + FPSTR(L_OT), F("Set cooling setpoint: %hhu%% (response: %hhu%%)"), + settings.heating.maxModulation, vars.slave.cooling.setpoint + ); + + } else { + Log.swarningln( + FPSTR(L_OT), F("Failed set cooling setpoint: %hhu%% (response: %hhu%%)"), + settings.heating.maxModulation, vars.slave.cooling.setpoint + ); + } + } + // Set max modulation level uint8_t targetMaxModulation = vars.slave.modulation.max; if (vars.slave.heating.active) { @@ -1568,6 +1586,26 @@ protected: return CustomOpenTherm::getUInt(response) == request; } + bool setCoolingSetpoint(const uint8_t value) { + const unsigned int request = CustomOpenTherm::toFloat(value); + const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( + OpenThermRequestType::WRITE_DATA, + OpenThermMessageID::CoolingControl, + request + )); + + if (!CustomOpenTherm::isValidResponse(response)) { + return false; + + } else if (!CustomOpenTherm::isValidResponseId(response, OpenThermMessageID::CoolingControl)) { + return false; + } + + vars.slave.cooling.setpoint = CustomOpenTherm::getFloat(response); + + return CustomOpenTherm::getUInt(response) == request; + } + bool setMaxModulationLevel(const uint8_t value) { const unsigned int request = CustomOpenTherm::toFloat(value); const unsigned long response = this->instance->sendRequest(CustomOpenTherm::buildRequest( diff --git a/src/SensorsTask.h b/src/SensorsTask.h index 135d20f..0a8801b 100644 --- a/src/SensorsTask.h +++ b/src/SensorsTask.h @@ -8,6 +8,45 @@ extern FileData fsSensorsSettings; +#if USE_BLE +class BluetoothClientCallbacks : public NimBLEClientCallbacks { +public: + BluetoothClientCallbacks(uint8_t sensorId) : sensorId(sensorId) {} + + void onConnect(NimBLEClient* pClient) { + auto& sSensor = Sensors::settings[this->sensorId]; + + Log.sinfoln( + FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s': connected to %s"), + sensorId, sSensor.name, pClient->getPeerAddress().toString().c_str() + ); + } + + void onDisconnect(NimBLEClient* pClient, int reason) { + auto& sSensor = Sensors::settings[this->sensorId]; + + Log.sinfoln( + FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s': disconnected, reason %i"), + sensorId, sSensor.name, reason + ); + } + + void onConnectFail(NimBLEClient* pClient, int reason) { + auto& sSensor = Sensors::settings[this->sensorId]; + + Log.sinfoln( + FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s': failed to connect, reason %i"), + sensorId, sSensor.name, reason + ); + + pClient->cancelConnect(); + } + +protected: + uint8_t sensorId; +}; +#endif + class SensorsTask : public LeanTask { public: SensorsTask(bool _enabled = false, unsigned long _interval = 0) : LeanTask(_enabled, _interval) { @@ -41,6 +80,7 @@ protected: std::unordered_map dallasPolling; std::unordered_map dallasLastPollingTime; #if USE_BLE + std::unordered_map bleClients; std::unordered_map bleSubscribed; std::unordered_map bleLastSetDtTime; #endif @@ -405,47 +445,35 @@ protected: #if USE_BLE void cleanBleInstances() { - #if USE_BLE if (!NimBLEDevice::isInitialized()) { return; } - for (auto client : NimBLEDevice::getConnectedClients()) { - auto address = client->getPeerAddress(); - bool used = false; - - for (uint8_t sensorId = 0; sensorId <= Sensors::getMaxSensorId(); sensorId++) { - auto& sSensor = Sensors::settings[sensorId]; - - if (!sSensor.enabled || sSensor.type != Sensors::Type::BLUETOOTH || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) { - continue; - } - - auto pAddress = address.getVal(); - uint8_t addr[] = { - pAddress[5], pAddress[4], pAddress[3], - pAddress[2], pAddress[1], pAddress[0] - }; - - if (isEqualAddress(addr, sSensor.address, sizeof(addr))) { - used = true; - break; - } + for (auto& [sensorId, pClient]: this->bleClients) { + if (pClient == nullptr) { + continue; } - if (!used) { + auto& sSensor = Sensors::settings[sensorId]; + const auto sAddress = NimBLEAddress(sSensor.address, 0); + + if (sAddress.isNull() || !sSensor.enabled || sSensor.type != Sensors::Type::BLUETOOTH || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) { Log.sinfoln( - FPSTR(L_SENSORS_BLE), F("Deleted unused client connected to %s"), - address.toString().c_str() + FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s', deleted unused client"), + sensorId, sSensor.name ); - NimBLEDevice::deleteClient(client); + NimBLEDevice::deleteClient(pClient); + pClient = nullptr; } } - #endif } void pollingBleSensors() { + if (!Sensors::getAmountByType(Sensors::Type::BLUETOOTH, true)) { + return; + } + if (!NimBLEDevice::isInitialized() && millis() > 5000) { Log.sinfoln(FPSTR(L_SENSORS_BLE), F("Initialized")); BLEDevice::init(""); @@ -460,38 +488,47 @@ protected: continue; } - auto client = this->getBleClient(sensorId); - if (client == nullptr) { + const auto address = NimBLEAddress(sSensor.address, 0); + if (address.isNull()) { continue; } - if (!client->isConnected()) { + auto pClient = this->getBleClient(sensorId); + if (pClient == nullptr) { + continue; + } + + if (pClient->getPeerAddress() != address) { + if (pClient->isConnected()) { + if (!pClient->disconnect()) { + continue; + } + } + + pClient->setPeerAddress(address); + } + + if (!pClient->isConnected()) { this->bleSubscribed[sensorId] = false; this->bleLastSetDtTime[sensorId] = 0; - if (client->connect()) { + if (pClient->connect(false, true, true)) { Log.sinfoln( - FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s': connected to %s"), - sensorId, sSensor.name, client->getPeerAddress().toString().c_str() + FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s': trying connecting to %s..."), + sensorId, sSensor.name, pClient->getPeerAddress().toString().c_str() ); - - } else { - Log.swarningln( - FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s': failed connecting to %s"), - sensorId, sSensor.name, client->getPeerAddress().toString().c_str() - ); - - continue; } + + continue; } if (!this->bleSubscribed[sensorId]) { - if (this->subscribeToBleDevice(sensorId, client)) { + if (this->subscribeToBleDevice(sensorId, pClient)) { this->bleSubscribed[sensorId] = true; } else { this->bleSubscribed[sensorId] = false; - client->disconnect(); + pClient->disconnect(); continue; } } @@ -503,7 +540,7 @@ protected: struct tm ti; if (getLocalTime(&ti)) { - if (this->setDateOnBleSensor(client, &ti)) { + if (this->setDateOnBleSensor(pClient, &ti)) { Log.sinfoln( FPSTR(L_SENSORS_BLE), F("Sensor #%hhu '%s', successfully set date: %02d.%02d.%04d %02d:%02d:%02d"), sensorId, sSensor.name, @@ -535,42 +572,22 @@ protected: if (!sSensor.enabled || sSensor.type != Sensors::Type::BLUETOOTH || sSensor.purpose == Sensors::Purpose::NOT_CONFIGURED) { return nullptr; } - - uint8_t addr[6] = { - sSensor.address[0], sSensor.address[1], sSensor.address[2], - sSensor.address[3], sSensor.address[4], sSensor.address[5] - }; - const auto address = NimBLEAddress(addr, 0); - - NimBLEClient* pClient = NimBLEDevice::getClientByPeerAddress(address); + + if (this->bleClients[sensorId] && this->bleClients[sensorId] != nullptr) { + return this->bleClients[sensorId]; + } + + auto pClient = NimBLEDevice::createClient(); if (pClient == nullptr) { - pClient = NimBLEDevice::getDisconnectedClient(); + return nullptr; } - if (pClient == nullptr) { - if (NimBLEDevice::getCreatedClientCount() >= NIMBLE_MAX_CONNECTIONS) { - return nullptr; - } + //pClient->setConnectionParams(BLE_GAP_CONN_ITVL_MS(10), BLE_GAP_CONN_ITVL_MS(100), 10, 150); + pClient->setConnectTimeout(30000); + pClient->setSelfDelete(false, false); + pClient->setClientCallbacks(new BluetoothClientCallbacks(sensorId), true); - pClient = NimBLEDevice::createClient(); - if (pClient == nullptr) { - return nullptr; - } - - /** - * Set initial connection parameters: - * These settings are safe for 3 clients to connect reliably, can go faster if you have less - * connections. Timeout should be a multiple of the interval, minimum is 100ms. - * Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 1000 * 10ms = 10000ms timeout - */ - pClient->setConnectionParams(12, 12, 0, 1000); - pClient->setConnectTimeout(5000); - pClient->setSelfDelete(false, true); - } - - if (!pClient->isConnected()) { - pClient->setPeerAddress(address); - } + this->bleClients[sensorId] = pClient; return pClient; } diff --git a/src/Settings.h b/src/Settings.h index c1a0005..9287d3a 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -167,6 +167,7 @@ struct Settings { struct { bool use = false; uint8_t gpio = DEFAULT_EXT_PUMP_GPIO; + bool invertState = false; unsigned short postCirculationTime = 600; unsigned int antiStuckInterval = 2592000; unsigned short antiStuckTime = 300; @@ -334,10 +335,14 @@ struct Variables { bool connected = false; bool flame = false; - bool cooling = false; float pressure = 0.0f; float heatExchangerTemp = 0.0f; + struct { + bool active = false; + uint8_t setpoint = 0; + } cooling; + struct { bool active = false; uint8_t code = 0; diff --git a/src/strings.h b/src/strings.h index 5611ed8..1699ead 100644 --- a/src/strings.h +++ b/src/strings.h @@ -191,6 +191,7 @@ const char S_STA[] PROGMEM = "sta"; const char S_STATE[] PROGMEM = "state"; const char S_STATIC_CONFIG[] PROGMEM = "staticConfig"; const char S_STATUS_LED_GPIO[] PROGMEM = "statusLedGpio"; +const char S_SETPOINT[] PROGMEM = "setpoint"; const char S_SETPOINT_TEMP[] PROGMEM = "setpointTemp"; const char S_SUBNET[] PROGMEM = "subnet"; const char S_SUMMER_WINTER_MODE[] PROGMEM = "summerWinterMode"; diff --git a/src/utils.h b/src/utils.h index 2082c84..831b816 100644 --- a/src/utils.h +++ b/src/utils.h @@ -544,6 +544,7 @@ void settingsToJson(const Settings& src, JsonVariant dst, bool safe = false) { auto externalPump = dst[FPSTR(S_EXTERNAL_PUMP)].to(); externalPump[FPSTR(S_USE)] = src.externalPump.use; externalPump[FPSTR(S_GPIO)] = src.externalPump.gpio; + externalPump[FPSTR(S_INVERT_STATE)] = src.externalPump.invertState; externalPump[FPSTR(S_POST_CIRCULATION_TIME)] = roundf(src.externalPump.postCirculationTime / 60, 0); externalPump[FPSTR(S_ANTI_STUCK_INTERVAL)] = roundf(src.externalPump.antiStuckInterval / 86400, 0); externalPump[FPSTR(S_ANTI_STUCK_TIME)] = roundf(src.externalPump.antiStuckTime / 60, 0); @@ -1520,6 +1521,15 @@ bool jsonToSettings(const JsonVariantConst src, Settings& dst, bool safe = false } } + if (src[FPSTR(S_EXTERNAL_PUMP)][FPSTR(S_INVERT_STATE)].is()) { + bool value = src[FPSTR(S_EXTERNAL_PUMP)][FPSTR(S_INVERT_STATE)].as(); + + if (value != dst.externalPump.invertState) { + dst.externalPump.invertState = value; + changed = true; + } + } + if (!src[FPSTR(S_EXTERNAL_PUMP)][FPSTR(S_POST_CIRCULATION_TIME)].isNull()) { unsigned short value = src[FPSTR(S_EXTERNAL_PUMP)][FPSTR(S_POST_CIRCULATION_TIME)].as(); @@ -1958,12 +1968,20 @@ bool jsonToSensorSettings(const uint8_t sensorId, const JsonVariantConst src, Se ); if (parsed == 8) { - for (uint8_t i = 0; i < 8; i++) { + for (uint8_t i = 0; i < parsed; i++) { if (dst.address[i] != tmp[i]) { dst.address[i] = tmp[i]; changed = true; } } + + } else { + // reset + for (uint8_t i = 0; i < sizeof(dst.address); i++) { + dst.address[i] = 0x00; + } + + changed = true; } } else if (dst.type == Sensors::Type::BLUETOOTH) { @@ -1976,12 +1994,20 @@ bool jsonToSensorSettings(const uint8_t sensorId, const JsonVariantConst src, Se ); if (parsed == 6) { - for (uint8_t i = 0; i < 6; i++) { + for (uint8_t i = 0; i < parsed; i++) { if (dst.address[i] != tmp[i]) { dst.address[i] = tmp[i]; changed = true; } } + + } else { + // reset + for (uint8_t i = 0; i < sizeof(dst.address); i++) { + dst.address[i] = 0x00; + } + + changed = true; } } } @@ -2088,7 +2114,10 @@ void varsToJson(const Variables& src, JsonVariant dst) { slave[FPSTR(S_PROTOCOL_VERSION)] = src.slave.appVersion; slave[FPSTR(S_CONNECTED)] = src.slave.connected; slave[FPSTR(S_FLAME)] = src.slave.flame; - slave[FPSTR(S_COOLING)] = src.slave.cooling; + + auto sCooling = slave[FPSTR(S_COOLING)].to(); + sCooling[FPSTR(S_ACTIVE)] = src.slave.cooling.active; + sCooling[FPSTR(S_SETPOINT)] = src.slave.cooling.setpoint; auto sModulation = slave[FPSTR(S_MODULATION)].to(); sModulation[FPSTR(S_MIN)] = src.slave.modulation.min; diff --git a/src_data/locales/cn.json b/src_data/locales/cn.json index 51ffb01..10a3a6b 100644 --- a/src_data/locales/cn.json +++ b/src_data/locales/cn.json @@ -109,7 +109,8 @@ "sConnected": "OpenTherm 通讯状态", "sFlame": "火焰", - "sCooling": "制冷", + "sCoolingActive": "制冷", + "sCoolingSetpoint": "冷却设定点", "sFaultActive": "报警状态", "sFaultCode": "报警代码", "sDiagActive": "诊断状态", @@ -454,6 +455,7 @@ "extPump": { "use": "使用外置循环泵", "gpio": "继电器 GPIO引脚", + "invertState": "切换 GPIO 状态", "postCirculationTime": "后循环时间 (分钟)", "antiStuckInterval": "防卡死间隔时间(天)", "antiStuckTime": "防卡死运行时长(分钟)" diff --git a/src_data/locales/en.json b/src_data/locales/en.json index c801561..24ac153 100644 --- a/src_data/locales/en.json +++ b/src_data/locales/en.json @@ -109,7 +109,8 @@ "sConnected": "OpenTherm connection", "sFlame": "Flame", - "sCooling": "Cooling", + "sCoolingActive": "Cooling", + "sCoolingSetpoint": "Cooling setpoint", "sFaultActive": "Fault", "sFaultCode": "Fault code", "sDiagActive": "Diagnostic", @@ -454,6 +455,7 @@ "extPump": { "use": "Use external pump", "gpio": "Relay GPIO", + "invertState": "Invert GPIO state", "postCirculationTime": "Post circulation time (min)", "antiStuckInterval": "Anti stuck interval (days)", "antiStuckTime": "Anti stuck time (min)" diff --git a/src_data/locales/it.json b/src_data/locales/it.json index 9a13be8..2e4f15c 100644 --- a/src_data/locales/it.json +++ b/src_data/locales/it.json @@ -109,7 +109,8 @@ "sConnected": "Connessione OpenTherm", "sFlame": "Fiamma", - "sCooling": "Raffrescamento", + "sCoolingActive": "Raffrescamento", + "sCoolingSetpoint": "Raffrescamento setpoint", "sFaultActive": "Anomalia", "sFaultCode": "Codice anomalia", "sDiagActive": "Diagnostica", @@ -454,6 +455,7 @@ "extPump": { "use": "Usa pompa/circolatore esterno", "gpio": "GPIO relè", + "invertState": "Inverti stato GPIO", "postCirculationTime": "Tempo di post circolazione (min)", "antiStuckInterval": "Intervallo antiblocco (days)", "antiStuckTime": "Tempo antiblocco (min)" diff --git a/src_data/locales/nl.json b/src_data/locales/nl.json new file mode 100644 index 0000000..65ff5a3 --- /dev/null +++ b/src_data/locales/nl.json @@ -0,0 +1,466 @@ +{ + "values": { + "logo": "OpenTherm Gateway", + "nav": { + "license": "Licentie", + "source": "Broncode", + "help": "Help", + "issues": "Problemen & vragen", + "releases": "Releases" + }, + "dbm": "dBm", + "kw": "kW", + "time": { + "days": "d.", + "hours": "u.", + "min": "min.", + "sec": "sec." + }, + "button": { + "upgrade": "Upgraden", + "restart": "Herstarten", + "save": "Opslaan", + "saved": "Opgeslagen", + "refresh": "Vernieuwen", + "restore": "Herstellen", + "restored": "Hersteld", + "backup": "Back-up", + "wait": "Even wachten...", + "uploading": "Uploaden...", + "success": "Succes", + "error": "Fout" + }, + "index": { + "title": "OpenTherm Gateway", + "section": { + "network": "Netwerk", + "system": "Systeem" + }, + "system": { + "build": { + "title": "Build", + "version": "Versie", + "date": "Datum", + "core": "Core", + "sdk": "SDK" + }, + "uptime": "Uptime", + "memory": { + "title": "Vrij geheugen", + "maxFreeBlock": "max. vrij blok", + "min": "min" + }, + "board": "Board", + "chip": { + "model": "Chip", + "cores": "Kernen", + "freq": "frequentie" + }, + "flash": { + "size": "Flash-grootte", + "realSize": "werkelijke grootte" + }, + "lastResetReason": "Reden laatste herstart" + } + }, + "dashboard": { + "name": "Dashboard", + "title": "Dashboard - OpenTherm Gateway", + "section": { + "control": "Bediening", + "states": "Statussen", + "sensors": "Sensoren", + "diag": "OpenTherm diagnose" + }, + "thermostat": { + "heating": "Verwarming", + "dhw": "Warm water", + "temp.current": "Huidig", + "enable": "Inschakelen", + "turbo": "Turbomodus" + }, + "notify": { + "fault": { + "title": "Ketelstoring is actief!", + "note": "Het wordt aanbevolen de ketel te inspecteren en de documentatie te raadplegen om de storingscode te interpreteren:" + }, + "diag": { + "title": "Keteldiagnose is actief!", + "note": "Heeft uw ketel misschien een inspectie nodig? Het wordt aanbevolen de documentatie te raadplegen om de diagnosecode te interpreteren:" + }, + "reset": "Probeer te resetten" + }, + "states": { + "mNetworkConnected": "Netwerkverbinding", + "mMqttConnected": "MQTT-verbinding", + "mEmergencyState": "Noodmodus", + "mExtPumpState": "Externe pomp", + "mCascadeControlInput": "Cascaderegeling (ingang)", + "mCascadeControlOutput": "Cascaderegeling (uitgang)", + "sConnected": "OpenTherm-verbinding", + "sFlame": "Vlam", + "sCoolingActive": "Koeling", + "sCoolingSetpoint": "Koelinstelpunt", + "sFaultActive": "Storing", + "sFaultCode": "Storingscode", + "sDiagActive": "Diagnose", + "sDiagCode": "Diagnosecode", + "mHeatEnabled": "Verwarming ingeschakeld", + "mHeatBlocking": "Verwarming geblokkeerd", + "mHeatOverheat": "Verwarming oververhit", + "sHeatActive": "Verwarming actief", + "mHeatSetpointTemp": "Insteltemperatuur verwarming", + "mHeatTargetTemp": "Doeltemperatuur verwarming", + "mHeatCurrTemp": "Huidige temperatuur verwarming", + "mHeatRetTemp": "Retourtemperatuur verwarming", + "mHeatIndoorTemp": "Verwarming, binnentemperatuur", + "mHeatOutdoorTemp": "Verwarming, buitentemperatuur", + "mDhwEnabled": "Warm water ingeschakeld", + "mDhwOverheat": "Warm water oververhit", + "sDhwActive": "Warm water actief", + "mDhwTargetTemp": "Doeltemperatuur warm water", + "mDhwCurrTemp": "Huidige temperatuur warm water", + "mDhwRetTemp": "Retourtemperatuur warm water" + }, + "sensors": { + "values": { + "temp": "Temperatuur", + "humidity": "Luchtvochtigheid", + "battery": "Batterij", + "rssi": "RSSI" + } + } + }, + "network": { + "title": "Netwerk - OpenTherm Gateway", + "name": "Netwerkinstellingen", + "section": { + "static": "Statische instellingen", + "availableNetworks": "Beschikbare netwerken", + "staSettings": "WiFi-instellingen", + "apSettings": "AP-instellingen" + }, + "scan": { + "pos": "#", + "info": "Info" + }, + "wifi": { + "ssid": "SSID", + "password": "Wachtwoord", + "channel": "Kanaal", + "signal": "Signaal", + "connected": "Verbonden" + }, + "params": { + "hostname": "Hostnaam", + "dhcp": "Gebruik DHCP", + "mac": "MAC", + "ip": "IP", + "subnet": "Subnet", + "gateway": "Gateway", + "dns": "DNS" + }, + "sta": { + "channel.note": "zet op 0 voor automatische selectie" + } + }, + "sensors": { + "title": "Sensorinstellingen - OpenTherm Gateway", + "name": "Sensorinstellingen", + "enabled": "Ingeschakeld", + "sensorName": { + "title": "Sensornaam", + "note": "Mag alleen bevatten: a-z, A-Z, 0-9, _ en spatie" + }, + "purpose": "Doel", + "purposes": { + "outdoorTemp": "Buitentemperatuur", + "indoorTemp": "Binnentemperatuur", + "heatTemp": "Verwarming, temperatuur", + "heatRetTemp": "Verwarming, retourtemperatuur", + "dhwTemp": "Warm water, temperatuur", + "dhwRetTemp": "Warm water, retourtemperatuur", + "dhwFlowRate": "Warm water, doorstroomsnelheid", + "exhaustTemp": "Rookgastemperatuur", + "modLevel": "Modulatieniveau (in procenten)", + "number": "Getal (ruw)", + "powerFactor": "Vermogen (in procent)", + "power": "Vermogen (in kWt)", + "fanSpeed": "Ventilatorsnelheid", + "co2": "CO2", + "pressure": "Druk", + "humidity": "Luchtvochtigheid", + "temperature": "Temperatuur", + "notConfigured": "Niet geconfigureerd" + }, + "type": "Type/bron", + "types": { + "otOutdoorTemp": "OpenTherm, buitentemp.", + "otHeatTemp": "OpenTherm, verwarming, temp.", + "otHeatRetTemp": "OpenTherm, verwarming, retourtemp.", + "otDhwTemp": "OpenTherm, warm water, temperatuur", + "otDhwTemp2": "OpenTherm, warm water, temperatuur 2", + "otDhwFlowRate": "OpenTherm, warm water, doorstroomsnelheid", + "otCh2Temp": "OpenTherm, kanaal 2, temp.", + "otExhaustTemp": "OpenTherm, rookgastemp.", + "otHeatExchangerTemp": "OpenTherm, warmtewisselaar temp.", + "otPressure": "OpenTherm, druk", + "otModLevel": "OpenTherm, modulatieniveau", + "otCurrentPower": "OpenTherm, huidig vermogen", + "otExhaustCo2": "OpenTherm, rookgas CO2", + "otExhaustFanSpeed": "OpenTherm, rookgasventilator snelheid", + "otSupplyFanSpeed": "OpenTherm, toevoerventilator snelheid", + "otSolarStorageTemp": "OpenTherm, zonneboiler opslagtemp.", + "otSolarCollectorTemp": "OpenTherm, zonnecollector temp.", + "otFanSpeedSetpoint": "OpenTherm, instelpunt ventilatorsnelheid", + "otFanSpeedCurrent": "OpenTherm, huidige ventilatorsnelheid", + "otBurnerStarts": "OpenTherm, aantal branderstarts", + "otDhwBurnerStarts": "OpenTherm, aantal branderstarts (warm water)", + "otHeatingPumpStarts": "OpenTherm, aantal pompstarts (verwarming)", + "otDhwPumpStarts": "OpenTherm, aantal pompstarts (warm water)", + "otBurnerHours": "OpenTherm, aantal branderuren", + "otDhwBurnerHours": "OpenTherm, aantal branderuren (warm water)", + "otHeatingPumpHours": "OpenTherm, aantal pompuren (verwarming)", + "otDhwPumpHours": "OpenTherm, aantal pompuren (warm water)", + "ntcTemp": "NTC-sensor", + "dallasTemp": "DALLAS-sensor", + "bluetooth": "BLE-sensor", + "heatSetpointTemp": "Verwarming, insteltemperatuur", + "manual": "Handmatig via MQTT/API", + "notConfigured": "Niet geconfigureerd" + }, + "gpio": "GPIO", + "address": { + "title": "Sensoradres", + "note": "Laat leeg voor automatische detectie van DALLAS-sensoren. Voor BLE-apparaten is een MAC-adres vereist." + }, + "correction": { + "desc": "Correctie van waarden", + "offset": "Compensatie (offset)", + "factor": "Vermenigvuldiger" + }, + "filtering": { + "desc": "Filteren van waarden", + "enabled": { + "title": "Filteren ingeschakeld", + "note": "Kan handig zijn bij veel scherpe ruis in de grafieken. Het gebruikte filter is \"Voortschrijdend gemiddelde\"." + }, + "factor": { + "title": "Filterfactor", + "note": "Hoe lager de waarde, hoe vloeiender en langer de verandering in numerieke waarden." + } + } + }, + "settings": { + "title": "Instellingen - OpenTherm Gateway", + "name": "Instellingen", + "section": { + "portal": "Portaalinstellingen", + "system": "Systeeminstellingen", + "diag": "Diagnose", + "heating": "Verwarmingsinstellingen", + "dhw": "Warmwaterinstellingen", + "emergency": "Instellingen noodmodus", + "equitherm": "Equitherm-instellingen", + "pid": "PID-instellingen", + "ot": "OpenTherm-instellingen", + "mqtt": "MQTT-instellingen", + "extPump": "Instellingen externe pomp", + "cascadeControl": "Instellingen cascaderegeling" + }, + "enable": "Inschakelen", + "note": { + "restart": "Na het wijzigen van deze instellingen moet het apparaat opnieuw worden opgestart om de wijzigingen door te voeren.", + "blankNotUse": "leeg - niet gebruiken", + "bleDevice": "BLE-apparaat kan alleen worden gebruikt met sommige ESP32-boards met BLE-ondersteuning!" + }, + "temp": { + "min": "Minimumtemperatuur", + "max": "Maximumtemperatuur" + }, + "maxModulation": "Max. modulatieniveau", + "ohProtection": { + "title": "Oververhittingsbeveiliging", + "desc": "Let op: Deze functie kan handig zijn als de ingebouwde oververhittingsbeveiliging van de ketel niet of niet correct werkt en de warmtedrager kookt. Om uit te schakelen, stel 0 in als hoge en lage temperatuur.", + "highTemp": { + "title": "Drempelwaarde hoge temperatuur", + "note": "Drempelwaarde waarbij de brander geforceerd wordt uitgeschakeld" + }, + "lowTemp": { + "title": "Drempelwaarde lage temperatuur", + "note": "Drempelwaarde waarbij de brander weer ingeschakeld kan worden" + } + }, + "freezeProtection": { + "title": "Vorstbeveiliging", + "desc": "De verwarming wordt geforceerd ingeschakeld als de temperatuur van de warmtedrager of de binnentemperatuur onder de Lage temperatuur daalt gedurende de Wachttijd.", + "lowTemp": "Drempelwaarde lage temperatuur", + "thresholdTime": "Wachttijd (sec)" + }, + "portal": { + "login": "Gebruikersnaam", + "password": "Wachtwoord", + "auth": "Authenticatie vereisen", + "mdns": "Gebruik mDNS" + }, + "system": { + "unit": "Eenheidssysteem", + "metric": "Metrisch (celsius, liters, bar)", + "imperial": "Imperiaal (fahrenheit, gallons, psi)", + "statusLedGpio": "Status LED GPIO", + "logLevel": "Logniveau", + "serial": { + "enable": "Seriële poort ingeschakeld", + "baud": "Baudrate seriële poort" + }, + "telnet": { + "enable": "Telnet ingeschakeld", + "port": { + "title": "Telnet-poort", + "note": "Standaard: 23" + } + }, + "ntp": { + "server": "NTP-server", + "timezone": "Tijdzone", + "timezonePresets": "Selecteer voorinstelling..." + } + }, + "heating": { + "hyst": "Hysterese (in graden)", + "turboFactor": "Turbomodus coëff." + }, + "emergency": { + "desc": "Noodmodus wordt automatisch geactiveerd wanneer «PID» of «Equitherm» het instelpunt van de warmtedrager niet kan berekenen:
- als «Equitherm» is ingeschakeld en de buitentemperatuursensor is losgekoppeld;
- als «PID» of OT-optie «Natuurlijke verwarmingsregeling» is ingeschakeld en de binnentemperatuursensor is losgekoppeld.
Let op: Bij een netwerk- of MQTT-storing krijgen sensoren van het type «Handmatig via MQTT/API» de status ONVERBONDEN.", + "target": { + "title": "Doeltemperatuur", + "note": "Belangrijk: Doel binnentemperatuur als OT-optie «Natuurlijke verwarmingsregeling» is ingeschakeld.
In alle andere gevallen, de doel warmtedragertemperatuur." + }, + "treshold": "Drempeltijd (sec)" + }, + "equitherm": { + "n": "N-factor", + "k": "K-factor", + "t": { + "title": "T-factor", + "note": "Niet gebruikt als PID is ingeschakeld" + } + }, + "pid": { + "p": "P-factor", + "i": "I-factor", + "d": "D-factor", + "dt": "DT in seconden", + "limits": { + "title": "Limieten", + "note": "Belangrijk: Bij gelijktijdig gebruik van «Equitherm» en «PID» beperken de min- en maxtemperaturen de invloed op de resulterende «Equitherm»-temperatuur.
Dus, als de min-temperatuur is ingesteld op -15 en de max-temperatuur op 15, zal het uiteindelijke instelpunt van de warmtedrager liggen tussen equitherm_resultaat - 15 en equitherm_resultaat + 15." + }, + "deadband": { + "title": "Deadband", + "note": "Deadband is een bereik rond de doeltemperatuur waarbinnen de PID-regeling minder actief wordt. Binnen dit bereik kan het algoritme de intensiteit verminderen of aanpassingen pauzeren om overreactie op kleine schommelingen te voorkomen.

Bijvoorbeeld, met een doeltemperatuur van 22°, een onderdrempel van 1.0 en een bovendrempel van 0.5, werkt de deadband tussen 21° en 22.5°. Als de I-coëfficiënt 0.0005 is en de I-vermenigvuldiger 0.05, dan wordt de I-coëfficiënt binnen de deadband: 0.0005 * 0.05 = 0.000025", + "p_multiplier": "Vermenigvuldiger voor P-factor", + "i_multiplier": "Vermenigvuldiger voor I-factor", + "d_multiplier": "Vermenigvuldiger voor D-factor", + "thresholdHigh": "Bovendrempel", + "thresholdLow": "Onderdrempel" + } + }, + "ot": { + "advanced": "Geavanceerde instellingen", + "inGpio": "In GPIO", + "outGpio": "Uit GPIO", + "ledGpio": "RX LED GPIO", + "memberId": "Master member ID", + "flags": "Master flags", + "minPower": { + "title": "Min. ketelvermogen (kW)", + "note": "Deze waarde is bij 0-1% modulatieniveau van de ketel. Typisch te vinden in de ketelspecificatie als \"minimum nuttig warmtevermogen\"." + }, + "maxPower": { + "title": "Max. ketelvermogen (kW)", + "note": "0 - probeer automatisch te detecteren. Typisch te vinden in de ketelspecificatie als \"maximum nuttig warmtevermogen\"." + }, + "options": { + "title": "Opties (aanvullende instellingen)", + "desc": "Opties kunnen de logica van de ketel veranderen. Niet alle opties zijn gedocumenteerd in het protocol, dus dezelfde optie kan verschillende effecten hebben op verschillende ketels.
Let op: Het is niet nodig om iets te veranderen als alles goed werkt.", + "dhwSupport": "Warm water ondersteuning", + "coolingSupport": "Koeling ondersteuning", + "summerWinterMode": "Zomer/wintermodus", + "heatingStateToSummerWinterMode": "Verwarmingsstatus als zomer/wintermodus", + "ch2AlwaysEnabled": "CH2 altijd ingeschakeld", + "heatingToCh2": "Dupliceer verwarming naar CH2", + "dhwToCh2": "Dupliceer warm water naar CH2", + "dhwBlocking": "Blokkering warm water", + "dhwStateAsDhwBlocking": "Status warm water als blokkering warm water", + "maxTempSyncWithTargetTemp": "Synchroniseer max. verwarmingstemp. met doeltemp.", + "getMinMaxTemp": "Haal min/max temp. op van ketel", + "ignoreDiagState": "Negeer diagnosestatus", + "autoFaultReset": "Automatische storingsreset (niet aanbevolen!)", + "autoDiagReset": "Automatische diagnosereset (niet aanbevolen!)", + "setDateAndTime": "Stel datum & tijd in op ketel", + "immergasFix": "Fix voor Immergas-ketels" + }, + "nativeHeating": { + "title": "Natuurlijke verwarmingsregeling (ketel)", + "note": "Werkt ALLEEN als de ketel de gewenste kamertemperatuur vereist en zelf de temperatuur van de warmtedrager regelt. Niet compatibel met PID- en Equitherm-regelaars in de firmware." + } + }, + "mqtt": { + "homeAssistantDiscovery": "Home Assistant Discovery", + "server": "Server", + "port": "Poort", + "user": "Gebruiker", + "password": "Wachtwoord", + "prefix": "Prefix", + "interval": "Publicatie-interval (sec)" + }, + "extPump": { + "use": "Gebruik externe pomp", + "gpio": "Relais GPIO", + "invertState": "Inverteer GPIO-status", + "postCirculationTime": "Nacirculatietijd (min)", + "antiStuckInterval": "Anti-vastloopinterval (dagen)", + "antiStuckTime": "Anti-vastlooptijd (min)" + }, + "cascadeControl": { + "input": { + "desc": "Kan worden gebruikt om de verwarming alleen in te schakelen als een andere ketel defect is. De besturing van de andere ketel moet de status van de GPIO-ingang wijzigen in geval van een storing.", + "enable": "Ingang ingeschakeld", + "gpio": "GPIO", + "invertState": "Inverteer GPIO-status", + "thresholdTime": "Drempeltijd statuswijziging (sec)" + }, + "output": { + "desc": "Kan worden gebruikt om een andere ketel in te schakelen via een relais.", + "enable": "Uitgang ingeschakeld", + "gpio": "GPIO", + "invertState": "Inverteer GPIO-status", + "thresholdTime": "Drempeltijd statuswijziging (sec)", + "events": { + "desc": "Gebeurtenissen", + "onFault": "Als de storingsstatus actief is", + "onLossConnection": "Als de verbinding via Opentherm is verbroken", + "onEnabledHeating": "Als de verwarming is ingeschakeld" + } + } + } + }, + "upgrade": { + "title": "Upgrade - OpenTherm Gateway", + "name": "Upgrade", + "section": { + "backupAndRestore": "Back-up & herstel", + "backupAndRestore.desc": "In deze sectie kunt u een back-up van ALLE instellingen opslaan en herstellen.", + "upgrade": "Upgrade", + "upgrade.desc": "In deze sectie kunt u de firmware en het bestandssysteem van uw apparaat upgraden.
De nieuwste releases kunnen worden gedownload van de Releases-pagina van de projectrepository." + }, + "note": { + "disclaimer1": "Na een succesvolle upgrade van het bestandssysteem worden ALLE instellingen teruggezet naar de standaardwaarden! Sla een back-up op voordat u gaat upgraden.", + "disclaimer2": "Na een succesvolle upgrade zal het apparaat automatisch herstarten na 15 seconden." + }, + "settingsFile": "Instellingenbestand", + "fw": "Firmware", + "fs": "Bestandssysteem" + } + } +} diff --git a/src_data/locales/ru.json b/src_data/locales/ru.json index 28055f7..7a6e627 100644 --- a/src_data/locales/ru.json +++ b/src_data/locales/ru.json @@ -109,7 +109,8 @@ "sConnected": "Подключение к OpenTherm", "sFlame": "Пламя", - "sCooling": "Охлаждение", + "sCoolingActive": "Охлаждение", + "sCoolingSetpoint": "Охлаждение, уставка", "sFaultActive": "Ошибка", "sFaultCode": "Код ошибки", "sDiagActive": "Диагностика", @@ -454,6 +455,7 @@ "extPump": { "use": "Использовать доп. насос", "gpio": "GPIO реле", + "invertState": "Инвертировать состояние GPIO", "postCirculationTime": "Время постциркуляции (в минутах)", "antiStuckInterval": "Интервал защиты от блокировки (в днях)", "antiStuckTime": "Время работы насоса (в минутах)" diff --git a/src_data/pages/dashboard.html b/src_data/pages/dashboard.html index 4a85a83..f01b72b 100644 --- a/src_data/pages/dashboard.html +++ b/src_data/pages/dashboard.html @@ -23,6 +23,7 @@ + @@ -153,9 +154,14 @@ dashboard.states.sFlame + - dashboard.states.sCooling - + dashboard.states.sCoolingActive + + + + dashboard.states.sCoolingSetpoint + % @@ -557,7 +563,9 @@ result.slave.connected ? "green" : "red" ); setState('.sFlame', result.slave.flame); - setState('.sCooling', result.slave.cooling); + + setState('.sCoolingActive', result.slave.cooling.active); + setValue('.sCoolingSetpoint', result.slave.cooling.setpoint); setValue('.sModMin', result.slave.modulation.min); setValue('.sModMax', result.slave.modulation.max); diff --git a/src_data/pages/index.html b/src_data/pages/index.html index 0958a62..c309190 100644 --- a/src_data/pages/index.html +++ b/src_data/pages/index.html @@ -23,6 +23,7 @@ + diff --git a/src_data/pages/network.html b/src_data/pages/network.html index 1a90b04..7204437 100644 --- a/src_data/pages/network.html +++ b/src_data/pages/network.html @@ -23,6 +23,7 @@ + diff --git a/src_data/pages/sensors.html b/src_data/pages/sensors.html index 0f5d0da..c36dbb7 100644 --- a/src_data/pages/sensors.html +++ b/src_data/pages/sensors.html @@ -23,6 +23,7 @@ + diff --git a/src_data/pages/settings.html b/src_data/pages/settings.html index 51fff96..5e2642e 100644 --- a/src_data/pages/settings.html +++ b/src_data/pages/settings.html @@ -23,6 +23,7 @@ + @@ -757,6 +758,11 @@ settings.extPump.use + +
@@ -954,6 +960,7 @@ // Extpump setCheckboxValue("[name='externalPump[use]']", data.externalPump.use); setInputValue("[name='externalPump[gpio]']", data.externalPump.gpio < 255 ? data.externalPump.gpio : ''); + setCheckboxValue("[name='externalPump[invertState]']", data.externalPump.invertState); setInputValue("[name='externalPump[postCirculationTime]']", data.externalPump.postCirculationTime); setInputValue("[name='externalPump[antiStuckInterval]']", data.externalPump.antiStuckInterval); setInputValue("[name='externalPump[antiStuckTime]']", data.externalPump.antiStuckTime); diff --git a/src_data/pages/upgrade.html b/src_data/pages/upgrade.html index c84e7eb..5cf0c85 100644 --- a/src_data/pages/upgrade.html +++ b/src_data/pages/upgrade.html @@ -23,6 +23,7 @@ +