Skip to content

Commit

Permalink
Add control z1 flow temperature target
Browse files Browse the repository at this point in the history
  • Loading branch information
limkinZero committed Nov 30, 2023
1 parent 4370c09 commit 6ab64bb
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Uses the CN105 connector on the Cased Flow Temp Controller (FTC6 in my setup) to
- Manage water boiler. Configure temperature set point and its modes (eco or normal).
- Control to boost DHW.
- Control to turn ON and turn OFF ecodan.
- Control to set point zone flow temperature target.

## Sensors information retreived
- Defrost mode
Expand All @@ -18,7 +19,9 @@ Uses the CN105 connector on the Cased Flow Temp Controller (FTC6 in my setup) to
- Output power
- Legionella prevention temperature setting
- Zone 1 room temperature
- Zone 1 flow temperature target
- Zone 2 room temperature
- Zone 2 flow temperature target
- Dhw current temperature
- Dhw temperature target
- Dhw temperature drop
Expand Down
47 changes: 47 additions & 0 deletions ecodan-ha-local/ehal_hp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,53 @@ namespace ehal::hp
return 60.0f;
}

// From FTC6 installation manual ("Zone heating/cooling min. temp.")
float get_min_flow_target_temperature(String mode)
{
String coolMode = "Cool Flow Temperature";
return (coolMode == mode) ? 5.0f : 20.0f;
}

float get_max_flow_target_temperature(String mode)
{
String coolMode = "Cool Flow Temperature";
return (coolMode == mode) ? 25.0f : 60.0f;
}

bool set_z1_flow_target_temperature(float newTemp)
{
if (newTemp > get_max_flow_target_temperature(status.hp_mode_as_string()))
{
log_web(F("Z1 flow temperature setting exceeds maximum allowed (%s)!"), String(get_max_flow_target_temperature(status.hp_mode_as_string())).c_str());
return false;
}

if (newTemp < get_min_flow_target_temperature(status.hp_mode_as_string()))
{
log_web(F("Z1 flow temperature setting is lower than minimum allowed (%s)!"), String(get_min_flow_target_temperature(status.hp_mode_as_string())).c_str());
return false;
}

Message cmd{MsgType::SET_CMD, SetType::BASIC_SETTINGS};
cmd[1] = SET_SETTINGS_FLAG_ZONE_TEMPERATURE;
cmd[2] = static_cast<uint8_t>(SetZone::ZONE_1);
cmd[6] = static_cast<uint8_t>(SetHpMode::FLOW_CONTROL_MODE);
cmd.set_float16(newTemp, 10);

{
std::lock_guard<std::mutex>{cmdQueueMutex};
cmdQueue.emplace(std::move(cmd));
}

if (!dispatch_next_cmd())
{
log_web(F("command dispatch failed for Z1 flow target temperature setting!"));
return false;
}

return true;
}

bool set_dhw_target_temperature(float newTemp)
{
if (newTemp > get_max_dhw_temperature())
Expand Down
3 changes: 3 additions & 0 deletions ecodan-ha-local/ehal_hp.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,11 @@ namespace ehal::hp
float get_max_thermostat_temperature();
float get_min_dhw_temperature();
float get_max_dhw_temperature();
float get_min_flow_target_temperature(String mode);
float get_max_flow_target_temperature(String mode);

bool set_z1_target_temperature(float value);
bool set_z1_flow_target_temperature(float value);
bool set_dhw_target_temperature(float value);
bool set_dhw_mode(String mode);
bool set_dhw_force(bool on);
Expand Down
75 changes: 75 additions & 0 deletions ecodan-ha-local/ehal_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,29 @@ off
}
}

void on_z1_flow_target_temperature_set_command(const String& payload)
{
if (payload.isEmpty())
{
return;
}

float setTemperature = payload.toFloat();

if (!hp::set_z1_flow_target_temperature(setTemperature))
{
log_web(F("Failed to set Z1 flow target temperature!"));
}
else
{
auto& status = hp::get_status();
std::lock_guard<hp::Status> lock{status};
status.Zone1FlowTemperatureSetPoint = setTemperature;

publish_sensor_status<float>(F("z1_flow_temp_target"), setTemperature);
}
}

