11#if DETWS_ENABLE_MQTT_SN
15uint8_t mqttsn_make_flags(
bool dup, uint8_t qos,
bool retain,
bool will,
bool clean, uint8_t topic_id_type)
20 f |= (uint8_t)((qos & 0x03) << MQTTSN_FLAG_QOS_SHIFT) & MQTTSN_FLAG_QOS_MASK;
22 f |= MQTTSN_FLAG_RETAIN;
24 f |= MQTTSN_FLAG_WILL;
26 f |= MQTTSN_FLAG_CLEAN;
27 f |= (uint8_t)(topic_id_type & MQTTSN_FLAG_TOPICIDTYPE_MASK);
36static size_t frame_header(uint8_t *buf,
size_t cap, uint8_t msg_type,
size_t body_len,
size_t *total)
38 size_t core = 1 + body_len;
51 if (t > 0xFFFF || t > cap)
55 buf[pos++] = (uint8_t)t;
58 buf[pos++] = MQTTSN_LEN3_PREFIX;
59 buf[pos++] = (uint8_t)(t >> 8);
60 buf[pos++] = (uint8_t)(t & 0xFF);
62 buf[pos++] = msg_type;
67static void wr16(uint8_t *p, uint16_t v)
69 p[0] = (uint8_t)(v >> 8);
70 p[1] = (uint8_t)(v & 0xFF);
73static uint16_t rd16(
const uint8_t *p)
75 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
78size_t mqttsn_build_connect(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t duration,
const char *client_id)
80 if (!buf || !client_id)
82 size_t idlen = strnlen(client_id, cap);
83 size_t total, p = frame_header(buf, cap, MQTTSN_CONNECT, 1 + 1 + 2 + idlen, &total);
87 buf[p++] = MQTTSN_PROTOCOL_ID;
88 wr16(buf + p, duration);
90 memcpy(buf + p, client_id, idlen);
94size_t mqttsn_build_register(uint8_t *buf,
size_t cap, uint16_t topic_id, uint16_t msg_id,
const char *topic_name)
96 if (!buf || !topic_name)
98 size_t nlen = strnlen(topic_name, cap);
99 size_t total, p = frame_header(buf, cap, MQTTSN_REGISTER, 2 + 2 + nlen, &total);
102 wr16(buf + p, topic_id);
104 wr16(buf + p, msg_id);
106 memcpy(buf + p, topic_name, nlen);
110size_t mqttsn_build_regack(uint8_t *buf,
size_t cap, uint16_t topic_id, uint16_t msg_id, uint8_t ret_code)
114 size_t total, p = frame_header(buf, cap, MQTTSN_REGACK, 2 + 2 + 1, &total);
117 wr16(buf + p, topic_id);
119 wr16(buf + p, msg_id);
125size_t mqttsn_build_publish(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t topic_id, uint16_t msg_id,
126 const uint8_t *data,
size_t data_len)
128 if (!buf || (data_len && !data))
130 size_t total, p = frame_header(buf, cap, MQTTSN_PUBLISH, 1 + 2 + 2 + data_len, &total);
134 wr16(buf + p, topic_id);
136 wr16(buf + p, msg_id);
139 memcpy(buf + p, data, data_len);
143size_t mqttsn_build_puback(uint8_t *buf,
size_t cap, uint16_t topic_id, uint16_t msg_id, uint8_t ret_code)
147 size_t total, p = frame_header(buf, cap, MQTTSN_PUBACK, 2 + 2 + 1, &total);
150 wr16(buf + p, topic_id);
152 wr16(buf + p, msg_id);
158size_t mqttsn_build_subscribe_name(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t msg_id,
const char *topic_name)
160 if (!buf || !topic_name)
162 size_t nlen = strnlen(topic_name, cap);
163 size_t total, p = frame_header(buf, cap, MQTTSN_SUBSCRIBE, 1 + 2 + nlen, &total);
167 wr16(buf + p, msg_id);
169 memcpy(buf + p, topic_name, nlen);
173size_t mqttsn_build_subscribe_id(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t msg_id, uint16_t topic_id)
177 size_t total, p = frame_header(buf, cap, MQTTSN_SUBSCRIBE, 1 + 2 + 2, &total);
181 wr16(buf + p, msg_id);
183 wr16(buf + p, topic_id);
187size_t mqttsn_build_pingreq(uint8_t *buf,
size_t cap,
const char *client_id)
191 size_t idlen = client_id ? strnlen(client_id, cap) : 0;
192 size_t total, p = frame_header(buf, cap, MQTTSN_PINGREQ, idlen, &total);
196 memcpy(buf + p, client_id, idlen);
200size_t mqttsn_build_disconnect(uint8_t *buf,
size_t cap,
bool with_duration, uint16_t duration)
204 size_t total, p = frame_header(buf, cap, MQTTSN_DISCONNECT, with_duration ? 2 : 0, &total);
208 wr16(buf + p, duration);
212size_t mqttsn_build_searchgw(uint8_t *buf,
size_t cap, uint8_t radius)
216 size_t total, p = frame_header(buf, cap, MQTTSN_SEARCHGW, 1, &total);
223bool mqttsn_parse_header(
const uint8_t *buf,
size_t len, MqttsnHeader *out,
size_t *consumed)
225 if (!buf || !out || !consumed || len < 2)
229 if (buf[0] == MQTTSN_LEN3_PREFIX)
233 total = ((size_t)buf[1] << 8) | buf[2];
241 if (total < lenfield + 1)
245 out->msg_type = buf[lenfield];
246 out->payload = buf + lenfield + 1;
247 out->payload_len = total - lenfield - 1;
252bool mqttsn_parse_connack(
const uint8_t *payload,
size_t len, uint8_t *ret_code)
254 if (!payload || len < 1)
257 *ret_code = payload[0];
261bool mqttsn_parse_regack(
const uint8_t *payload,
size_t len, uint16_t *topic_id, uint16_t *msg_id, uint8_t *ret_code)
263 if (!payload || len < 5)
266 *topic_id = rd16(payload);
268 *msg_id = rd16(payload + 2);
270 *ret_code = payload[4];
274bool mqttsn_parse_puback(
const uint8_t *payload,
size_t len, uint16_t *topic_id, uint16_t *msg_id, uint8_t *ret_code)
276 return mqttsn_parse_regack(payload, len, topic_id, msg_id, ret_code);
279bool mqttsn_parse_suback(
const uint8_t *payload,
size_t len, uint8_t *flags, uint16_t *topic_id, uint16_t *msg_id,
282 if (!payload || len < 6)
287 *topic_id = rd16(payload + 1);
289 *msg_id = rd16(payload + 3);
291 *ret_code = payload[5];
295bool mqttsn_parse_publish(
const uint8_t *payload,
size_t len, uint8_t *flags, uint16_t *topic_id, uint16_t *msg_id,
296 const uint8_t **data,
size_t *data_len)
298 if (!payload || len < 5)
303 *topic_id = rd16(payload + 1);
305 *msg_id = rd16(payload + 3);
313bool mqttsn_parse_register(
const uint8_t *payload,
size_t len, uint16_t *topic_id, uint16_t *msg_id,
314 const char **topic_name,
size_t *topic_name_len)
316 if (!payload || len < 4)
319 *topic_id = rd16(payload);
321 *msg_id = rd16(payload + 2);
323 *topic_name = (
const char *)(payload + 4);
325 *topic_name_len = len - 4;
MQTT-SN v1.2 wire codec (DETWS_ENABLE_MQTT_SN) - zero-heap message builder + parser for MQTT for Sens...