49inline uint8_t
round_percent(
float fraction) {
return static_cast<uint8_t
>(std::lround(fraction * 100.0F)); }
83 out +=
" (this device)";
111 if (parameter_id == LIMITATION_PARAM_MP) {
114 std::array<char, LIMITATION_TEXT_BUFFER_SIZE> buffer{};
115 if (parameter_id >= LIMITATION_PARAM_FP_FIRST && parameter_id <= LIMITATION_PARAM_FP_LAST) {
116 std::snprintf(buffer.data(), buffer.size(),
"FP%u", parameter_id);
118 std::snprintf(buffer.data(), buffer.size(),
"0x%02X", parameter_id);
120 return std::string(buffer.data());
131 std::array<char, LIMITATION_TEXT_BUFFER_SIZE> buffer{};
132 const unsigned hi = value_raw >> BITS_PER_BYTE;
133 const unsigned lo = value_raw & 0xFFU;
134 if (value_raw > STATUS_POS_MAX) {
135 std::snprintf(buffer.data(), buffer.size(),
"selector (%02X %02X)", hi, lo);
136 return std::string(buffer.data());
138 const double percent = value_raw * 100.0 / STATUS_POS_MAX;
139 const bool whole = (value_raw * 100U) % STATUS_POS_MAX == 0;
140 std::snprintf(buffer.data(), buffer.size(), whole ?
"%.0f%% (%02X %02X)" :
"%.1f%% (%02X %02X)", percent, hi, lo);
141 return std::string(buffer.data());
146 std::array<char, LIMITATION_TEXT_BUFFER_SIZE> buffer{};
147 if (time_raw == LIMITATION_TIME_UNLIMITED) {
148 std::snprintf(buffer.data(), buffer.size(),
"0x%02X (unlimited)", time_raw);
149 }
else if (time_raw > LIMITATION_TIME_MAX_COUNTED) {
150 std::snprintf(buffer.data(), buffer.size(),
"0x%02X (code %u)", time_raw, time_raw);
152 std::snprintf(buffer.data(), buffer.size(),
"0x%02X (%" PRIu32
" s)", time_raw,
limitation_time_seconds(time_raw));
154 return std::string(buffer.data());
173 return "limitation (assumed layout): unexpected length " + std::to_string(frame.
data_len);
183 uint8_t parameter_id = 0;
185 return "limitation request (assumed layout): unexpected payload";
186 return std::string(
"limitation request (assumed layout): type=") +
Hub-layer log tag and log/format helpers shared by the hub and its collaborators.
constexpr size_t LIMITATION_TEXT_BUFFER_SIZE
Buffer size for the limitation fragments below: the longest is "selector (D8 01)" or "0xFD (unlimited...
std::string describe_limitation_reply(const IoFrame &frame)
Render a CMD_LIMITATION_STATUS_RESP frame for a log line or probe report.
std::string format_name_and_hex(const char *name, uint8_t value)
Format a name/value pair as "name(0xXX)", e.g. "execute(0x00)".
std::string format_limitation_param(uint8_t parameter_id)
Render a limitation parameter id: "MP" for the main parameter, "FP<n>" for 1-16, else hex.
constexpr float BINARY_ENTITY_ON_POSITION_THRESHOLD
Shared 0-100 cutoff: values below this mean binary "on".
std::string describe_last_command_source(const IoDevice &dev)
Render the "Last Command Source" sensor string.
std::string format_limitation_value(uint16_t value_raw)
Render a limitation value: a percentage, or the raw selector when it is not a position.
std::string describe_limitation_request(const IoFrame &frame)
Render a CMD_LIMITATION_STATUS_REQ frame for a log line.
uint8_t round_percent(float fraction)
Convert a 0.0-1.0 HA fraction (position, tilt, or brightness) to a 0-100 IO percent.
std::string format_limitation_status(const LimitationStatus &status)
Render a decoded limitation reply on one line, raw bytes beside every decoded value.
std::string format_limitation_time(uint8_t time_raw)
Render a limitation time code with its raw byte: "0x1D (900 s)", "0xFD (unlimited)",...
std::string describe_last_commander(const IoDevice &dev, const uint8_t *hub_node_id)
Render the "Last Commanded By" sensor string.
std::string format_originator(uint8_t originator)
Render a Command Originator byte as "name(0xXX)", e.g.
bool decode_limitation_status(const IoFrame &f, LimitationStatus &out)
Decode a limitation reply (assumed layout, see LimitationStatus).
uint32_t limitation_time_seconds(uint8_t time_raw)
Remaining time of a limitation in seconds.
bool decode_limitation_request(const IoFrame &f, LimitationType &type, uint8_t ¶meter_id)
Decode a limitation request (assumed layout [selector] [parameter id] [00]).
std::string node_id_to_string(const uint8_t id[NODE_ID_SIZE])
Format a 3‑byte node ID as a 6‑character uppercase hex string.
LimitationType
On-air selector byte (request data[0]) choosing which resulting limit to read.
@ MINIMUM
Resulting minimum limit; rain protection raises it (a floor on the position value).
const char * originator_name(uint8_t originator)
Get a human-readable name for a command originator byte.
Device-name, address-classification and 1W-frame codecs.
IO-Homecontrol command IDs, result codes and protocol enumerations.
IO-Homecontrol device-type model, capabilities and runtime device state.
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
Fundamental IO-Homecontrol frame and crypto size constants.
Runtime state of a paired IO‑Homecontrol device.
uint8_t last_commander[NODE_ID_SIZE]
Node ID of the controller that last commanded this device, as reported verbatim by the device in its ...
uint8_t last_command_originator
That command's Command Originator byte (ORIGINATOR_* in proto_constants.h).
uint8_t node_id[NODE_ID_SIZE]
Device's 3‑byte radio address.
bool has_last_command
True once a status reply carried a well-formed last-command record.
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
uint8_t data_len
Actual length of data.
One decoded CMD_LIMITATION_STATUS_RESP payload.
uint8_t parameter_id
data[0]; LIMITATION_PARAM_MP for the main parameter.
uint8_t originator
data[3], Command Originator that imposed the limit (ORIGINATOR_*).
uint16_t value_raw
data[1..2], big-endian, position coding (STATUS_POS_MAX = 100 %).
uint8_t time_raw
data[4], remaining-time code; see limitation_time_seconds().