void on_dhw_temperature_set_command(const String& payload)
{
if (payload.isEmpty())
Expand Down Expand Up @@ -275,17 +298,23 @@ off
auto& config = config_instance();
String climateEntity = unique_entity_name(F("climate_control"));
String tempCmdTopic = config.MqttTopic + "/" + climateEntity + F("/temp_cmd");
String z1FlowTargetCmdTopic = config.MqttTopic + "/" + unique_entity_name(F("z1_flow_temp_target")) + F("/set");
String dhwForceCmdTopic = config.MqttTopic + "/" + unique_entity_name(F("force_dhw")) + F("/set");
String turnOnOffCmdTopic = config.MqttTopic + "/" + unique_entity_name(F("turn_on_off_hp")) + F("/set");
String dhwTempCmdTopic = config.MqttTopic + "/" + unique_entity_name(F("dhw_water_heater")) + F("/set");
String dhwModeCmdTopic = config.MqttTopic + "/" + unique_entity_name(F("dhw_mode")) + F("/set");
String shModeCmdTopic = config.MqttTopic + "/" + unique_entity_name(F("sh_mode")) + F("/set");

log_web(F("MQTT topic received: %s: '%s'"), topic.c_str(), payload.c_str());

if (tempCmdTopic == topic)
{
on_z1_temperature_set_command(payload);
}
else if (z1FlowTargetCmdTopic == topic)
{
on_z1_flow_target_temperature_set_command(payload);
}
else if (dhwTempCmdTopic == topic)
{
on_dhw_temperature_set_command(payload);
Expand Down Expand Up @@ -492,6 +521,43 @@ off
return true;
}

bool publish_ha_set_z1_flow_target_auto_discover()
{
// https://www.home-assistant.io/integrations/number.mqtt/
String uniqueName = unique_entity_name(F("z1_flow_temp_target"));

const auto& config = config_instance();
auto& status = hp::get_status();
String discoveryTopic = String(F("homeassistant/number/")) + uniqueName + F("/config");
String stateTopic = config.MqttTopic + "/" + unique_entity_name(F("z1_flow_temp_target")) + F("/state");
String cmdTopic = config.MqttTopic + "/" + uniqueName + F("/set");

DynamicJsonDocument payloadJson(8192);
payloadJson[F("name")] = uniqueName;
payloadJson[F("unique_id")] = uniqueName;

add_discovery_device_object(payloadJson);

payloadJson[F("stat_t")] = stateTopic;
payloadJson[F("stat_t_tpl")] = F("{{ value }}");
payloadJson[F("cmd_t")] = cmdTopic;
payloadJson[F("cmd_tpl")] = F("{{ value }}");
payloadJson[F("min")] = String(ehal::hp::get_min_flow_target_temperature(status.hp_mode_as_string()));
payloadJson[F("max")] = String(ehal::hp::get_max_flow_target_temperature(status.hp_mode_as_string()));
payloadJson[F("step")] = 1;
payloadJson[F("dev_cla")] = F("temperature");
payloadJson[F("unit_of_meas")] = F("°C");
payloadJson[F("icon")] = String("mdi:thermometer-water");

if (!publish_mqtt(discoveryTopic, payloadJson, /* retain =*/true))
{
log_web(F("Failed to publish homeassistant Z1 flow temperature set entity auto-discover"));
return false;
}

return true;
}

bool publish_ha_turn_on_off_auto_discover()
{
// https://www.home-assistant.io/integrations/switch.mqtt/
Expand Down Expand Up @@ -738,6 +804,9 @@ off
if (!publish_ha_climate_auto_discover())
anyFailed = true;

if (!publish_ha_set_z1_flow_target_auto_discover())
anyFailed = true;

if (!publish_ha_force_dhw_auto_discover())
anyFailed = true;

Expand Down Expand Up @@ -973,6 +1042,12 @@ off
return false;
}

if (!mqttClient.subscribe(config.MqttTopic + "/" + unique_entity_name(F("z1_flow_temp_target")) + F("/set")))
{
log_web(F("Failed to subscribe to Z1 flow target temperature command topic!"));
return false;
}

if (!mqttClient.subscribe(config.MqttTopic + "/" + unique_entity_name(F("dhw_mode")) + F("/set")))
{
log_web(F("Failed to subscribe to DHW mode command topic!"));
Expand Down
9 changes: 8 additions & 1 deletion ecodan-ha-local/ehal_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ namespace ehal::hp
ZONE_1,
ZONE_2,
BOTH
};
};

enum class SetHpMode
{
TEMPERATURE_MODE,
FLOW_CONTROL_MODE,
COMPENSATION_CURVE_MODE
};

enum class GetType : uint8_t
{
Expand Down

0 comments on commit 6ab64bb

Please sign in to comment.