Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
platform_climate_controls.cpp
Go to the documentation of this file.
1/// @file platform_climate_controls.cpp
2/// @brief Generated per-heater auxiliary entities: the window binary sensor, the open-window
3/// detection switch and the night light.
4/// @ingroup hioc_platforms
5
7
8#include "entity_helpers.h"
9#include "esphome/core/log.h"
10
11#include <algorithm>
12#include <utility>
13
14namespace esphome {
15namespace home_io_control {
16
17static const char *const TAG_WINDOW = "home_io_control.window";
18static const char *const TAG_DETECTION = "home_io_control.window_detection";
19static const char *const TAG_NIGHT_LIGHT = "home_io_control.night_light";
20
21/// Brightness register value for a light switched on at a brightness that rounds to 0 %: the lowest
22/// level that is still on.
23static constexpr uint8_t NIGHT_LIGHT_MIN_ON_PERCENT = 1;
24
26 this->register_companion_binding_([this](const IoDevice &dev) {
27 if (dev.heating.window_open < 0) {
28 // "Closed" must mean the heater said so: nothing read means no state.
29 this->invalidate_state();
30 return;
31 }
32 this->publish_state(dev.heating.window_open != 0);
33 });
34}
35
37 ESP_LOGCONFIG(TAG_WINDOW, "IO-Homecontrol Window:");
38 ESP_LOGCONFIG(TAG_WINDOW, " Device ID: %s", this->device_id_.c_str());
39}
40
42 this->register_companion_binding_([this](const IoDevice &dev) {
43 // Shown only from a reply; a switch with no reading yet keeps its unknown state.
44 if (dev.heating.open_window_detection >= 0)
45 this->publish_state(dev.heating.open_window_detection != 0);
46 });
47}
48
50 if (this->parent_ == nullptr)
51 return;
53 state ? 1.0F : 0.0F)) {
54 ESP_LOGW(TAG_DETECTION, "Device %s: open-window detection %s was not acknowledged", this->device_id_.c_str(),
55 state ? "on" : "off");
56 return;
57 }
58 // The read-back updates IoDevice::heating, and the companion binding above publishes it.
60 EXCHANGE_RETRY_COUNT);
61}
62
64 ESP_LOGCONFIG(TAG_DETECTION, "IO-Homecontrol Open Window Detection:");
65 ESP_LOGCONFIG(TAG_DETECTION, " Device ID: %s", this->device_id_.c_str());
66}
67
69 this->register_companion_binding_([this](const IoDevice &dev) { this->on_device_update_(dev); });
70}
71
73 auto traits = light::LightTraits();
74 traits.set_supported_color_modes({light::ColorMode::BRIGHTNESS});
75 return traits;
76}
77
79 // Shown only from a reply: a light with no reading yet keeps its unknown state.
80 if (this->state_ == nullptr || this->writing_ || dev.heating.night_light < 0)
81 return;
82 const bool on = dev.heating.night_light != 0;
83 // A brightness of 0 (or none read yet) says nothing about the level the light comes on at: keep the
84 // one shown.
85 const float brightness =
88 : this->state_->remote_values.get_brightness();
89 publish_light_reading(this->state_, on, brightness, this->suppress_write_);
90}
91
93 if (this->parent_->send_heating_command(this->device_id_, fn, value))
94 return true;
95 ESP_LOGW(TAG_NIGHT_LIGHT, "Device %s: %s %.0f was not acknowledged", this->device_id_.c_str(),
96 heating_function_name(fn), value);
97 return false;
98}
99
100void IOHomeHeaterNightLight::write_state(light::LightState *state) {
101 if (this->suppress_write_) {
102 this->suppress_write_ = false;
103 return;
104 }
105 if (this->parent_ == nullptr)
106 return;
107
108 this->writing_ = true;
109 const bool on = state->current_values.is_on();
110 bool brightness_written = false;
111 if (on) {
112 // The raw brightness, not current_values_as_brightness(): that one applies gamma_correct, meant for a
113 // PWM output, and would send a different percentage than the one the user picked.
114 const uint8_t percent = std::clamp<uint8_t>(detail::round_percent(state->current_values.get_brightness()),
116 const IoDevice *dev = this->parent_->get_device(this->device_id_);
117 if (dev == nullptr || std::cmp_not_equal(dev->heating.night_light_brightness, percent))
118 brightness_written = this->write_register_(HeatingFunction::NIGHT_LIGHT_BRIGHTNESS, percent);
119 }
120 // On/off goes out even when the brightness write failed: switching the light is what the user asked.
121 const bool switched = this->write_register_(HeatingFunction::NIGHT_LIGHT, on ? 1.0F : 0.0F);
122
123 // The read-backs update IoDevice::heating; what the heater then holds is published once, below. A write
124 // the heater did not acknowledge is not read back: the light then shows the heater's last reading again.
125 if (switched)
126 this->parent_->read_heating_register(this->device_id_, HeatingFunction::NIGHT_LIGHT, nullptr, EXCHANGE_RETRY_COUNT);
127 if (brightness_written) {
129 EXCHANGE_RETRY_COUNT);
130 }
131 this->writing_ = false;
132 if (const IoDevice *dev = this->parent_->get_device(this->device_id_); dev != nullptr)
133 this->on_device_update_(*dev);
134}
135
137 ESP_LOGCONFIG(TAG_NIGHT_LIGHT, "IO-Homecontrol Heater Night Light:");
138 ESP_LOGCONFIG(TAG_NIGHT_LIGHT, " Device ID: %s", this->device_id_.c_str());
139}
140
141} // namespace home_io_control
142} // namespace esphome
void register_companion_binding_(const std::function< void(const IoDevice &)> &publish)
Shared setup() body: subscribe to this device's updates and publish the initial state.
virtual bool send_heating_command(const std::string &device_id, HeatingFunction fn, float value)
Run one heating function on the heater's private register protocol (CMD_WRITE_PRIVATE 0x20): a write ...
virtual IoDevice * get_device(const std::string &device_id)
Retrieve a device by ID; returns nullptr if not found.
Definition hub_core.cpp:402
virtual bool read_heating_register(const std::string &device_id, HeatingFunction fn, float *value_out, uint8_t max_tries)
Read one register of a heater and fold the decoded value into IoDevice::heating.
void on_device_update_(const IoDevice &dev)
Publish the heater's light state, without echoing it back as a write.
light::LightTraits get_traits() override
Brightness is the light's only colour mode.
void write_state(light::LightState *state) override
Send the requested state to the heater and read it back.
void dump_config() override
Dump light configuration to the log.
bool writing_
True while write_state() runs its writes and read-backs: the device updates they cause are not publis...
void setup() override
Subscribe to the device's updates and publish what is already known.
bool write_register_(HeatingFunction fn, float value)
Write one light register.
bool suppress_write_
Swallows the write_state() that LightState::make_call().perform() causes for a state this entity publ...
void dump_config() override
Dump switch configuration to the log.
void write_state(bool state) override
Write the detection setting and read it back.
void setup() override
Subscribe to the device's updates and publish what is already known.
void dump_config() override
Dump sensor configuration to the log.
void setup() override
Subscribe to the device's updates and publish what is already known.
Conversions and renderers shared by the hub and its Home Assistant entities.
void publish_light_reading(light::LightState *state, bool on, std::optional< float > brightness, bool &suppress_write)
Show a device's light state on its LightState without sending it back to the device.
uint8_t round_percent(float fraction)
Convert a 0.0-1.0 HA fraction (position, tilt, or brightness) to a 0-100 IO percent.
HeatingFunction
Registers and functions of a 2W heater, one row of the descriptor table each.
@ NIGHT_LIGHT
Register 0x0144, read/write: a heater's night light on (1) or off (0).
@ NIGHT_LIGHT_BRIGHTNESS
Register 0x0142, read/write: the night light's brightness, 0-100 %, 16-bit.
@ SET_OPEN_WINDOW_DETECTION
Register 0x0106, read/write: open-window detection on (1) or off (0).
static const char *const TAG_NIGHT_LIGHT
const char * heating_function_name(HeatingFunction fn)
Stable lowercase name for a heating function ("power_on", "set_temperature", ...).
constexpr uint8_t HEATING_NIGHT_LIGHT_BRIGHTNESS_MAX
Highest night light brightness (HeatingFunction::NIGHT_LIGHT_BRIGHTNESS): a percentage,...
static constexpr uint8_t NIGHT_LIGHT_MIN_ON_PERCENT
Brightness register value for a light switched on at a brightness that rounds to 0 %: the lowest leve...
static const char *const TAG_WINDOW
static const char *const TAG_DETECTION
Generated per-heater auxiliary entities: the window binary sensor, the open-window detection switch a...
int16_t window_open
0 closed / 1 open; -1 until read.
int16_t open_window_detection
1 detection on / 0 off; -1 until read.
int16_t night_light
Night light 1 on / 0 off; -1 until read.
int16_t night_light_brightness
Night light brightness, 0-100 %; -1 until read.
Runtime state of a paired IO‑Homecontrol device.
HeatingReadings heating
What the hub has read from a heater over the private register protocol (room temperature,...