15uint8_t pc_mqttsn_make_flags(
bool dup, uint8_t qos,
bool retain,
bool will,
bool clean, uint8_t topic_id_type)
22 f |= (uint8_t)((qos & 0x03) << MQTTSN_FLAG_QOS_SHIFT) & MQTTSN_FLAG_QOS_MASK;
25 f |= MQTTSN_FLAG_RETAIN;
29 f |= MQTTSN_FLAG_WILL;
33 f |= MQTTSN_FLAG_CLEAN;
35 f |= (uint8_t)(topic_id_type & MQTTSN_FLAG_TOPICIDTYPE_MASK);
44static size_t frame_header(uint8_t *buf,
size_t cap, uint8_t msg_type,
size_t body_len,
size_t *total)
46 size_t core = 1 + body_len;
59 if (t > 0xFFFF || t > cap)
66 buf[pos++] = (uint8_t)t;
70 buf[pos++] = MQTTSN_LEN3_PREFIX;
71 buf[pos++] = (uint8_t)(t >> 8);
72 buf[pos++] = (uint8_t)(t & 0xFF);
74 buf[pos++] = msg_type;
79static void wr16(uint8_t *p, uint16_t v)
81 p[0] = (uint8_t)(v >> 8);
82 p[1] = (uint8_t)(v & 0xFF);
85static uint16_t rd16(
const uint8_t *p)
87 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
90size_t pc_mqttsn_build_connect(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t duration,
const char *client_id)
92 if (!buf || !client_id)
96 size_t idlen = strnlen(client_id, cap);
97 size_t total, p = frame_header(buf, cap, MQTTSN_CONNECT, 1 + 1 + 2 + idlen, &total);
103 buf[p++] = MQTTSN_PROTOCOL_ID;
104 wr16(buf + p, duration);
106 memcpy(buf + p, client_id, idlen);
110size_t pc_mqttsn_build_register(uint8_t *buf,
size_t cap, uint16_t topic_id, uint16_t msg_id,
const char *topic_name)
112 if (!buf || !topic_name)
116 size_t nlen = strnlen(topic_name, cap);
117 size_t total, p = frame_header(buf, cap, MQTTSN_REGISTER, 2 + 2 + nlen, &total);
122 wr16(buf + p, topic_id);
124 wr16(buf + p, msg_id);
126 memcpy(buf + p, topic_name, nlen);
130size_t pc_mqttsn_build_regack(uint8_t *buf,
size_t cap, uint16_t topic_id, uint16_t msg_id, uint8_t ret_code)
136 size_t total, p = frame_header(buf, cap, MQTTSN_REGACK, 2 + 2 + 1, &total);
141 wr16(buf + p, topic_id);
143 wr16(buf + p, msg_id);
149size_t pc_mqttsn_build_publish(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t topic_id, uint16_t msg_id,
150 const uint8_t *data,
size_t data_len)
152 if (!buf || (data_len && !data))
156 size_t total, p = frame_header(buf, cap, MQTTSN_PUBLISH, 1 + 2 + 2 + data_len, &total);
162 wr16(buf + p, topic_id);
164 wr16(buf + p, msg_id);
168 memcpy(buf + p, data, data_len);
173size_t pc_mqttsn_build_puback(uint8_t *buf,
size_t cap, uint16_t topic_id, uint16_t msg_id, uint8_t ret_code)
179 size_t total, p = frame_header(buf, cap, MQTTSN_PUBACK, 2 + 2 + 1, &total);
184 wr16(buf + p, topic_id);
186 wr16(buf + p, msg_id);
192size_t pc_mqttsn_build_subscribe_name(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t msg_id,
const char *topic_name)
194 if (!buf || !topic_name)
198 size_t nlen = strnlen(topic_name, cap);
199 size_t total, p = frame_header(buf, cap, MQTTSN_SUBSCRIBE, 1 + 2 + nlen, &total);
205 wr16(buf + p, msg_id);
207 memcpy(buf + p, topic_name, nlen);
211size_t pc_mqttsn_build_subscribe_id(uint8_t *buf,
size_t cap, uint8_t flags, uint16_t msg_id, uint16_t topic_id)
217 size_t total, p = frame_header(buf, cap, MQTTSN_SUBSCRIBE, 1 + 2 + 2, &total);
223 wr16(buf + p, msg_id);
225 wr16(buf + p, topic_id);
229size_t pc_mqttsn_build_pingreq(uint8_t *buf,
size_t cap,
const char *client_id)
235 size_t idlen = client_id ? strnlen(client_id, cap) : 0;
236 size_t total, p = frame_header(buf, cap, MQTTSN_PINGREQ, idlen, &total);
243 memcpy(buf + p, client_id, idlen);
248size_t pc_mqttsn_build_disconnect(uint8_t *buf,
size_t cap,
bool with_duration, uint16_t duration)
254 size_t total, p = frame_header(buf, cap, MQTTSN_DISCONNECT, with_duration ? 2 : 0, &total);
261 wr16(buf + p, duration);
266size_t pc_mqttsn_build_searchgw(uint8_t *buf,
size_t cap, uint8_t radius)
272 size_t total, p = frame_header(buf, cap, MQTTSN_SEARCHGW, 1, &total);
281bool pc_mqttsn_parse_header(
const uint8_t *buf,
size_t len, MqttsnHeader *out,
size_t *consumed)
283 if (!buf || !out || !consumed || len < 2)
289 if (buf[0] == MQTTSN_LEN3_PREFIX)
295 total = ((size_t)buf[1] << 8) | buf[2];
303 if (total < lenfield + 1)
311 out->msg_type = buf[lenfield];
312 out->payload = buf + lenfield + 1;
313 out->payload_len = total - lenfield - 1;
318bool pc_mqttsn_parse_connack(
const uint8_t *payload,
size_t len, uint8_t *ret_code)
320 if (!payload || len < 1)
326 *ret_code = payload[0];
331bool pc_mqttsn_parse_regack(
const uint8_t *payload,
size_t len, uint16_t *topic_id, uint16_t *msg_id, uint8_t *ret_code)
333 if (!payload || len < 5)
339 *topic_id = rd16(payload);
343 *msg_id = rd16(payload + 2);
347 *ret_code = payload[4];
352bool pc_mqttsn_parse_puback(
const uint8_t *payload,
size_t len, uint16_t *topic_id, uint16_t *msg_id, uint8_t *ret_code)
354 return pc_mqttsn_parse_regack(payload, len, topic_id, msg_id, ret_code);
357bool pc_mqttsn_parse_suback(
const uint8_t *payload,
size_t len, uint8_t *flags, uint16_t *topic_id, uint16_t *msg_id,
360 if (!payload || len < 6)
370 *topic_id = rd16(payload + 1);
374 *msg_id = rd16(payload + 3);
378 *ret_code = payload[5];
383bool pc_mqttsn_parse_publish(
const uint8_t *payload,
size_t len, uint8_t *flags, uint16_t *topic_id, uint16_t *msg_id,
384 const uint8_t **data,
size_t *data_len)
386 if (!payload || len < 5)
396 *topic_id = rd16(payload + 1);
400 *msg_id = rd16(payload + 3);
413bool pc_mqttsn_parse_register(
const uint8_t *payload,
size_t len, uint16_t *topic_id, uint16_t *msg_id,
414 const char **topic_name,
size_t *topic_name_len)
416 if (!payload || len < 4)
422 *topic_id = rd16(payload);
426 *msg_id = rd16(payload + 2);
430 *topic_name = (
const char *)(payload + 4);
434 *topic_name_len = len - 4;
MQTT-SN v1.2 wire codec (PC_ENABLE_MQTT_SN) - zero-heap message builder + parser for MQTT for Sensor ...