mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-11 18:54:28 +05:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
229628fdc5 | ||
|
|
b0e01afecb | ||
|
|
f544baee0a | ||
|
|
3ff68f544f |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,2 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.vscode
|
||||
11
README.md
11
README.md
@@ -28,10 +28,11 @@
|
||||

|
||||
|
||||
## Tested on
|
||||
| Boiler | Master Member ID |
|
||||
| --- | --- |
|
||||
| BAXI ECO Nova | default or 4 |
|
||||
| BAXI Ampera | 1028 |
|
||||
| Boiler | Master Member ID | Notes |
|
||||
| --- | --- | --- |
|
||||
| BAXI ECO Nova | default or 4 | Pressure sensor not supported, modulation level not stable |
|
||||
| BAXI Ampera | 1028 | Pressure sensor not supported, only heating (DHW not tested) |
|
||||
| [Remeha Calenta Ace 40C](https://github.com/Laxilef/OTGateway/issues/1#issuecomment-1726081554) | default | - |
|
||||
|
||||
## PCB
|
||||
<img src="/assets/pcb.svg" width="25%" /> <img src="/assets/pcb_3d.png" width="30%" /> <img src="/assets/after_assembly.png" width="37%" />
|
||||
@@ -60,7 +61,7 @@ To save money, 2 levels are ordered as one board. After manufacturing, the board
|
||||
- [TelnetStream](https://github.com/jandrassy/TelnetStream)
|
||||
- [EEManager](https://github.com/GyverLibs/EEManager)
|
||||
- [GyverPID](https://github.com/GyverLibs/GyverPID)
|
||||
- [microDS18B20](https://github.com/GyverLibs/microDS18B20)
|
||||
- [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library)
|
||||
- [WiFiManager](https://github.com/tzapu/WiFiManager)
|
||||
|
||||
|
||||
|
||||
4
otgateway.ino
Normal file
4
otgateway.ino
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
This file is needed by the Arduino IDE because the ino file needs to be named as the directory name.
|
||||
Don't worry, the Arduino compiler will "merge" all files, including src/main.cpp
|
||||
*/
|
||||
@@ -21,7 +21,7 @@ lib_deps =
|
||||
jandrassy/TelnetStream@^1.2.4
|
||||
gyverlibs/EEManager@^2.0
|
||||
gyverlibs/GyverPID@^3.3
|
||||
gyverlibs/microDS18B20@^3.10
|
||||
milesburton/DallasTemperature@^3.11.0
|
||||
https://github.com/tzapu/WiFiManager.git#v2.0.16-rc.2
|
||||
build_flags = -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
upload_speed = 921600
|
||||
|
||||
@@ -27,10 +27,10 @@ public:
|
||||
_deviceConfigUrl = value;
|
||||
}
|
||||
|
||||
bool publishSelectOutdoorTempSource(bool enabledByDefault = true) {
|
||||
bool publishSelectOutdoorSensorType(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"outdoorTempSource\": {% if value == 'Boiler' %}0{% elif value == 'Manual' %}1{% elif value == 'External' %}2{% endif %}}");
|
||||
doc[F("command_template")] = F("{\"sensors\": {\"outdoor\": {\"type\": {% if value == 'Boiler' %}0{% elif value == 'Manual' %}1{% elif value == 'External' %}2{% endif %}}}}");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
@@ -40,17 +40,17 @@ public:
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_outdoorTempSource");
|
||||
doc[F("object_id")] = _prefix + F("_outdoorTempSource");
|
||||
doc[F("unique_id")] = _prefix + F("_outdoor_sensor_type");
|
||||
doc[F("object_id")] = _prefix + F("_outdoor_sensor_type");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("name")] = F("Outdoor temperature source");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{% if value_json.outdoorTempSource == 0 %}Boiler{% elif value_json.outdoorTempSource == 1 %}Manual{% elif value_json.outdoorTempSource == 2 %}External{% endif %}");
|
||||
doc[F("value_template")] = F("{% if value_json.sensors.outdoor.type == 0 %}Boiler{% elif value_json.sensors.outdoor.type == 1 %}Manual{% elif value_json.sensors.outdoor.type == 2 %}External{% endif %}");
|
||||
doc[F("options")][0] = F("Boiler");
|
||||
doc[F("options")][1] = F("Manual");
|
||||
doc[F("options")][2] = F("External");
|
||||
|
||||
client.beginPublish((F("homeassistant/select/") + _prefix + F("/outdoorTempSource/config")).c_str(), measureJson(doc), true);
|
||||
client.beginPublish((F("homeassistant/select/") + _prefix + F("/outdoor_sensor_type/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
//serializeJson(doc, bufferedClient);
|
||||
//bufferedClient.flush();
|
||||
@@ -58,6 +58,105 @@ public:
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSelectIndoorSensorType(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"sensors\": {\"indoor\": {\"type\": {% if value == 'Manual' %}1{% elif value == 'External' %}2{% endif %}}}}");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_indoor_sensor_type");
|
||||
doc[F("object_id")] = _prefix + F("_indoor_sensor_type");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("name")] = F("Indoor temperature source");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{% if value_json.sensors.indoor.type == 1 %}Manual{% elif value_json.sensors.indoor.type == 2 %}External{% endif %}");
|
||||
doc[F("options")][0] = F("Manual");
|
||||
doc[F("options")][1] = F("External");
|
||||
|
||||
client.beginPublish((F("homeassistant/select/") + _prefix + F("/indoor_sensor_type/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
//serializeJson(doc, bufferedClient);
|
||||
//bufferedClient.flush();
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberOutdoorSensorOffset(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/settings");
|
||||
doc[F("availability")][F("value_template")] = F("{{ iif(value_json.sensors.outdoor.type != 1, 'online', 'offline') }}");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_outdoor_sensor_offset");
|
||||
doc[F("object_id")] = _prefix + F("_outdoor_sensor_offset");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Outdoor sensor offset");
|
||||
doc[F("icon")] = F("mdi:altimeter");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.sensors.outdoor.offset|float(0)|round(2) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"sensors\": {\"outdoor\" : {\"offset\" : {{ value }}}}}");
|
||||
doc[F("min")] = -10;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/outdoor_sensor_offset/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberIndoorSensorOffset(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/settings");
|
||||
doc[F("availability")][F("value_template")] = F("{{ iif(value_json.sensors.indoor.type != 1, 'online', 'offline') }}");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_indoor_sensor_offset");
|
||||
doc[F("object_id")] = _prefix + F("_indoor_sensor_offset");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Indoor sensor offset");
|
||||
doc[F("icon")] = F("mdi:altimeter");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.sensors.indoor.offset|float(0)|round(2) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"sensors\": {\"indoor\" : {\"offset\" : {{ value }}}}}");
|
||||
doc[F("min")] = -10;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/indoor_sensor_offset/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
|
||||
bool publishSwitchDebug(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
@@ -148,6 +247,7 @@ public:
|
||||
doc[F("min")] = 5;
|
||||
doc[F("max")] = 50;
|
||||
doc[F("step")] = 0.5;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/emergency_target/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -160,7 +260,7 @@ public:
|
||||
bool publishSwitchEmergencyUseEquitherm(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/settings");
|
||||
doc[F("availability")][F("value_template")] = F("{{ iif(value_json.outdoorTempSource != 1, 'online', 'offline') }}");
|
||||
doc[F("availability")][F("value_template")] = F("{{ iif(value_json.sensors.outdoor.type != 1, 'online', 'offline') }}");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
@@ -282,8 +382,9 @@ public:
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"heating\": {\"target\" : {{ value }}}}");
|
||||
doc[F("min")] = minTemp;
|
||||
doc[F("max")] = maxTemp;
|
||||
doc[F("max")] = maxTemp <= minTemp ? maxTemp : maxTemp;
|
||||
doc[F("step")] = 0.5;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/heating_target/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -318,6 +419,7 @@ public:
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 5;
|
||||
doc[F("step")] = 0.1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/heating_hysteresis/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -358,6 +460,126 @@ public:
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSensorCurrentHeatingMinTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/status");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_current_heating_min_temp");
|
||||
doc[F("object_id")] = _prefix + F("_current_heating_min_temp");
|
||||
doc[F("entity_category")] = F("diagnostic");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("state_class")] = F("measurement");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Current heating min temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-down");
|
||||
doc[F("state_topic")] = _prefix + F("/state");
|
||||
doc[F("value_template")] = F("{{ value_json.parameters.heatingMinTemp|int(0) }}");
|
||||
|
||||
client.beginPublish((F("homeassistant/sensor/") + _prefix + F("/current_heating_min_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSensorCurrentHeatingMaxTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/status");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_current_heating_max_temp");
|
||||
doc[F("object_id")] = _prefix + F("_current_heating_max_temp");
|
||||
doc[F("entity_category")] = F("diagnostic");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("state_class")] = F("measurement");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Current heating max temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-up");
|
||||
doc[F("state_topic")] = _prefix + F("/state");
|
||||
doc[F("value_template")] = F("{{ value_json.parameters.heatingMaxTemp|int(0) }}");
|
||||
|
||||
client.beginPublish((F("homeassistant/sensor/") + _prefix + F("/current_heating_max_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberHeatingMinTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_heating_min_temp");
|
||||
doc[F("object_id")] = _prefix + F("_heating_min_temp");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Heating min temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-down");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.heating.minTemp|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"heating\": {\"minTemp\" : {{ value }}}}");
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 99;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/heating_min_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberHeatingMaxTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_heating_max_temp");
|
||||
doc[F("object_id")] = _prefix + F("_heating_max_temp");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Heating max temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-up");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.heating.maxTemp|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"heating\": {\"maxTemp\" : {{ value }}}}");
|
||||
doc[F("min")] = 1;
|
||||
doc[F("max")] = 100;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/heating_max_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
|
||||
bool publishSwitchDHW(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
@@ -416,8 +638,9 @@ public:
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"dhw\": {\"target\" : {{ value|int(0) }}}}");
|
||||
doc[F("min")] = minTemp;
|
||||
doc[F("max")] = maxTemp;
|
||||
doc[F("max")] = maxTemp <= minTemp ? maxTemp : maxTemp;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/dhw_target/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -427,6 +650,126 @@ public:
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSensorCurrentDHWMinTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/status");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_current_dhw_min_temp");
|
||||
doc[F("object_id")] = _prefix + F("_current_dhw_min_temp");
|
||||
doc[F("entity_category")] = F("diagnostic");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("state_class")] = F("measurement");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Current DHW min temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-down");
|
||||
doc[F("state_topic")] = _prefix + F("/state");
|
||||
doc[F("value_template")] = F("{{ value_json.parameters.dhwMinTemp|int(0) }}");
|
||||
|
||||
client.beginPublish((F("homeassistant/sensor/") + _prefix + F("/current_dhw_min_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSensorCurrentDHWMaxTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][F("topic")] = _prefix + F("/status");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_current_dhw_max_temp");
|
||||
doc[F("object_id")] = _prefix + F("_current_dhw_max_temp");
|
||||
doc[F("entity_category")] = F("diagnostic");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("state_class")] = F("measurement");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Current DHW max temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-up");
|
||||
doc[F("state_topic")] = _prefix + F("/state");
|
||||
doc[F("value_template")] = F("{{ value_json.parameters.dhwMaxTemp|int(0) }}");
|
||||
|
||||
client.beginPublish((F("homeassistant/sensor/") + _prefix + F("/current_dhw_max_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberDHWMinTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_dhw_min_temp");
|
||||
doc[F("object_id")] = _prefix + F("_dhw_min_temp");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("DHW min temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-down");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.dhw.minTemp|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"dhw\": {\"minTemp\" : {{ value }}}}");
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 99;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/dhw_min_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberDHWMaxTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_dhw_max_temp");
|
||||
doc[F("object_id")] = _prefix + F("_dhw_max_temp");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("DHW max temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-up");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.dhw.maxTemp|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"dhw\": {\"maxTemp\" : {{ value }}}}");
|
||||
doc[F("min")] = 1;
|
||||
doc[F("max")] = 100;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/dhw_max_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
|
||||
bool publishSwitchPID(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
@@ -482,6 +825,7 @@ public:
|
||||
doc[F("min")] = 0.001;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.001;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/pid_p_factor/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -513,6 +857,7 @@ public:
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.001;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/pid_i_factor/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -544,6 +889,7 @@ public:
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.001;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/pid_d_factor/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -553,6 +899,70 @@ public:
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberPIDMinTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_pid_min_temp");
|
||||
doc[F("object_id")] = _prefix + F("_pid_min_temp");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("PID min temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-down");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.pid.minTemp|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"pid\": {\"minTemp\" : {{ value }}}}");
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 99;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/pid_min_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberPIDMaxTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_pid_max_temp");
|
||||
doc[F("object_id")] = _prefix + F("_pid_max_temp");
|
||||
doc[F("entity_category")] = F("config");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("PID max temp");
|
||||
doc[F("icon")] = F("mdi:thermometer-chevron-up");
|
||||
doc[F("state_topic")] = _prefix + F("/settings");
|
||||
doc[F("value_template")] = F("{{ value_json.pid.maxTemp|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/settings/set");
|
||||
doc[F("command_template")] = F("{\"pid\": {\"maxTemp\" : {{ value }}}}");
|
||||
doc[F("min")] = 1;
|
||||
doc[F("max")] = 100;
|
||||
doc[F("step")] = 1;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/pid_max_temp/config")).c_str(), measureJson(doc), true);
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
|
||||
bool publishSwitchEquitherm(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
@@ -608,6 +1018,7 @@ public:
|
||||
doc[F("min")] = 0.001;
|
||||
doc[F("max")] = 5;
|
||||
doc[F("step")] = 0.001;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/equitherm_n_factor/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -639,6 +1050,7 @@ public:
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.01;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/equitherm_k_factor/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -672,6 +1084,7 @@ public:
|
||||
doc[F("min")] = 0;
|
||||
doc[F("max")] = 10;
|
||||
doc[F("step")] = 0.01;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/equitherm_t_factor/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -979,7 +1392,7 @@ public:
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSensorRssi(bool enabledByDefault = false) {
|
||||
bool publishSensorRssi(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc["device"]["identifiers"][0] = _prefix;
|
||||
doc["device"]["sw_version"] = _deviceVersion;
|
||||
@@ -1076,7 +1489,6 @@ public:
|
||||
|
||||
bool publishNumberIndoorTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
//doc[F("availability")][F("topic")] = _prefix + F("/status");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
@@ -1097,8 +1509,10 @@ public:
|
||||
doc[F("value_template")] = F("{{ value_json.temperatures.indoor|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/state/set");
|
||||
doc[F("command_template")] = F("{\"temperatures\": {\"indoor\":{{ value }}}}");
|
||||
doc[F("min")] = -70;
|
||||
doc[F("max")] = 50;
|
||||
doc[F("min")] = -99;
|
||||
doc[F("max")] = 99;
|
||||
doc[F("step")] = 0.01;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/indoor_temp/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -1108,6 +1522,38 @@ public:
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishSensorIndoorTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][0][F("topic")] = _prefix + F("/status");
|
||||
doc[F("availability_mode")] = F("any");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
doc[F("device")][F("manufacturer")] = _deviceManufacturer;
|
||||
doc[F("device")][F("model")] = _deviceModel;
|
||||
doc[F("device")][F("name")] = _deviceName;
|
||||
if (_deviceConfigUrl) {
|
||||
doc[F("device")][F("configuration_url")] = _deviceConfigUrl;
|
||||
}
|
||||
doc[F("enabled_by_default")] = enabledByDefault;
|
||||
doc[F("unique_id")] = _prefix + F("_indoor_temp");
|
||||
doc[F("object_id")] = _prefix + F("_indoor_temp");
|
||||
doc[F("entity_category")] = F("diagnostic");
|
||||
doc[F("device_class")] = F("temperature");
|
||||
doc[F("state_class")] = F("measurement");
|
||||
doc[F("unit_of_measurement")] = F("°C");
|
||||
doc[F("name")] = F("Indoor temperature");
|
||||
doc[F("icon")] = F("mdi:home-thermometer");
|
||||
doc[F("state_topic")] = _prefix + F("/state");
|
||||
doc[F("value_template")] = F("{{ value_json.temperatures.indoor|float(0)|round(1) }}");
|
||||
|
||||
client.beginPublish((F("homeassistant/sensor/") + _prefix + F("/indoor_temp/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
//serializeJson(doc, bufferedClient);
|
||||
//bufferedClient.flush();
|
||||
serializeJson(doc, client);
|
||||
return client.endPublish();
|
||||
}
|
||||
|
||||
bool publishNumberOutdoorTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
@@ -1130,8 +1576,10 @@ public:
|
||||
doc[F("value_template")] = F("{{ value_json.temperatures.outdoor|float(0)|round(1) }}");
|
||||
doc[F("command_topic")] = _prefix + F("/state/set");
|
||||
doc[F("command_template")] = F("{\"temperatures\": {\"outdoor\":{{ value }}}}");
|
||||
doc[F("min")] = -70;
|
||||
doc[F("max")] = 50;
|
||||
doc[F("min")] = -99;
|
||||
doc[F("max")] = 99;
|
||||
doc[F("step")] = 0.01;
|
||||
doc[F("mode")] = "box";
|
||||
|
||||
client.beginPublish((F("homeassistant/number/") + _prefix + F("/outdoor_temp/config")).c_str(), measureJson(doc), true);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
@@ -1144,8 +1592,6 @@ public:
|
||||
bool publishSensorOutdoorTemp(bool enabledByDefault = true) {
|
||||
StaticJsonDocument<1536> doc;
|
||||
doc[F("availability")][0][F("topic")] = _prefix + F("/status");
|
||||
doc[F("availability")][1][F("topic")] = _prefix + F("/settings");
|
||||
doc[F("availability")][1][F("value_template")] = F("{{ iif(value_json.outdoorTempSource == 2, 'online', 'offline') }}");
|
||||
doc[F("availability_mode")] = F("any");
|
||||
doc[F("device")][F("identifiers")][0] = _prefix;
|
||||
doc[F("device")][F("sw_version")] = _deviceVersion;
|
||||
@@ -1353,6 +1799,14 @@ public:
|
||||
return client.publish((F("homeassistant/sensor/") + _prefix + F("/outdoor_temp/config")).c_str(), NULL, true);
|
||||
}
|
||||
|
||||
bool deleteNumberIndoorTemp() {
|
||||
return client.publish((F("homeassistant/number/") + _prefix + F("/indoor_temp/config")).c_str(), NULL, true);
|
||||
}
|
||||
|
||||
bool deleteSensorIndoorTemp() {
|
||||
return client.publish((F("homeassistant/sensor/") + _prefix + F("/indoor_temp/config")).c_str(), NULL, true);
|
||||
}
|
||||
|
||||
private:
|
||||
String _prefix = "opentherm";
|
||||
String _deviceVersion = "1.0";
|
||||
|
||||
@@ -13,7 +13,6 @@ protected:
|
||||
|
||||
void setup() {
|
||||
pinMode(LED_STATUS_PIN, OUTPUT);
|
||||
//pinMode(LED_OT_RX_PIN, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -49,12 +48,6 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
if (!tSensors->isEnabled() && settings.outdoorTempSource == 2) {
|
||||
tSensors->enable();
|
||||
} else if (tSensors->isEnabled() && settings.outdoorTempSource != 2) {
|
||||
tSensors->disable();
|
||||
}
|
||||
|
||||
if (!tOt->isEnabled() && settings.opentherm.inPin > 0 && settings.opentherm.outPin > 0 && settings.opentherm.inPin != settings.opentherm.outPin) {
|
||||
tOt->enable();
|
||||
}
|
||||
|
||||
254
src/MqttTask.h
254
src/MqttTask.h
@@ -19,7 +19,6 @@ protected:
|
||||
void setup() {
|
||||
DEBUG("[MQTT] Started");
|
||||
|
||||
client.setServer(settings.mqtt.server, settings.mqtt.port);
|
||||
client.setCallback(__callback);
|
||||
haHelper.setPrefix(settings.mqtt.prefix);
|
||||
haHelper.setDeviceVersion(OT_GATEWAY_VERSION);
|
||||
@@ -32,6 +31,7 @@ protected:
|
||||
if (!client.connected() && millis() - lastReconnectAttempt >= MQTT_RECONNECT_INTERVAL) {
|
||||
INFO_F("Mqtt not connected, state: %i, connecting to server %s...\n", client.state(), settings.mqtt.server);
|
||||
|
||||
client.setServer(settings.mqtt.server, settings.mqtt.port);
|
||||
if (client.connect(settings.hostname, settings.mqtt.user, settings.mqtt.password)) {
|
||||
INFO("Connected to MQTT server");
|
||||
|
||||
@@ -93,15 +93,6 @@ protected:
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["outdoorTempSource"].isNull() && doc["outdoorTempSource"].is<int>() && doc["outdoorTempSource"] >= 0 && doc["outdoorTempSource"] <= 2) {
|
||||
settings.outdoorTempSource = doc["outdoorTempSource"];
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["mqtt"]["interval"].isNull() && doc["mqtt"]["interval"].is<int>() && doc["mqtt"]["interval"] >= 1000 && doc["mqtt"]["interval"] <= 120000) {
|
||||
settings.mqtt.interval = doc["mqtt"]["interval"].as<unsigned int>();
|
||||
flag = true;
|
||||
}
|
||||
|
||||
// emergency
|
||||
if (!doc["emergency"]["enable"].isNull() && doc["emergency"]["enable"].is<bool>()) {
|
||||
@@ -109,9 +100,11 @@ protected:
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["emergency"]["target"].isNull() && (doc["emergency"]["target"].is<float>() || doc["emergency"]["target"].is<int>())) {
|
||||
settings.emergency.target = round(doc["emergency"]["target"].as<float>() * 10) / 10;
|
||||
flag = true;
|
||||
if (!doc["emergency"]["target"].isNull() && doc["emergency"]["target"].is<float>()) {
|
||||
if ( doc["emergency"]["target"].as<float>() > 0 && doc["emergency"]["target"].as<float>() < 100 ) {
|
||||
settings.emergency.target = round(doc["emergency"]["target"].as<float>() * 10) / 10;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["emergency"]["useEquitherm"].isNull() && doc["emergency"]["useEquitherm"].is<bool>()) {
|
||||
@@ -119,6 +112,7 @@ protected:
|
||||
flag = true;
|
||||
}
|
||||
|
||||
|
||||
// heating
|
||||
if (!doc["heating"]["enable"].isNull() && doc["heating"]["enable"].is<bool>()) {
|
||||
settings.heating.enable = doc["heating"]["enable"].as<bool>();
|
||||
@@ -130,46 +124,106 @@ protected:
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["heating"]["target"].isNull() && (doc["heating"]["target"].is<float>() || doc["heating"]["target"].is<int>())) {
|
||||
settings.heating.target = round(doc["heating"]["target"].as<float>() * 10) / 10;
|
||||
flag = true;
|
||||
if (!doc["heating"]["target"].isNull() && doc["heating"]["target"].is<float>()) {
|
||||
if ( doc["heating"]["target"].as<float>() > 0 && doc["heating"]["target"].as<float>() < 100 ) {
|
||||
settings.heating.target = round(doc["heating"]["target"].as<float>() * 10) / 10;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["heating"]["hysteresis"].isNull() && (doc["heating"]["hysteresis"].is<float>() || doc["heating"]["hysteresis"].is<int>())) {
|
||||
settings.heating.hysteresis = round(doc["heating"]["hysteresis"].as<float>() * 10) / 10;
|
||||
flag = true;
|
||||
if (!doc["heating"]["hysteresis"].isNull() && doc["heating"]["hysteresis"].is<float>()) {
|
||||
if ( doc["heating"]["hysteresis"].as<float>() > 0 && doc["heating"]["hysteresis"].as<float>() <= 5 ) {
|
||||
settings.heating.hysteresis = round(doc["heating"]["hysteresis"].as<float>() * 10) / 10;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["heating"]["maxTemp"].isNull() && doc["heating"]["maxTemp"].is<unsigned char>()) {
|
||||
if ( doc["heating"]["maxTemp"].as<unsigned char>() > 0 && doc["heating"]["maxTemp"].as<unsigned char>() <= 100 && doc["heating"]["maxTemp"].as<unsigned char>() > settings.heating.minTemp ) {
|
||||
settings.heating.maxTemp = doc["heating"]["maxTemp"].as<unsigned char>();
|
||||
vars.parameters.heatingMaxTemp = settings.heating.maxTemp;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["heating"]["minTemp"].isNull() && doc["heating"]["minTemp"].is<unsigned char>()) {
|
||||
if ( doc["heating"]["minTemp"].as<unsigned char>() >= 0 && doc["heating"]["minTemp"].as<unsigned char>() < 100 && doc["heating"]["minTemp"].as<unsigned char>() < settings.heating.maxTemp ) {
|
||||
settings.heating.minTemp = doc["heating"]["minTemp"].as<unsigned char>();
|
||||
vars.parameters.heatingMinTemp = settings.heating.minTemp;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dhw
|
||||
if (!doc["dhw"]["enable"].isNull() && doc["dhw"]["enable"].is<bool>()) {
|
||||
settings.dhw.enable = doc["dhw"]["enable"].as<bool>();
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["dhw"]["target"].isNull() && doc["dhw"]["target"].is<int>()) {
|
||||
settings.dhw.target = doc["dhw"]["target"].as<int>();
|
||||
flag = true;
|
||||
if (!doc["dhw"]["target"].isNull() && doc["dhw"]["target"].is<unsigned char>()) {
|
||||
if ( doc["dhw"]["target"].as<unsigned char>() >= 0 && doc["dhw"]["target"].as<unsigned char>() < 100 ) {
|
||||
settings.dhw.target = doc["dhw"]["target"].as<unsigned char>();
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["dhw"]["maxTemp"].isNull() && doc["dhw"]["maxTemp"].is<unsigned char>()) {
|
||||
if ( doc["dhw"]["maxTemp"].as<unsigned char>() > 0 && doc["dhw"]["maxTemp"].as<unsigned char>() <= 100 && doc["dhw"]["maxTemp"].as<unsigned char>() > settings.dhw.minTemp ) {
|
||||
settings.dhw.maxTemp = doc["dhw"]["maxTemp"].as<unsigned char>();
|
||||
vars.parameters.dhwMaxTemp = settings.dhw.maxTemp;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["dhw"]["minTemp"].isNull() && doc["dhw"]["minTemp"].is<unsigned char>()) {
|
||||
if ( doc["dhw"]["minTemp"].as<unsigned char>() >= 0 && doc["dhw"]["minTemp"].as<unsigned char>() < 100 && doc["dhw"]["minTemp"].as<unsigned char>() < settings.dhw.maxTemp ) {
|
||||
settings.dhw.minTemp = doc["dhw"]["minTemp"].as<unsigned char>();
|
||||
vars.parameters.dhwMinTemp = settings.dhw.minTemp;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// pid
|
||||
if (!doc["pid"]["enable"].isNull() && doc["pid"]["enable"].is<bool>()) {
|
||||
settings.pid.enable = doc["pid"]["enable"].as<bool>();
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["pid"]["p_factor"].isNull() && (doc["pid"]["p_factor"].is<float>() || doc["pid"]["p_factor"].is<int>())) {
|
||||
settings.pid.p_factor = round(doc["pid"]["p_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
if (!doc["pid"]["p_factor"].isNull() && doc["pid"]["p_factor"].is<float>()) {
|
||||
if ( doc["pid"]["p_factor"].as<float>() >= 0 && doc["pid"]["p_factor"].as<float>() <= 20 ) {
|
||||
settings.pid.p_factor = round(doc["pid"]["p_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["pid"]["i_factor"].isNull() && (doc["pid"]["i_factor"].is<float>() || doc["pid"]["i_factor"].is<int>())) {
|
||||
settings.pid.i_factor = round(doc["pid"]["i_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
if (!doc["pid"]["i_factor"].isNull() && doc["pid"]["i_factor"].is<float>()) {
|
||||
if ( doc["pid"]["i_factor"].as<float>() >= 0 && doc["pid"]["i_factor"].as<float>() <= 20 ) {
|
||||
settings.pid.i_factor = round(doc["pid"]["i_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["pid"]["d_factor"].isNull() && (doc["pid"]["d_factor"].is<float>() || doc["pid"]["d_factor"].is<int>())) {
|
||||
settings.pid.d_factor = round(doc["pid"]["d_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
if (!doc["pid"]["d_factor"].isNull() && doc["pid"]["d_factor"].is<float>()) {
|
||||
if ( doc["pid"]["d_factor"].as<float>() >= 0 && doc["pid"]["d_factor"].as<float>() <= 20 ) {
|
||||
settings.pid.d_factor = round(doc["pid"]["d_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["pid"]["maxTemp"].isNull() && doc["pid"]["maxTemp"].is<unsigned char>()) {
|
||||
if ( doc["pid"]["maxTemp"].as<unsigned char>() > 0 && doc["pid"]["maxTemp"].as<unsigned char>() <= 100 && doc["pid"]["maxTemp"].as<unsigned char>() > settings.pid.minTemp ) {
|
||||
settings.pid.maxTemp = doc["pid"]["maxTemp"].as<unsigned char>();
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["pid"]["minTemp"].isNull() && doc["pid"]["minTemp"].is<unsigned char>()) {
|
||||
if ( doc["pid"]["minTemp"].as<unsigned char>() >= 0 && doc["pid"]["minTemp"].as<unsigned char>() < 100 && doc["pid"]["minTemp"].as<unsigned char>() < settings.pid.maxTemp ) {
|
||||
settings.pid.minTemp = doc["pid"]["minTemp"].as<unsigned char>();
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
// equitherm
|
||||
@@ -178,21 +232,58 @@ protected:
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["equitherm"]["n_factor"].isNull() && (doc["equitherm"]["n_factor"].is<float>() || doc["equitherm"]["n_factor"].is<int>())) {
|
||||
settings.equitherm.n_factor = round(doc["equitherm"]["n_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
if (!doc["equitherm"]["n_factor"].isNull() && doc["equitherm"]["n_factor"].is<float>()) {
|
||||
if ( doc["equitherm"]["n_factor"].as<float>() >= 0 && doc["equitherm"]["n_factor"].as<float>() <= 20 ) {
|
||||
settings.equitherm.n_factor = round(doc["equitherm"]["n_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["equitherm"]["k_factor"].isNull() && (doc["equitherm"]["k_factor"].is<float>() || doc["equitherm"]["k_factor"].is<int>())) {
|
||||
settings.equitherm.k_factor = round(doc["equitherm"]["k_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
if (!doc["equitherm"]["k_factor"].isNull() && doc["equitherm"]["k_factor"].is<float>()) {
|
||||
if ( doc["equitherm"]["k_factor"].as<float>() >= 0 && doc["equitherm"]["k_factor"].as<float>() <= 20 ) {
|
||||
settings.equitherm.k_factor = round(doc["equitherm"]["k_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["equitherm"]["t_factor"].isNull() && (doc["equitherm"]["t_factor"].is<float>() || doc["equitherm"]["t_factor"].is<int>())) {
|
||||
settings.equitherm.t_factor = round(doc["equitherm"]["t_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
if (!doc["equitherm"]["t_factor"].isNull() && doc["equitherm"]["t_factor"].is<float>()) {
|
||||
if ( doc["equitherm"]["t_factor"].as<float>() >= 0 && doc["equitherm"]["t_factor"].as<float>() <= 20 ) {
|
||||
settings.equitherm.t_factor = round(doc["equitherm"]["t_factor"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sensors
|
||||
if (!doc["sensors"]["outdoor"]["type"].isNull() && doc["sensors"]["outdoor"]["type"].is<unsigned char>()) {
|
||||
if ( doc["sensors"]["outdoor"]["type"].as<unsigned char>() >= 0 && doc["sensors"]["outdoor"]["type"].as<unsigned char>() <= 2 ) {
|
||||
settings.sensors.outdoor.type = doc["sensors"]["outdoor"]["type"].as<unsigned char>();
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["sensors"]["outdoor"]["offset"].isNull() && doc["sensors"]["outdoor"]["offset"].is<float>()) {
|
||||
if ( doc["sensors"]["outdoor"]["offset"].as<float>() >= -10 && doc["sensors"]["outdoor"]["offset"].as<float>() <= 10 ) {
|
||||
settings.sensors.outdoor.offset = round(doc["sensors"]["outdoor"]["offset"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["sensors"]["indoor"]["type"].isNull() && doc["sensors"]["indoor"]["type"].is<unsigned char>()) {
|
||||
if ( doc["sensors"]["indoor"]["type"].as<unsigned char>() >= 1 && doc["sensors"]["indoor"]["type"].as<unsigned char>() <= 2 ) {
|
||||
settings.sensors.indoor.type = doc["sensors"]["indoor"]["type"].as<unsigned char>();
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["sensors"]["indoor"]["offset"].isNull() && doc["sensors"]["indoor"]["offset"].is<float>()) {
|
||||
if ( doc["sensors"]["indoor"]["offset"].as<float>() >= -10 && doc["sensors"]["indoor"]["offset"].as<float>() <= 10 ) {
|
||||
settings.sensors.indoor.offset = round(doc["sensors"]["indoor"]["offset"].as<float>() * 1000) / 1000;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (flag) {
|
||||
eeSettings.update();
|
||||
publish(true);
|
||||
@@ -215,27 +306,33 @@ protected:
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!doc["tuning"]["regulator"].isNull() && doc["tuning"]["regulator"].is<int>() && doc["tuning"]["regulator"] >= 0 && doc["tuning"]["regulator"] <= 1) {
|
||||
vars.tuning.regulator = doc["tuning"]["regulator"];
|
||||
flag = true;
|
||||
if (!doc["tuning"]["regulator"].isNull() && doc["tuning"]["regulator"].is<unsigned char>()) {
|
||||
if (doc["tuning"]["regulator"].as<unsigned char>() >= 0 && doc["tuning"]["regulator"].as<unsigned char>() <= 1) {
|
||||
vars.tuning.regulator = doc["tuning"]["regulator"].as<unsigned char>();
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["temperatures"]["indoor"].isNull() && (doc["temperatures"]["indoor"].is<float>() || doc["temperatures"]["indoor"].is<int>())) {
|
||||
vars.temperatures.indoor = round(doc["temperatures"]["indoor"].as<float>() * 100) / 100;
|
||||
flag = true;
|
||||
if (!doc["temperatures"]["indoor"].isNull() && doc["temperatures"]["indoor"].is<float>()) {
|
||||
if ( settings.sensors.indoor.type == 1 && doc["temperatures"]["indoor"].as<float>() > -100 && doc["temperatures"]["indoor"].as<float>() < 100 ) {
|
||||
vars.temperatures.indoor = round(doc["temperatures"]["indoor"].as<float>() * 100) / 100;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["temperatures"]["outdoor"].isNull() && (doc["temperatures"]["outdoor"].is<float>() || doc["temperatures"]["outdoor"].is<int>()) && settings.outdoorTempSource == 1) {
|
||||
vars.temperatures.outdoor = round(doc["temperatures"]["outdoor"].as<float>() * 100) / 100;
|
||||
flag = true;
|
||||
if (!doc["temperatures"]["outdoor"].isNull() && doc["temperatures"]["outdoor"].is<float>()) {
|
||||
if ( settings.sensors.outdoor.type == 1 && doc["temperatures"]["outdoor"].as<float>() > -100 && doc["temperatures"]["outdoor"].as<float>() < 100 ) {
|
||||
vars.temperatures.outdoor = round(doc["temperatures"]["outdoor"].as<float>() * 100) / 100;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!doc["restart"].isNull() && doc["restart"].is<bool>() && doc["restart"]) {
|
||||
if (!doc["restart"].isNull() && doc["restart"].is<bool>() && doc["restart"].as<bool>()) {
|
||||
DEBUG("Received restart message...");
|
||||
eeSettings.updateNow();
|
||||
Scheduler.delay(10000);
|
||||
DEBUG("Restart...");
|
||||
|
||||
eeSettings.updateNow();
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
@@ -275,7 +372,10 @@ protected:
|
||||
|
||||
static void publishHaEntities() {
|
||||
// main
|
||||
haHelper.publishSelectOutdoorTempSource();
|
||||
haHelper.publishSelectOutdoorSensorType();
|
||||
haHelper.publishSelectIndoorSensorType();
|
||||
haHelper.publishNumberOutdoorSensorOffset(false);
|
||||
haHelper.publishNumberIndoorSensorOffset(false);
|
||||
haHelper.publishSwitchDebug(false);
|
||||
|
||||
// emergency
|
||||
@@ -289,16 +389,26 @@ protected:
|
||||
//haHelper.publishNumberHeatingTarget(false);
|
||||
haHelper.publishNumberHeatingHysteresis();
|
||||
haHelper.publishSensorHeatingSetpoint(false);
|
||||
haHelper.publishSensorCurrentHeatingMinTemp(false);
|
||||
haHelper.publishSensorCurrentHeatingMaxTemp(false);
|
||||
haHelper.publishNumberHeatingMinTemp(false);
|
||||
haHelper.publishNumberHeatingMaxTemp(false);
|
||||
|
||||
// dhw
|
||||
haHelper.publishSwitchDHW(false);
|
||||
//haHelper.publishNumberDHWTarget(false);
|
||||
haHelper.publishSensorCurrentDHWMinTemp(false);
|
||||
haHelper.publishSensorCurrentDHWMaxTemp(false);
|
||||
haHelper.publishNumberDHWMinTemp(false);
|
||||
haHelper.publishNumberDHWMaxTemp(false);
|
||||
|
||||
// pid
|
||||
haHelper.publishSwitchPID();
|
||||
haHelper.publishNumberPIDFactorP();
|
||||
haHelper.publishNumberPIDFactorI();
|
||||
haHelper.publishNumberPIDFactorD();
|
||||
haHelper.publishNumberPIDMinTemp(false);
|
||||
haHelper.publishNumberPIDMaxTemp(false);
|
||||
|
||||
// equitherm
|
||||
haHelper.publishSwitchEquitherm();
|
||||
@@ -319,7 +429,7 @@ protected:
|
||||
haHelper.publishBinSensorFault();
|
||||
haHelper.publishBinSensorDiagnostic();
|
||||
haHelper.publishSensorFaultCode();
|
||||
haHelper.publishSensorRssi();
|
||||
haHelper.publishSensorRssi(false);
|
||||
|
||||
// sensors
|
||||
haHelper.publishSensorModulation(false);
|
||||
@@ -333,18 +443,15 @@ protected:
|
||||
}
|
||||
|
||||
static bool publishNonStaticHaEntities(bool force = false) {
|
||||
static byte _heatingMinTemp;
|
||||
static byte _heatingMaxTemp;
|
||||
static byte _dhwMinTemp;
|
||||
static byte _dhwMaxTemp;
|
||||
static bool _editableOutdoorTemp;
|
||||
static byte _heatingMinTemp, _heatingMaxTemp, _dhwMinTemp, _dhwMaxTemp;
|
||||
static bool _editableOutdoorTemp, _editableIndoorTemp;
|
||||
|
||||
bool published = false;
|
||||
bool isStupidMode = !settings.pid.enable && !settings.equitherm.enable;
|
||||
byte heatingMinTemp = isStupidMode ? vars.parameters.heatingMinTemp : 10;
|
||||
byte heatingMaxTemp = isStupidMode ? vars.parameters.heatingMaxTemp : 30;
|
||||
bool editableOutdoorTemp = settings.outdoorTempSource == 1;
|
||||
|
||||
bool editableOutdoorTemp = settings.sensors.outdoor.type == 1;
|
||||
bool editableIndoorTemp = settings.sensors.indoor.type == 1;
|
||||
|
||||
if (force || _heatingMinTemp != heatingMinTemp || _heatingMaxTemp != heatingMaxTemp) {
|
||||
if (settings.heating.target < heatingMinTemp || settings.heating.target > heatingMaxTemp) {
|
||||
@@ -384,6 +491,20 @@ protected:
|
||||
published = true;
|
||||
}
|
||||
|
||||
if (force || _editableIndoorTemp != editableIndoorTemp) {
|
||||
_editableIndoorTemp = editableIndoorTemp;
|
||||
|
||||
if (editableIndoorTemp) {
|
||||
haHelper.deleteSensorIndoorTemp();
|
||||
haHelper.publishNumberIndoorTemp();
|
||||
} else {
|
||||
haHelper.deleteNumberIndoorTemp();
|
||||
haHelper.publishSensorIndoorTemp();
|
||||
}
|
||||
|
||||
published = true;
|
||||
}
|
||||
|
||||
return published;
|
||||
}
|
||||
|
||||
@@ -391,7 +512,6 @@ protected:
|
||||
StaticJsonDocument<2048> doc;
|
||||
|
||||
doc["debug"] = settings.debug;
|
||||
doc["outdoorTempSource"] = settings.outdoorTempSource;
|
||||
|
||||
doc["emergency"]["enable"] = settings.emergency.enable;
|
||||
doc["emergency"]["target"] = settings.emergency.target;
|
||||
@@ -401,20 +521,32 @@ protected:
|
||||
doc["heating"]["turbo"] = settings.heating.turbo;
|
||||
doc["heating"]["target"] = settings.heating.target;
|
||||
doc["heating"]["hysteresis"] = settings.heating.hysteresis;
|
||||
doc["heating"]["minTemp"] = settings.heating.minTemp;
|
||||
doc["heating"]["maxTemp"] = settings.heating.maxTemp;
|
||||
|
||||
doc["dhw"]["enable"] = settings.dhw.enable;
|
||||
doc["dhw"]["target"] = settings.dhw.target;
|
||||
doc["dhw"]["minTemp"] = settings.dhw.minTemp;
|
||||
doc["dhw"]["maxTemp"] = settings.dhw.maxTemp;
|
||||
|
||||
doc["pid"]["enable"] = settings.pid.enable;
|
||||
doc["pid"]["p_factor"] = settings.pid.p_factor;
|
||||
doc["pid"]["i_factor"] = settings.pid.i_factor;
|
||||
doc["pid"]["d_factor"] = settings.pid.d_factor;
|
||||
doc["pid"]["minTemp"] = settings.pid.minTemp;
|
||||
doc["pid"]["maxTemp"] = settings.pid.maxTemp;
|
||||
|
||||
doc["equitherm"]["enable"] = settings.equitherm.enable;
|
||||
doc["equitherm"]["n_factor"] = settings.equitherm.n_factor;
|
||||
doc["equitherm"]["k_factor"] = settings.equitherm.k_factor;
|
||||
doc["equitherm"]["t_factor"] = settings.equitherm.t_factor;
|
||||
|
||||
doc["sensors"]["outdoor"]["type"] = settings.sensors.outdoor.type;
|
||||
doc["sensors"]["outdoor"]["offset"] = settings.sensors.outdoor.offset;
|
||||
|
||||
doc["sensors"]["indoor"]["type"] = settings.sensors.indoor.type;
|
||||
doc["sensors"]["indoor"]["offset"] = settings.sensors.indoor.offset;
|
||||
|
||||
client.beginPublish(topic, measureJson(doc), false);
|
||||
//BufferingPrint bufferedClient(client, 32);
|
||||
//serializeJson(doc, bufferedClient);
|
||||
|
||||
@@ -9,6 +9,11 @@ public:
|
||||
|
||||
protected:
|
||||
void setup() {
|
||||
vars.parameters.heatingMinTemp = settings.heating.minTemp;
|
||||
vars.parameters.heatingMaxTemp = settings.heating.maxTemp;
|
||||
vars.parameters.dhwMinTemp = settings.dhw.minTemp;
|
||||
vars.parameters.dhwMaxTemp = settings.dhw.maxTemp;
|
||||
|
||||
ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin);
|
||||
|
||||
ot->begin(handleInterrupt, responseCallback);
|
||||
@@ -63,7 +68,7 @@ protected:
|
||||
updateMinMaxDhwTemp();
|
||||
updateMinMaxHeatingTemp();
|
||||
|
||||
if (settings.outdoorTempSource == 0) {
|
||||
if (settings.sensors.outdoor.type == 0) {
|
||||
updateOutsideTemp();
|
||||
}
|
||||
if (vars.states.fault) {
|
||||
@@ -83,6 +88,7 @@ protected:
|
||||
if ( settings.dhw.enable || settings.heating.enable || heatingEnable ) {
|
||||
updateModulationLevel();
|
||||
}
|
||||
yield();
|
||||
|
||||
if ( settings.dhw.enable ) {
|
||||
updateDHWTemp();
|
||||
@@ -95,7 +101,6 @@ protected:
|
||||
} else {
|
||||
vars.temperatures.heating = 0;
|
||||
}
|
||||
|
||||
yield();
|
||||
|
||||
//
|
||||
@@ -306,8 +311,8 @@ protected:
|
||||
byte maxTemp = (response & 0xFFFF) >> 8;
|
||||
|
||||
if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) {
|
||||
vars.parameters.dhwMinTemp = minTemp;
|
||||
vars.parameters.dhwMaxTemp = maxTemp;
|
||||
vars.parameters.dhwMinTemp = minTemp < settings.dhw.minTemp ? settings.dhw.minTemp : minTemp;
|
||||
vars.parameters.dhwMaxTemp = maxTemp > settings.dhw.maxTemp ? settings.dhw.maxTemp : maxTemp;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -325,8 +330,8 @@ protected:
|
||||
byte maxTemp = (response & 0xFFFF) >> 8;
|
||||
|
||||
if (minTemp >= 0 && maxTemp > 0 && maxTemp > minTemp) {
|
||||
vars.parameters.heatingMinTemp = minTemp;
|
||||
vars.parameters.heatingMaxTemp = maxTemp;
|
||||
vars.parameters.heatingMinTemp = minTemp < settings.heating.minTemp ? settings.heating.minTemp : minTemp;
|
||||
vars.parameters.heatingMaxTemp = maxTemp > settings.heating.maxTemp ? settings.heating.maxTemp : maxTemp;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -340,7 +345,7 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
vars.temperatures.outdoor = ot->getFloat(response);
|
||||
vars.temperatures.outdoor = ot->getFloat(response) + settings.sensors.outdoor.offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <PIDtuner.h>
|
||||
|
||||
Equitherm etRegulator;
|
||||
GyverPID pidRegulator(0, 0, 0, 10000);
|
||||
GyverPID pidRegulator(0, 0, 0);
|
||||
PIDtuner pidTuner;
|
||||
|
||||
class RegulatorTask: public LeanTask {
|
||||
@@ -73,7 +73,7 @@ protected:
|
||||
float newTemp = 0;
|
||||
|
||||
// if use equitherm
|
||||
if (settings.emergency.useEquitherm && settings.outdoorTempSource != 1) {
|
||||
if (settings.emergency.useEquitherm && settings.sensors.outdoor.type != 1) {
|
||||
float etResult = getEquithermTemp(vars.parameters.heatingMinTemp, vars.parameters.heatingMaxTemp);
|
||||
|
||||
if (fabs(prevEtResult - etResult) + 0.0001 >= 0.5) {
|
||||
@@ -123,21 +123,24 @@ protected:
|
||||
}
|
||||
|
||||
// if use pid
|
||||
if (settings.pid.enable) {
|
||||
if (settings.pid.enable && vars.states.heating) {
|
||||
float pidResult = getPidTemp(
|
||||
settings.equitherm.enable ? -30 : vars.parameters.heatingMinTemp,
|
||||
settings.equitherm.enable ? 30 : vars.parameters.heatingMaxTemp
|
||||
settings.equitherm.enable ? (settings.pid.maxTemp * -1) : settings.pid.minTemp,
|
||||
settings.equitherm.enable ? settings.pid.maxTemp : settings.pid.maxTemp
|
||||
);
|
||||
|
||||
if (fabs(prevPidResult - pidResult) + 0.0001 >= 0.5) {
|
||||
if (1 || fabs(prevPidResult - pidResult) + 0.0001 >= 0.5) {
|
||||
prevPidResult = pidResult;
|
||||
newTemp += pidResult;
|
||||
|
||||
INFO_F("[REGULATOR][PID] New result: %u (%f) \n", (int)round(pidResult), pidResult);
|
||||
INFO_F("[REGULATOR][PID] New result: %d (%f) \n", (int)round(pidResult), pidResult);
|
||||
|
||||
} else {
|
||||
newTemp += prevPidResult;
|
||||
}
|
||||
|
||||
} else if ( settings.pid.enable && !vars.states.heating && prevPidResult != 0 ) {
|
||||
newTemp += prevPidResult;
|
||||
}
|
||||
|
||||
// default temp, manual mode
|
||||
@@ -145,7 +148,9 @@ protected:
|
||||
newTemp = settings.heating.target;
|
||||
}
|
||||
|
||||
return round(newTemp);
|
||||
newTemp = round(newTemp);
|
||||
newTemp = constrain(newTemp, 0, 100);
|
||||
return newTemp;
|
||||
}
|
||||
|
||||
byte getTuningModeTemp() {
|
||||
@@ -269,7 +274,7 @@ protected:
|
||||
pidRegulator.input = vars.temperatures.indoor;
|
||||
pidRegulator.setpoint = settings.heating.target;
|
||||
|
||||
return pidRegulator.getResultTimer();
|
||||
return pidRegulator.getResultNow();
|
||||
}
|
||||
|
||||
float tuneEquithermN(float ratio, float currentTemp, float setTemp, unsigned int dirtyInterval = 60, unsigned int accurateInterval = 1800, float accurateStep = 0.01, float accurateStepAfter = 1) {
|
||||
|
||||
@@ -1,45 +1,149 @@
|
||||
#include <microDS18B20.h>
|
||||
|
||||
MicroDS18B20<DS18B20_PIN> outdoorSensor;
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
|
||||
class SensorsTask: public LeanTask {
|
||||
public:
|
||||
SensorsTask(bool _enabled = false, unsigned long _interval = 0): LeanTask(_enabled, _interval) {}
|
||||
|
||||
protected:
|
||||
OneWire* oneWireOutdoorSensor;
|
||||
OneWire* oneWireIndoorSensor;
|
||||
|
||||
DallasTemperature* outdoorSensor;
|
||||
DallasTemperature* indoorSensor;
|
||||
|
||||
bool initOutdoorSensor = false;
|
||||
unsigned long startConversionTime = 0;
|
||||
float filteredOutdoorTemp = 0;
|
||||
bool emptyOutdoorTemp = true;
|
||||
|
||||
bool initIndoorSensor = false;
|
||||
float filteredIndoorTemp = 0;
|
||||
bool emptyIndoorTemp = true;
|
||||
|
||||
|
||||
void setup() {}
|
||||
|
||||
void loop() {
|
||||
// DS18B20 sensor
|
||||
if (outdoorSensor.online()) {
|
||||
if (outdoorSensor.readTemp()) {
|
||||
float rawTemp = outdoorSensor.getTemp();
|
||||
DEBUG_F("[SENSORS][DS18B20] Raw temp: %f \n", rawTemp);
|
||||
if ( settings.sensors.outdoor.type == 2 ) {
|
||||
outdoorTemperatureSensor();
|
||||
}
|
||||
|
||||
if (emptyOutdoorTemp) {
|
||||
filteredOutdoorTemp = rawTemp;
|
||||
emptyOutdoorTemp = false;
|
||||
|
||||
} else {
|
||||
filteredOutdoorTemp += (rawTemp - filteredOutdoorTemp) * OUTDOOR_SENSOR_FILTER_K;
|
||||
}
|
||||
|
||||
filteredOutdoorTemp = floor(filteredOutdoorTemp * 100) / 100;
|
||||
|
||||
if (fabs(vars.temperatures.outdoor - filteredOutdoorTemp) > 0.099) {
|
||||
vars.temperatures.outdoor = filteredOutdoorTemp;
|
||||
INFO_F("[SENSORS][DS18B20] New temp: %f \n", filteredOutdoorTemp);
|
||||
}
|
||||
|
||||
} else {
|
||||
ERROR("[SENSORS][DS18B20] Invalid data from sensor");
|
||||
}
|
||||
|
||||
outdoorSensor.requestTemp();
|
||||
} else {
|
||||
ERROR("[SENSORS][DS18B20] Failed to connect to sensor");
|
||||
if ( settings.sensors.indoor.type == 2 ) {
|
||||
indoorTemperatureSensor();
|
||||
}
|
||||
}
|
||||
|
||||
void outdoorTemperatureSensor() {
|
||||
if ( !initOutdoorSensor ) {
|
||||
oneWireOutdoorSensor = new OneWire(settings.sensors.outdoor.pin);
|
||||
outdoorSensor = new DallasTemperature(oneWireOutdoorSensor);
|
||||
outdoorSensor->begin();
|
||||
outdoorSensor->setResolution(12);
|
||||
outdoorSensor->setWaitForConversion(false);
|
||||
outdoorSensor->requestTemperatures();
|
||||
startConversionTime = millis();
|
||||
initOutdoorSensor = true;
|
||||
}
|
||||
|
||||
unsigned long estimateConversionTime = millis() - startConversionTime;
|
||||
if ( estimateConversionTime < outdoorSensor->millisToWaitForConversion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool completed = outdoorSensor->isConversionComplete();
|
||||
if ( !completed && estimateConversionTime >= 1000 ) {
|
||||
// fail, retry
|
||||
outdoorSensor->requestTemperatures();
|
||||
startConversionTime = millis();
|
||||
|
||||
ERROR("[SENSORS][OUTDOOR] Could not read temperature data (no response)");
|
||||
}
|
||||
|
||||
if ( !completed ) {
|
||||
return;
|
||||
}
|
||||
|
||||
float rawTemp = outdoorSensor->getTempCByIndex(0);
|
||||
if (rawTemp == DEVICE_DISCONNECTED_C) {
|
||||
ERROR("[SENSORS][OUTDOOR] Could not read temperature data (not connected)");
|
||||
|
||||
} else {
|
||||
DEBUG_F("[SENSORS][OUTDOOR] Raw temp: %f \n", rawTemp);
|
||||
|
||||
if (emptyOutdoorTemp) {
|
||||
filteredOutdoorTemp = rawTemp;
|
||||
emptyOutdoorTemp = false;
|
||||
|
||||
} else {
|
||||
filteredOutdoorTemp += (rawTemp - filteredOutdoorTemp) * EXT_SENSORS_FILTER_K;
|
||||
}
|
||||
|
||||
filteredOutdoorTemp = floor(filteredOutdoorTemp * 100) / 100;
|
||||
|
||||
if (fabs(vars.temperatures.outdoor - filteredOutdoorTemp) > 0.099) {
|
||||
vars.temperatures.outdoor = filteredOutdoorTemp + settings.sensors.outdoor.offset;
|
||||
INFO_F("[SENSORS][OUTDOOR] New temp: %f \n", filteredOutdoorTemp);
|
||||
}
|
||||
}
|
||||
|
||||
outdoorSensor->requestTemperatures();
|
||||
startConversionTime = millis();
|
||||
}
|
||||
|
||||
void indoorTemperatureSensor() {
|
||||
if ( !initIndoorSensor ) {
|
||||
oneWireIndoorSensor = new OneWire(settings.sensors.indoor.pin);
|
||||
indoorSensor = new DallasTemperature(oneWireIndoorSensor);
|
||||
indoorSensor->begin();
|
||||
indoorSensor->setResolution(12);
|
||||
indoorSensor->setWaitForConversion(false);
|
||||
indoorSensor->requestTemperatures();
|
||||
startConversionTime = millis();
|
||||
initIndoorSensor = true;
|
||||
}
|
||||
|
||||
unsigned long estimateConversionTime = millis() - startConversionTime;
|
||||
if ( estimateConversionTime < indoorSensor->millisToWaitForConversion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool completed = indoorSensor->isConversionComplete();
|
||||
if ( !completed && estimateConversionTime >= 1000 ) {
|
||||
// fail, retry
|
||||
indoorSensor->requestTemperatures();
|
||||
startConversionTime = millis();
|
||||
|
||||
ERROR("[SENSORS][INDOOR] Could not read temperature data (no response)");
|
||||
}
|
||||
|
||||
if ( !completed ) {
|
||||
return;
|
||||
}
|
||||
|
||||
float rawTemp = indoorSensor->getTempCByIndex(0);
|
||||
if (rawTemp == DEVICE_DISCONNECTED_C) {
|
||||
ERROR("[SENSORS][INDOOR] Could not read temperature data (not connected)");
|
||||
|
||||
} else {
|
||||
DEBUG_F("[SENSORS][INDOOR] Raw temp: %f \n", rawTemp);
|
||||
|
||||
if (emptyIndoorTemp) {
|
||||
filteredIndoorTemp = rawTemp;
|
||||
emptyIndoorTemp = false;
|
||||
|
||||
} else {
|
||||
filteredIndoorTemp += (rawTemp - filteredIndoorTemp) * EXT_SENSORS_FILTER_K;
|
||||
}
|
||||
|
||||
filteredIndoorTemp = floor(filteredIndoorTemp * 100) / 100;
|
||||
|
||||
if (fabs(vars.temperatures.indoor - filteredIndoorTemp) > 0.099) {
|
||||
vars.temperatures.indoor = filteredIndoorTemp + settings.sensors.indoor.offset;
|
||||
INFO_F("[SENSORS][INDOOR] New temp: %f \n", filteredIndoorTemp);
|
||||
}
|
||||
}
|
||||
|
||||
indoorSensor->requestTemperatures();
|
||||
startConversionTime = millis();
|
||||
}
|
||||
};
|
||||
@@ -1,12 +1,10 @@
|
||||
struct Settings {
|
||||
bool debug = false;
|
||||
// 0 - boiler, 1 - manual, 2 - ds18b20
|
||||
byte outdoorTempSource = 0;
|
||||
char hostname[80] = "opentherm";
|
||||
|
||||
struct {
|
||||
byte inPin = 5;
|
||||
byte outPin = 4;
|
||||
byte inPin = 4;
|
||||
byte outPin = 5;
|
||||
unsigned int memberIdCode = 0;
|
||||
} opentherm;
|
||||
|
||||
@@ -30,11 +28,15 @@ struct Settings {
|
||||
bool turbo = false;
|
||||
float target = 40.0f;
|
||||
float hysteresis = 0.5f;
|
||||
byte minTemp = 20.0f;
|
||||
byte maxTemp = 90.0f;
|
||||
} heating;
|
||||
|
||||
struct {
|
||||
bool enable = true;
|
||||
byte target = 40;
|
||||
byte minTemp = 30.0f;
|
||||
byte maxTemp = 60.0f;
|
||||
} dhw;
|
||||
|
||||
struct {
|
||||
@@ -42,6 +44,8 @@ struct Settings {
|
||||
float p_factor = 3;
|
||||
float i_factor = 0.2f;
|
||||
float d_factor = 0;
|
||||
byte minTemp = 0.0f;
|
||||
byte maxTemp = 90.0f;
|
||||
} pid;
|
||||
|
||||
struct {
|
||||
@@ -51,6 +55,23 @@ struct Settings {
|
||||
float t_factor = 2.0f;
|
||||
} equitherm;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
// 0 - boiler, 1 - manual, 2 - ds18b20
|
||||
byte type = 0;
|
||||
byte pin = 12;
|
||||
float offset = 0.0f;
|
||||
} outdoor;
|
||||
|
||||
struct {
|
||||
// 1 - manual, 2 - ds18b20
|
||||
byte type = 1;
|
||||
byte pin = 14;
|
||||
float offset = 0.0f;
|
||||
} indoor;
|
||||
} sensors;
|
||||
|
||||
char validationValue[8] = SETTINGS_VALID_VALUE;
|
||||
} settings;
|
||||
|
||||
struct Variables {
|
||||
@@ -84,11 +105,11 @@ struct Variables {
|
||||
} temperatures;
|
||||
|
||||
struct {
|
||||
byte heatingMinTemp = 20;
|
||||
byte heatingMaxTemp = 90;
|
||||
byte heatingMinTemp = 0;
|
||||
byte heatingMaxTemp = 0;
|
||||
byte heatingSetpoint = 0.0f;
|
||||
byte dhwMinTemp = 30;
|
||||
byte dhwMaxTemp = 60;
|
||||
byte dhwMinTemp = 0;
|
||||
byte dhwMaxTemp = 0;
|
||||
uint8_t slaveMemberIdCode;
|
||||
uint8_t slaveType;
|
||||
uint8_t slaveVersion;
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
// Wifimanager
|
||||
WiFiManager wm;
|
||||
WiFiManagerParameter* wmHostname;
|
||||
WiFiManagerParameter* wmOtInPin;
|
||||
WiFiManagerParameter* wmOtOutPin;
|
||||
WiFiManagerParameter* wmOtMemberIdCode;
|
||||
WiFiManagerParameter* wmMqttServer;
|
||||
WiFiManagerParameter* wmMqttPort;
|
||||
WiFiManagerParameter* wmMqttUser;
|
||||
WiFiManagerParameter* wmMqttPassword;
|
||||
WiFiManagerParameter* wmMqttPrefix;
|
||||
WiFiManagerParameter* wmMqttPublishInterval;
|
||||
WiFiManagerParameter* wmOtInPin;
|
||||
WiFiManagerParameter* wmOtOutPin;
|
||||
WiFiManagerParameter* wmOtMemberIdCode;
|
||||
WiFiManagerParameter* wmOutdoorSensorPin;
|
||||
WiFiManagerParameter* wmIndoorSensorPin;
|
||||
|
||||
class WifiManagerTask: public Task {
|
||||
public:
|
||||
@@ -24,18 +27,6 @@ protected:
|
||||
wmHostname = new WiFiManagerParameter("hostname", "Hostname", settings.hostname, 80);
|
||||
wm.addParameter(wmHostname);
|
||||
|
||||
sprintf(buffer, "%d", settings.opentherm.inPin);
|
||||
wmOtInPin = new WiFiManagerParameter("ot_in_pin", "Opentherm pin IN", buffer, 1);
|
||||
wm.addParameter(wmOtInPin);
|
||||
|
||||
sprintf(buffer, "%d", settings.opentherm.outPin);
|
||||
wmOtOutPin = new WiFiManagerParameter("ot_out_pin", "Opentherm pin OUT", buffer, 1);
|
||||
wm.addParameter(wmOtOutPin);
|
||||
|
||||
sprintf(buffer, "%d", settings.opentherm.memberIdCode);
|
||||
wmOtMemberIdCode = new WiFiManagerParameter("ot_member_id_code", "Opentherm member id code", buffer, 5);
|
||||
wm.addParameter(wmOtMemberIdCode);
|
||||
|
||||
wmMqttServer = new WiFiManagerParameter("mqtt_server", "MQTT server", settings.mqtt.server, 80);
|
||||
wm.addParameter(wmMqttServer);
|
||||
|
||||
@@ -52,6 +43,30 @@ protected:
|
||||
wmMqttPrefix = new WiFiManagerParameter("mqtt_prefix", "MQTT prefix", settings.mqtt.prefix, 32);
|
||||
wm.addParameter(wmMqttPrefix);
|
||||
|
||||
sprintf(buffer, "%d", settings.mqtt.interval);
|
||||
wmMqttPublishInterval = new WiFiManagerParameter("mqtt_publish_interval", "MQTT publish interval", buffer, 5);
|
||||
wm.addParameter(wmMqttPublishInterval);
|
||||
|
||||
sprintf(buffer, "%d", settings.opentherm.inPin);
|
||||
wmOtInPin = new WiFiManagerParameter("ot_in_pin", "Opentherm pin IN", buffer, 2);
|
||||
wm.addParameter(wmOtInPin);
|
||||
|
||||
sprintf(buffer, "%d", settings.opentherm.outPin);
|
||||
wmOtOutPin = new WiFiManagerParameter("ot_out_pin", "Opentherm pin OUT", buffer, 2);
|
||||
wm.addParameter(wmOtOutPin);
|
||||
|
||||
sprintf(buffer, "%d", settings.opentherm.memberIdCode);
|
||||
wmOtMemberIdCode = new WiFiManagerParameter("ot_member_id_code", "Opentherm member id", buffer, 5);
|
||||
wm.addParameter(wmOtMemberIdCode);
|
||||
|
||||
sprintf(buffer, "%d", settings.sensors.outdoor.pin);
|
||||
wmOutdoorSensorPin = new WiFiManagerParameter("outdoor_sensor_pin", "Outdoor sensor pin", buffer, 2);
|
||||
wm.addParameter(wmOutdoorSensorPin);
|
||||
|
||||
sprintf(buffer, "%d", settings.sensors.indoor.pin);
|
||||
wmIndoorSensorPin = new WiFiManagerParameter("indoor_sensor_pin", "Indoor sensor pin", buffer, 2);
|
||||
wm.addParameter(wmIndoorSensorPin);
|
||||
|
||||
//wm.setCleanConnect(true);
|
||||
wm.setRestorePersistent(false);
|
||||
|
||||
@@ -94,32 +109,43 @@ protected:
|
||||
|
||||
void static saveParamsCallback() {
|
||||
strcpy(settings.hostname, wmHostname->getValue());
|
||||
settings.opentherm.inPin = atoi(wmOtInPin->getValue());
|
||||
settings.opentherm.outPin = atoi(wmOtOutPin->getValue());
|
||||
settings.opentherm.memberIdCode = atoi(wmOtMemberIdCode->getValue());
|
||||
strcpy(settings.mqtt.server, wmMqttServer->getValue());
|
||||
settings.mqtt.port = atoi(wmMqttPort->getValue());
|
||||
strcpy(settings.mqtt.user, wmMqttUser->getValue());
|
||||
strcpy(settings.mqtt.password, wmMqttPassword->getValue());
|
||||
strcpy(settings.mqtt.prefix, wmMqttPrefix->getValue());
|
||||
settings.mqtt.interval = atoi(wmMqttPublishInterval->getValue());
|
||||
settings.opentherm.inPin = atoi(wmOtInPin->getValue());
|
||||
settings.opentherm.outPin = atoi(wmOtOutPin->getValue());
|
||||
settings.opentherm.memberIdCode = atoi(wmOtMemberIdCode->getValue());
|
||||
settings.sensors.outdoor.pin = atoi(wmOutdoorSensorPin->getValue());
|
||||
settings.sensors.indoor.pin = atoi(wmIndoorSensorPin->getValue());
|
||||
|
||||
INFO_F(
|
||||
"New settings:\r\n"
|
||||
" Hostname: %s\r\n"
|
||||
" OT in pin: %d"
|
||||
" OT out pin: %d"
|
||||
" OT member id code: %d"
|
||||
" Mqtt server: %s:%d\r\n"
|
||||
" Mqtt user: %s\r\n"
|
||||
" Mqtt pass: %s\r\n",
|
||||
" Mqtt pass: %s\r\n"
|
||||
" Mqtt prefix: %s\r\n"
|
||||
" Mqtt publish interval: %d\r\n"
|
||||
" OT in pin: %d\r\n"
|
||||
" OT out pin: %d\r\n"
|
||||
" OT member id code: %d\r\n"
|
||||
" Outdoor sensor pin: %d\r\n"
|
||||
" Indoor sensor pin: %d\r\n",
|
||||
settings.hostname,
|
||||
settings.opentherm.inPin,
|
||||
settings.opentherm.outPin,
|
||||
settings.opentherm.memberIdCode,
|
||||
settings.mqtt.server,
|
||||
settings.mqtt.port,
|
||||
settings.mqtt.user,
|
||||
settings.mqtt.password
|
||||
settings.mqtt.password,
|
||||
settings.mqtt.prefix,
|
||||
settings.mqtt.interval,
|
||||
settings.opentherm.inPin,
|
||||
settings.opentherm.outPin,
|
||||
settings.opentherm.memberIdCode,
|
||||
settings.sensors.outdoor.pin,
|
||||
settings.sensors.indoor.pin
|
||||
);
|
||||
eeSettings.updateNow();
|
||||
INFO(F("Settings saved"));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define OT_GATEWAY_VERSION "1.2.1"
|
||||
#define OT_GATEWAY_VERSION "1.3.0"
|
||||
#define AP_SSID "OpenTherm Gateway"
|
||||
#define AP_PASSWORD "otgateway123456"
|
||||
#define USE_TELNET
|
||||
@@ -9,9 +9,8 @@
|
||||
|
||||
#define OPENTHERM_OFFLINE_TRESHOLD 10
|
||||
|
||||
#define DS18B20_PIN 2
|
||||
#define DS18B20_INTERVAL 5000
|
||||
#define OUTDOOR_SENSOR_FILTER_K 0.15
|
||||
#define EXT_SENSORS_INTERVAL 5000
|
||||
#define EXT_SENSORS_FILTER_K 0.15
|
||||
#define DS_CHECK_CRC true
|
||||
#define DS_CRC_USE_TABLE true
|
||||
|
||||
@@ -19,6 +18,7 @@
|
||||
#define LED_OT_RX_PIN 15
|
||||
|
||||
#define CONFIG_URL "http://%s/"
|
||||
#define SETTINGS_VALID_VALUE "stvalid" // only 8 chars!
|
||||
|
||||
|
||||
#ifdef USE_TELNET
|
||||
|
||||
11
src/main.cpp
11
src/main.cpp
@@ -29,7 +29,7 @@ MainTask* tMain;
|
||||
void setup() {
|
||||
#ifdef USE_TELNET
|
||||
TelnetStream.begin();
|
||||
delay(5000);
|
||||
delay(1000);
|
||||
#else
|
||||
Serial.begin(115200);
|
||||
Serial.println("\n\n");
|
||||
@@ -40,6 +40,13 @@ void setup() {
|
||||
if (eeSettingsResult == 0) {
|
||||
INFO("Settings loaded");
|
||||
|
||||
if ( strcmp(SETTINGS_VALID_VALUE, settings.validationValue) != 0 ) {
|
||||
INFO("Settings not valid, reset and restart...");
|
||||
eeSettings.reset();
|
||||
delay(1000);
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
} else if (eeSettingsResult == 1) {
|
||||
INFO("Settings NOT loaded, first start");
|
||||
|
||||
@@ -56,7 +63,7 @@ void setup() {
|
||||
tOt = new OpenThermTask(false);
|
||||
Scheduler.start(tOt);
|
||||
|
||||
tSensors = new SensorsTask(false, DS18B20_INTERVAL);
|
||||
tSensors = new SensorsTask(true, EXT_SENSORS_INTERVAL);
|
||||
Scheduler.start(tSensors);
|
||||
|
||||
tRegulator = new RegulatorTask(true, 10000);
|
||||
|
||||
Reference in New Issue
Block a user