Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
platform_companion_sensors.cpp
Go to the documentation of this file.
1/// @file platform_companion_sensors.cpp
2/// @brief The seven auto-generated per-device diagnostic companion sensors.
3/// @ingroup hioc_platforms
4
6
7#include "hub_internal.h"
8#include "proto_constants.h"
9#include "esphome/core/hal.h"
10#include "esphome/core/log.h"
11
12namespace esphome {
13namespace home_io_control {
14
15// Each dump_config() keeps its own log tag as a `static` function-local constant: the ESPHome
16// LOG_SENSOR / LOG_TEXT_SENSOR macros expand to a bare `TAG` identifier, so one shared file-scope
17// constant could not carry seven different values. Values are unchanged from the former per-sensor
18// files. (`static` so the name resolves as a StaticConstant, i.e. UPPER_CASE, under clang-tidy's
19// identifier-naming check rather than as a lower_case local.)
20
21namespace {
22
23constexpr float MS_PER_SECOND = 1000.0F;
24// How often the Last Contact heartbeat re-publishes the age while the device stays quiet.
25// Frame-driven updates alone would freeze the entity's value at whatever it was the moment
26// traffic stopped; without this it can't count up in Home Assistant between frames.
27constexpr uint32_t HEARTBEAT_INTERVAL_MS = 60000;
28
29} // namespace
30
32 this->register_companion_binding_([this](const IoDevice &dev) {
33 if (const int16_t ema_dbm = device_rssi_ema_dbm(dev); ema_dbm != RSSI_UNKNOWN_DBM)
34 this->publish_state(ema_dbm);
35 });
36}
37
39 static const char *const TAG = "home_io_control.rssi";
40 LOG_SENSOR("", "IO-Homecontrol RSSI", this);
41 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
42}
43
45 this->register_companion_binding_([this](const IoDevice &dev) { this->publish_age_(dev); });
46
47 this->set_interval("heartbeat", HEARTBEAT_INTERVAL_MS, [this]() {
48 if (this->parent_ == nullptr)
49 return;
50 if (const auto *dev = this->parent_->get_device(this->device_id_); dev != nullptr)
51 this->publish_age_(*dev);
52 });
53}
54
56 if (dev.last_seen_ms != 0)
57 this->publish_state(static_cast<float>(millis() - dev.last_seen_ms) / MS_PER_SECOND);
58}
59
61 static const char *const TAG = "home_io_control.last_contact";
62 LOG_SENSOR("", "IO-Homecontrol Last Contact", this);
63 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
64}
65
68 [this](const IoDevice &dev) { this->publish_state(static_cast<float>(dev.exchange_timeout_count)); });
69}
70
72 static const char *const TAG = "home_io_control.exchange_failures";
73 LOG_SENSOR("", "IO-Homecontrol Exchange Failures", this);
74 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
75}
76
78 if (this->parent_ == nullptr)
79 return;
80
81 this->register_companion_binding_([this](const IoDevice &dev) { this->publish_state(dev.name); });
82
83 this->set_timeout("init_name", INITIAL_STATUS_REQUEST_DELAY_MS,
84 [this]() { this->parent_->queue_request_device_name(this->device_id_); });
85}
86
88 static const char *const TAG = "home_io_control.device_name";
89 LOG_TEXT_SENSOR("", "IO-Homecontrol Device Name", this);
90 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
91}
92
94 this->register_companion_binding_([this](const IoDevice &dev) {
95 // Empty string when no result is recorded; otherwise the symbolic result name.
96 this->publish_state(dev.last_result_code == 0 ? "" : command_result_name(dev.last_result_code));
97 });
98}
99
101 static const char *const TAG = "home_io_control.active_issue";
102 LOG_TEXT_SENSOR("", "IO-Homecontrol Active Issue", this);
103 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
104}
105
107 // No parent_ == nullptr guard needed here (unlike IOHomeDeviceNameTextSensor, which dereferences
108 // parent_ a second time outside the binding, in a set_timeout lambda): register_companion_binding_()
109 // already no-ops on a null parent before this lambda is ever invoked, so parent_ is guaranteed
110 // non-null every time it runs.
112 [this](const IoDevice &dev) { this->publish_state(this->parent_->describe_last_commander(dev)); });
113}
114
116 static const char *const TAG = "home_io_control.last_commanded_by";
117 LOG_TEXT_SENSOR("", "IO-Homecontrol Last Commanded By", this);
118 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
119}
120
123 [this](const IoDevice &dev) { this->publish_state(detail::describe_last_command_source(dev)); });
124}
125
127 static const char *const TAG = "home_io_control.last_command_source";
128 LOG_TEXT_SENSOR("", "IO-Homecontrol Last Command Source", this);
129 ESP_LOGCONFIG(TAG, " Device ID: %s", this->device_id_.c_str());
130}
131
132} // namespace home_io_control
133} // 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.
void setup() override
Register the device-update subscription and publish the initial cached state.
void dump_config() override
Dump text-sensor configuration to the log.
void setup() override
Register the device-update subscription and schedule an initial name fetch.
void dump_config() override
Dump text-sensor configuration to the log.
void setup() override
Register the device-update subscription and publish the initial cached state.
void dump_config() override
Dump sensor configuration to the log.
void dump_config() override
Dump sensor configuration to the log.
void publish_age_(const IoDevice &dev)
Compute and publish seconds since dev.last_seen_ms; no-op before the first frame.
void setup() override
Register the device-update subscription, start the heartbeat, and publish the initial cached state.
void setup() override
Register the device-update subscription and publish the initial cached state.
void dump_config() override
Dump sensor configuration to the log.
Internal helpers shared by the hub implementation .cpp files.
std::string describe_last_command_source(const IoDevice &dev)
Render the "Last Command Source" sensor string.
static constexpr const char * TAG
const char * command_result_name(uint8_t result)
Return a stable symbolic name for a CMD_ERROR_RESP result code.
static constexpr uint32_t INITIAL_STATUS_REQUEST_DELAY_MS
Delay before the first post-boot status request from an entity.
int16_t device_rssi_ema_dbm(const IoDevice &dev)
A device's smoothed RSSI in whole dBm.
static constexpr int16_t RSSI_UNKNOWN_DBM
Sentinel value meaning "no RSSI sample recorded yet" for last_rssi_dbm/rssi_ema_scaled.
The seven auto-generated per-device diagnostic companion sensors.
IO-Homecontrol command IDs, result codes and protocol enumerations.
Runtime state of a paired IO‑Homecontrol device.
uint8_t last_result_code
Last CMD_ERROR_RESP result byte (0 = none recorded).
char name[DEVICE_NAME_BUFFER_SIZE]
Cached UTF-8 device name decoded from Latin-1 wire payloads.
uint32_t last_seen_ms
millis() of the last frame received from this device (any command), 0 = never.
uint16_t exchange_timeout_count
Cumulative count of outbound exchanges to this device with no valid response (see detail::record_exch...