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