ESPHome 2026.5.1
Loading...
Searching...
No Matches
tormatic_protocol.h
Go to the documentation of this file.
1#pragma once
3#include <cinttypes>
49namespace esphome::tormatic {
50
51using namespace esphome::cover;
52
53// MessageType is the type of message that follows the MessageHeader.
54enum MessageType : uint16_t {
55 STATUS = 0x0104,
56 COMMAND = 0x0106,
57};
58
59// Max string length: 7 ("Unknown"/"Command"). Update print() buffer sizes if adding longer strings.
60inline const char *message_type_to_str(MessageType t) {
61 switch (t) {
62 case STATUS:
63 return "Status";
64 case COMMAND:
65 return "Command";
66 default:
67 return "Unknown";
68 }
69}
70
71// MessageHeader appears at the start of every message, both requests and replies.
73 uint16_t seq;
76
77 MessageHeader() = default;
79 this->type = type;
80 this->seq = seq;
81 // len includes the length of the type field. It was
82 // included in MessageHeader to avoid having to parse
83 // it as part of the payload.
84 this->len = payload_size + sizeof(this->type);
85 }
86
87 std::string print() {
88 // 64 bytes: "MessageHeader: seq " + uint16 + ", len " + uint32 + ", type " + type + safety margin
89 char buf[64];
90 buf_append_printf(buf, sizeof(buf), 0, "MessageHeader: seq %d, len %" PRIu32 ", type %s", this->seq, this->len,
91 message_type_to_str(this->type));
92 return buf;
93 }
94
95 void byteswap() {
96 this->len = convert_big_endian(this->len);
97 this->seq = convert_big_endian(this->seq);
98 this->type = convert_big_endian(this->type);
99 }
100
101 // payload_size returns the amount of payload bytes to be read from the uart
102 // buffer after reading the header.
103 uint32_t payload_size() { return this->len > sizeof(this->type) ? this->len - sizeof(this->type) : 0; }
104} __attribute__((packed));
105
106// StatusType denotes which 'page' of information needs to be retrieved.
107// On my Novoferm 423, only the GATE status type returns values, Unknown
108// only contains zeroes.
109enum StatusType : uint16_t {
110 GATE = 0x0A,
111 UNKNOWN = 0x0B,
113
114// GateStatus defines the current state of the gate, received in a StatusReply
115// and sent in a Command.
124
126 switch (s) {
127 case OPENING:
129 case CLOSING:
131 case OPENED:
132 case CLOSED:
133 case PAUSED:
134 case VENTILATING:
136 }
138}
139
140// Max string length: 11 ("Ventilating"). Update print() buffer sizes if adding longer strings.
141inline const char *gate_status_to_str(GateStatus s) {
142 switch (s) {
143 case PAUSED:
144 return "Paused";
145 case CLOSED:
146 return "Closed";
147 case VENTILATING:
148 return "Ventilating";
149 case OPENED:
150 return "Opened";
151 case OPENING:
152 return "Opening";
153 case CLOSING:
154 return "Closing";
155 default:
156 return "Unknown";
157 }
158}
159
160// A StatusRequest is sent to request the gate's current status.
163 uint16_t trailer = 0x1;
164
165 StatusRequest() = default;
167
168 void byteswap() {
169 this->type = convert_big_endian(this->type);
170 this->trailer = convert_big_endian(this->trailer);
171 }
172} __attribute__((packed));
173
174// StatusReply is received from the unit in response to a StatusRequest.
176 uint8_t ack = 0x2;
178 uint8_t trailer = 0x0;
179
180 std::string print() {
181 // 48 bytes: "StatusReply: state " (19) + state (11) + safety margin
182 char buf[48];
183 buf_append_printf(buf, sizeof(buf), 0, "StatusReply: state %s", gate_status_to_str(this->state));
184 return buf;
185 }
186
187 void byteswap(){};
188} __attribute__((packed));
189
190// Serialize the given object to a new byte vector.
191// Invokes the object's byteswap() method.
192template<typename T> std::vector<uint8_t> serialize(T obj) {
193 obj.byteswap();
194
195 std::vector<uint8_t> out(sizeof(T));
196 memcpy(out.data(), &obj, sizeof(T));
197
198 return out;
199}
200
201// Command tells the gate to start or stop moving.
202// It is echoed back by the unit on success.
204 // The part of the unit to control. For now only the gate is supported.
206 uint8_t pad = 0x0;
207 // The desired state:
208 // PAUSED = stop
209 // VENTILATING = move to ~20% open
210 // CLOSED = close
211 // OPENED = open/high-torque reverse when closing
213
216
217 std::string print() {
218 // 56 bytes: "CommandRequestReply: state " (27) + state (11) + safety margin
219 char buf[56];
220 buf_append_printf(buf, sizeof(buf), 0, "CommandRequestReply: state %s", gate_status_to_str(this->state));
221 return buf;
222 }
223
224 void byteswap() { this->type = convert_big_endian(this->type); }
225} __attribute__((packed));
226
227} // namespace esphome::tormatic
enum esphome::cover::CoverOperation __attribute__
CoverOperation
Enum encoding the current operation of a cover.
Definition cover.h:79
@ COVER_OPERATION_OPENING
The cover is currently opening.
Definition cover.h:83
@ COVER_OPERATION_CLOSING
The cover is currently closing.
Definition cover.h:85
@ COVER_OPERATION_IDLE
The cover is currently idle (not moving)
Definition cover.h:81
This file implements the UART protocol spoken over the on-board Micro-USB (Type B) connector of Torma...
CoverOperation gate_status_to_cover_operation(GateStatus s)
std::vector< uint8_t > serialize(T obj)
const char * message_type_to_str(MessageType t)
const char * gate_status_to_str(GateStatus s)
constexpr T convert_big_endian(T val)
Convert a value between host byte order and big endian (most significant byte first) order.
Definition helpers.h:915
static void uint32_t
MessageHeader(MessageType type, uint16_t seq, uint32_t payload_size)