10#include "esphome/core/log.h"
18static const char *
const TAG =
"home_io_control.fan";
23constexpr int HEAT_STEPS = 100;
33 "Device %s is declared as %s, which a fan entity cannot drive (it drives exterior heating) — disabling it",
45 const bool has_level =
47 return fan::FanTraits(
false, has_level,
false, HEAT_STEPS);
51 const bool has_level = this->
get_traits().supports_speed();
52 const auto state = call.get_state();
53 const auto speed = call.get_speed();
56 if (state.has_value() && !*state) {
58 }
else if (speed.has_value() && has_level) {
59 heat = std::clamp(*speed, 0, HEAT_STEPS);
60 }
else if (state.has_value()) {
62 heat = (has_level && this->speed > 0) ? this->speed : HEAT_STEPS;
68 const auto io_position =
detail::round_percent(1.0F - (
static_cast<float>(heat) /
static_cast<float>(HEAT_STEPS)));
72 this->state = heat > 0;
73 if (heat > 0 && has_level)
75 this->publish_state();
83 const int heat = std::clamp(
static_cast<int>(std::lround(100.0F - dev.
position)), 0, HEAT_STEPS);
84 const bool on = heat > 0;
85 const bool has_level = this->
get_traits().supports_speed();
86 const int speed = (on && has_level) ? heat : this->speed;
87 if (this->state == on && this->speed == speed)
91 this->publish_state();
95 ESP_LOGCONFIG(
TAG,
"IO-Homecontrol Exterior Heating Fan:");
96 ESP_LOGCONFIG(
TAG,
" Device ID: %s", this->
device_id_.c_str());
98 ESP_LOGCONFIG(
TAG,
" Status: experimental, unvalidated on hardware");
void log_poll_interval_config_(const char *tag) const
Emit the shared two-branch poll-interval line for dump_config().
void register_device_binding_(Component *self, DeviceCapabilityClass entity_class, std::optional< bool > invert_override, std::function< void(const std::string &, const IoDevice &)> on_update, bool dimmable=false)
Perform the shared setup() registration ritual.
IOHomeControlComponent * parent_
bool passes_binary_update_filter_(const std::string &id, const IoDevice &dev) const
Shared inbound-update guard for binary endpoints.
DeviceFeatures device_features_(DeviceCapabilityClass entity_class) const
What this entity's device can do: the registered device's features, or, before it is registered,...
virtual void queue_set_fan_position(const std::string &device_id, uint8_t position)
Async form of set_fan_position() that keeps radio work serialized on the main loop.
fan::FanTraits get_traits() override
Traits: a 100-step speed (the heat level) unless the device takes the main parameter only (subtype 58...
void dump_config() override
Dump configuration to the log.
void on_device_update_(const std::string &id, const IoDevice &dev)
Show a settled device status: heat level = 100 - position.
void setup() override
Register the entity with the shared hub and schedule the first status poll.
void control(const fan::FanCall &call) override
Apply a Home Assistant fan request: a heat level, or on/off.
Conversions and renderers shared by the hub and its Home Assistant entities.
uint8_t round_percent(float fraction)
Convert a 0.0-1.0 HA fraction (position, tilt, or brightness) to a 0-100 IO percent.
DeviceCapabilityClass device_capability_class(DeviceType type)
Map a raw IO‑Homecontrol type to the closest ESPHome/Home Assistant entity family.
static constexpr const char * TAG
@ UNKNOWN
Unknown/unspecified device.
constexpr bool has_feature(DeviceFeatures set, DeviceFeatures bit)
True when every bit of bit is set in set.
@ HEATER_LEVEL
Heater with a heat level in the position field (exterior heating).
std::string format_device_kind(DeviceType type, uint8_t subtype)
Human-readable description of a (type, subtype) for logs and reports.
static const char *const TAG
The IO node-type and subtype table: names, entity class, platform and behaviour flags.
Runtime state of a paired IO‑Homecontrol device.
float position
Current position: 0=open, 100=closed, or UNKNOWN_POSITION.