mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
heatpump support - #560
This commit is contained in:
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- new command under system called `report`. http://ems-esp/api?device=system&cmd=report to generate a report log for troubleshooting
|
- new command under system called `report`. http://ems-esp/api?device=system&cmd=report to generate a report log for troubleshooting
|
||||||
- thermostat error codes
|
- thermostat error codes
|
||||||
- Console command `pulbish ha` to also force the creation of the Home Assistant MQTT Discovery topics
|
- Console command `pulbish ha` to also force the creation of the Home Assistant MQTT Discovery topics
|
||||||
|
- Heatpump values
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- fix wwontime readback
|
- fix wwontime readback
|
||||||
|
|||||||
@@ -29,27 +29,128 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
|
|||||||
LOG_DEBUG(F("Adding new Heat Pump module with device ID 0x%02X"), device_id);
|
LOG_DEBUG(F("Adding new Heat Pump module with device ID 0x%02X"), device_id);
|
||||||
|
|
||||||
// telegram handlers
|
// telegram handlers
|
||||||
register_telegram_type(0x047B, F("HP1"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor1(t); });
|
register_telegram_type(0x042B, F("HP1"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor1(t); });
|
||||||
register_telegram_type(0x042B, F("HP2"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor2(t); });
|
register_telegram_type(0x047B, F("HP2"), true, [&](std::shared_ptr<const Telegram> t) { process_HPMonitor2(t); });
|
||||||
|
|
||||||
|
// API call
|
||||||
|
Command::add_with_json(this->device_type(), F("info"), [&](const char * value, const int8_t id, JsonObject & object) {
|
||||||
|
return command_info(value, id, object);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Heatpump::command_info(const char * value, const int8_t id, JsonObject & output) {
|
||||||
|
return (export_values(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates JSON doc from values
|
||||||
|
// returns false if empty
|
||||||
|
bool Heatpump::export_values(JsonObject & output) {
|
||||||
|
if (Helpers::hasValue(airHumidity_)) {
|
||||||
|
output["airHumidity"] = (float)airHumidity_ / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Helpers::hasValue(dewTemperature_)) {
|
||||||
|
output["dewTemperature"] = dewTemperature_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heatpump::device_info_web(JsonArray & root) {
|
void Heatpump::device_info_web(JsonArray & root) {
|
||||||
|
// fetch the values into a JSON document
|
||||||
|
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||||
|
JsonObject output = doc.to<JsonObject>();
|
||||||
|
if (!export_values(output)) {
|
||||||
|
return; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
print_value_json(root, F("airHumidity"), nullptr, F_(airHumidity), F_(percent), output);
|
||||||
|
print_value_json(root, F("dewTemperature"), nullptr, F_(dewTemperature), F_(degrees), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// display all values into the shell console
|
// display all values into the shell console
|
||||||
void Heatpump::show_values(uuid::console::Shell & shell) {
|
void Heatpump::show_values(uuid::console::Shell & shell) {
|
||||||
// EMSdevice::show_values(shell); // always call this to show header
|
EMSdevice::show_values(shell); // always call this to show header
|
||||||
|
|
||||||
|
// fetch the values into a JSON document
|
||||||
|
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||||
|
JsonObject output = doc.to<JsonObject>();
|
||||||
|
if (!export_values(output)) {
|
||||||
|
return; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
print_value_json(shell, F("airHumidity"), nullptr, F_(airHumidity), F_(percent), output);
|
||||||
|
print_value_json(shell, F("dewTemperature"), nullptr, F_(dewTemperature), F_(degrees), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish values via MQTT
|
// publish values via MQTT
|
||||||
void Heatpump::publish_values(JsonObject & data, bool force) {
|
void Heatpump::publish_values(JsonObject & data, bool force) {
|
||||||
|
// handle HA first
|
||||||
|
if (Mqtt::mqtt_format() == Mqtt::Format::HA) {
|
||||||
|
register_mqtt_ha_config(force);
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||||
|
JsonObject output = doc.to<JsonObject>();
|
||||||
|
if (export_values(output)) {
|
||||||
|
Mqtt::publish(F("heatpump_data"), doc.as<JsonObject>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Heatpump::register_mqtt_ha_config(bool force) {
|
||||||
|
if ((mqtt_ha_config_ && !force)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Mqtt::connected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the Master device
|
||||||
|
StaticJsonDocument<EMSESP_MAX_JSON_SIZE_MEDIUM> doc;
|
||||||
|
doc["name"] = F_(EMSESP);
|
||||||
|
doc["uniq_id"] = F_(heatpump);
|
||||||
|
doc["ic"] = F_(iconheatpump);
|
||||||
|
|
||||||
|
char stat_t[50];
|
||||||
|
snprintf_P(stat_t, sizeof(stat_t), PSTR("%s/heatpump_data"), System::hostname().c_str());
|
||||||
|
doc["stat_t"] = stat_t;
|
||||||
|
|
||||||
|
doc["val_tpl"] = F("{{value_json.airHumidity}}");
|
||||||
|
|
||||||
|
JsonObject dev = doc.createNestedObject("dev");
|
||||||
|
dev["name"] = F("EMS-ESP Heat Pump");
|
||||||
|
dev["sw"] = EMSESP_APP_VERSION;
|
||||||
|
dev["mf"] = this->brand_to_string();
|
||||||
|
dev["mdl"] = this->name();
|
||||||
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
|
ids.add("ems-esp-heatpump");
|
||||||
|
Mqtt::publish_retain(F("homeassistant/sensor/ems-esp/heatpump/config"), doc.as<JsonObject>(), true); // publish the config payload with retain flag
|
||||||
|
|
||||||
|
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(airHumidity), this->device_type(), "airHumidity", F_(percent), nullptr);
|
||||||
|
Mqtt::register_mqtt_ha_sensor(nullptr, nullptr, F_(dewTemperature), this->device_type(), "dewTemperature", F_(degrees), nullptr);
|
||||||
|
|
||||||
|
mqtt_ha_config_ = true; // done
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if values have been updated
|
// check to see if values have been updated
|
||||||
bool Heatpump::updated_values() {
|
bool Heatpump::updated_values() {
|
||||||
|
if (changed_) {
|
||||||
|
changed_ = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Type 0x47B - HeatPump Monitor 2
|
||||||
|
* e.g. "38 10 FF 00 03 7B 08 24 00 4B"
|
||||||
|
*/
|
||||||
|
void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
changed_ |= telegram->read_value(dewTemperature_, 0);
|
||||||
|
changed_ |= telegram->read_value(airHumidity_, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
@@ -61,14 +162,6 @@ void Heatpump::process_HPMonitor1(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// still to implement
|
// still to implement
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Type 0x47B - HeatPump Monitor 2
|
|
||||||
* e.g. "38 10 FF 00 03 7B 08 24 00 4B"
|
|
||||||
*/
|
|
||||||
void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
|
|
||||||
// still to implement
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <uuid/log.h>
|
#include <uuid/log.h>
|
||||||
|
|
||||||
#include "emsdevice.h"
|
#include "emsdevice.h"
|
||||||
|
#include "emsesp.h"
|
||||||
#include "telegram.h"
|
#include "telegram.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
@@ -43,6 +44,16 @@ class Heatpump : public EMSdevice {
|
|||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|
||||||
|
bool export_values(JsonObject & doc);
|
||||||
|
bool command_info(const char * value, const int8_t id, JsonObject & output);
|
||||||
|
void register_mqtt_ha_config(bool force);
|
||||||
|
|
||||||
|
uint8_t airHumidity_ = EMS_VALUE_UINT_NOTSET;
|
||||||
|
uint8_t dewTemperature_ = EMS_VALUE_UINT_NOTSET;
|
||||||
|
|
||||||
|
bool changed_ = false;
|
||||||
|
bool mqtt_ha_config_ = false; // for HA MQTT Discovery
|
||||||
|
|
||||||
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
|
void process_HPMonitor1(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);
|
void process_HPMonitor2(std::shared_ptr<const Telegram> telegram);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ MAKE_PSTR(1space, " ")
|
|||||||
MAKE_PSTR(2spaces, " ")
|
MAKE_PSTR(2spaces, " ")
|
||||||
MAKE_PSTR(kwh, "kWh")
|
MAKE_PSTR(kwh, "kWh")
|
||||||
MAKE_PSTR(wh, "Wh")
|
MAKE_PSTR(wh, "Wh")
|
||||||
|
MAKE_PSTR(EMSESP, "EMS-ESP")
|
||||||
MAKE_PSTR(master_thermostat_fmt, "Master Thermostat Device ID = %s")
|
MAKE_PSTR(master_thermostat_fmt, "Master Thermostat Device ID = %s")
|
||||||
MAKE_PSTR(host_fmt, "Host = %s")
|
MAKE_PSTR(host_fmt, "Host = %s")
|
||||||
MAKE_PSTR(hostname_fmt, "WiFi Hostname = %s")
|
MAKE_PSTR(hostname_fmt, "WiFi Hostname = %s")
|
||||||
@@ -260,6 +261,10 @@ MAKE_PSTR(roominfluence, "Room influence")
|
|||||||
MAKE_PSTR(mode, "Mode")
|
MAKE_PSTR(mode, "Mode")
|
||||||
MAKE_PSTR(modetype, "Mode type")
|
MAKE_PSTR(modetype, "Mode type")
|
||||||
|
|
||||||
|
// heat pump
|
||||||
|
MAKE_PSTR(airHumidity, "Relative air humidity")
|
||||||
|
MAKE_PSTR(dewTemperature, "Dew point temperature")
|
||||||
|
|
||||||
// HA icons
|
// HA icons
|
||||||
MAKE_PSTR(icontemperature, "mdi:coolant-temperature")
|
MAKE_PSTR(icontemperature, "mdi:coolant-temperature")
|
||||||
MAKE_PSTR(iconpercent, "mdi:sine-wave")
|
MAKE_PSTR(iconpercent, "mdi:sine-wave")
|
||||||
@@ -272,6 +277,8 @@ MAKE_PSTR(iconimport, "mdi:home-import-outline")
|
|||||||
MAKE_PSTR(iconcruise, "mdi:car-cruise-control")
|
MAKE_PSTR(iconcruise, "mdi:car-cruise-control")
|
||||||
MAKE_PSTR(iconvalve, "mdi:valve")
|
MAKE_PSTR(iconvalve, "mdi:valve")
|
||||||
MAKE_PSTR(iconpower, "mdi:power-cycle")
|
MAKE_PSTR(iconpower, "mdi:power-cycle")
|
||||||
|
MAKE_PSTR(iconthermostat, "mdi:home-thermometer-outline")
|
||||||
|
MAKE_PSTR(iconheatpump, "mdi:water-pump")
|
||||||
|
|
||||||
// MQTT topic suffix
|
// MQTT topic suffix
|
||||||
MAKE_PSTR(mqtt_suffix_main, "_main")
|
MAKE_PSTR(mqtt_suffix_main, "_main")
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace emsesp {
|
|||||||
// used with the 'test' command, under su/admin
|
// used with the 'test' command, under su/admin
|
||||||
void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||||
if (command == "default") {
|
if (command == "default") {
|
||||||
run_test(shell, "general"); // add the default test case here
|
run_test(shell, "heatpump"); // add the default test case here
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.empty()) {
|
if (command.empty()) {
|
||||||
@@ -368,6 +368,27 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
|||||||
EMSESP::show_device_values(shell);
|
EMSESP::show_device_values(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (command == "heatpump") {
|
||||||
|
shell.printfln(F("Testing Heat Pump"));
|
||||||
|
|
||||||
|
EMSESP::rxservice_.ems_mask(EMSbus::EMS_MASK_BUDERUS);
|
||||||
|
|
||||||
|
std::string version("1.2.3");
|
||||||
|
|
||||||
|
// add heatpump
|
||||||
|
EMSESP::add_device(0x38, 200, version, EMSdevice::Brand::BUDERUS); // Enviline module
|
||||||
|
|
||||||
|
// add a thermostat
|
||||||
|
EMSESP::add_device(0x10, 192, version, EMSdevice::Brand::JUNKERS); // FW120
|
||||||
|
uart_telegram({0x90, 0x00, 0xFF, 0x00, 0x00, 0x6F, 0x00, 0xCF, 0x21, 0x2E, 0x20, 0x00, 0x2E, 0x24,
|
||||||
|
0x03, 0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03}); // HC1
|
||||||
|
|
||||||
|
uart_telegram("38 0B FF 00 03 7B 0C 34 00 74");
|
||||||
|
shell.invoke_command("call");
|
||||||
|
shell.invoke_command("call heatpump info");
|
||||||
|
EMSESP::show_device_values(shell);
|
||||||
|
}
|
||||||
|
|
||||||
if (command == "solar200") {
|
if (command == "solar200") {
|
||||||
shell.printfln(F("Testing Solar SM200"));
|
shell.printfln(F("Testing Solar SM200"));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user