4#include "ustd_platform.h"
12#define HardwareSerial TinySoftwareSerial
82 HardwareSerial *pSerial;
83 unsigned long baudRate;
84 uint8_t connectionLed;
85 unsigned long ledTimer = 0;
87 enum LinkState { SYNC, HEADER, MSG, MUCRC };
88 bool bCheckLink =
false;
91 unsigned long lastRead = 0;
92 unsigned long lastMsg = 0;
93 unsigned long lastPingSent = 0;
94 bool linkConnected =
false;
95 unsigned long readTimeout = 5;
96 unsigned long pingReceiveTimeout = 10;
97 unsigned long pingPeriod = 5;
98 String remoteName =
"";
99 ustd::array<String> outgoingBlockList;
100 ustd::array<String> incomingBlockList;
102 const uint8_t SOH = 0x01, STX = 0x02, ETX = 0x03, EOT = 0x04;
103 const uint8_t VER = 0x01;
113 typedef struct t_header {
125 typedef struct t_footer {
139 MuSerial(String name, HardwareSerial *pSerial,
unsigned long baudRate = 115200,
140 uint8_t connectionLed = -1)
141 : name(name), pSerial(pSerial), baudRate(baudRate), connectionLed(connectionLed) {
162 pSerial->begin(baudRate);
168 auto ft = [=]() { this->loop(); };
169 tID = pSched->add(ft,
"serlink", 20000L);
170 auto fnall = [=](String topic, String msg, String originator) {
171 this->subsMsg(topic, msg, originator);
173 pSched->subscribe(tID,
"#", fnall);
176 if (connectionLed != -1) {
177 pinMode(connectionLed, OUTPUT);
192 for (
unsigned int i = 0; i < outgoingBlockList.length(); i++) {
193 if (outgoingBlockList[i] == topic)
196 if (outgoingBlockList.add(topic) == -1)
210 for (
unsigned int i = 0; i < outgoingBlockList.length(); i++) {
211 if (outgoingBlockList[i] == topic) {
212 if (!outgoingBlockList.erase(i))
228 for (
unsigned int i = 0; i < incomingBlockList.length(); i++) {
229 if (incomingBlockList[i] == topic)
232 if (incomingBlockList.add(topic) == -1)
246 for (
unsigned int i = 0; i < incomingBlockList.length(); i++) {
247 if (incomingBlockList[i] == topic) {
248 if (!incomingBlockList.erase(i))
257 unsigned char crc(
const unsigned char *buf,
unsigned int len,
unsigned char init = 0) {
258 unsigned char c = init;
259 for (
unsigned int i = 0; i < len; i++)
266#if defined(__ARDUINO__) || defined(__ARM__) || defined(__RISC_V__)
267 ltoa(pSched->getUptime(), strTime, 15);
269 ltoa(time(
nullptr), strTime, 15);
271 sendOut(strTime, name, LinkCmd::MUPING);
272 lastPingSent = pSched->getUptime();
275 void handleTime(uint64_t remoteTime) {
279 void sendOut(String topic, String msg, LinkCmd cmd = LinkCmd::MQTT) {
283 unsigned char nul = 0x0;
290 unsigned int len = topic.length() + msg.length() + 2;
298 ccrc = crc((
const uint8_t *)&(th.ver),
sizeof(th) - 1);
299 ccrc = crc((
const uint8_t *)topic.c_str(), topic.length(), ccrc);
300 ccrc = crc((
const uint8_t *)&nul, 1, ccrc);
301 ccrc = crc((
const uint8_t *)msg.c_str(), msg.length(), ccrc);
302 ccrc = crc((
const uint8_t *)&nul, 1, ccrc);
303 ccrc = crc((
const uint8_t *)&tf, 2, ccrc);
307 pSerial->write((
unsigned char *)&th,
sizeof(th));
308 pSerial->write((
unsigned char *)topic.c_str(), topic.length());
309 pSerial->write((uint8_t)nul);
310 pSerial->write((
unsigned char *)msg.c_str(), msg.length());
311 pSerial->write((uint8_t)nul);
312 pSerial->write((
unsigned char *)&tf,
sizeof(tf));
319 uint16_t msgLen, curMsg;
320 unsigned char *msgBuf =
nullptr;
321 bool allocated =
false;
326 bool internalPub(String topic, String msg) {
327 for (
unsigned int i = 0; i < incomingBlockList.length(); i++) {
328 if (Scheduler::mqttmatch(topic, incomingBlockList[i])) {
334 String pre2 = remoteName +
"/";
335 String pre1 = name +
"/";
336 if (topic.substring(0, pre1.length()) == pre1) {
337 topic = topic.substring(pre1.length());
339 if (topic.substring(0, pre2.length()) == pre1) {
340 topic = topic.substring(pre2.length());
344 pSched->publish(topic, msg, remoteName);
356 if (connectionLed != -1) {
361 if (pSched->getUptime() - lastPingSent > pingPeriod) {
364 while (pSerial->available() > 0) {
366 lastRead = pSched->getUptime();
372 pHd = (
unsigned char *)&hd;
380 if (hLen ==
sizeof(hd)) {
382 if (hd.ver != VER || hd.stx != STX) {
385 msgLen = 256 * hd.hLen + hd.lLen;
387 msgBuf = (
unsigned char *)malloc(msgLen);
405 if (curMsg == msgLen) {
407 pFo = (
unsigned char *)&fo;
415 if (cLen ==
sizeof(fo)) {
416 if (fo.etx != ETX || fo.eot != EOT) {
417 if (allocated && msgBuf !=
nullptr) {
425 ccrc = crc((
const uint8_t *)&(hd.ver),
sizeof(hd) - 1);
426 ccrc = crc(msgBuf, msgLen, ccrc);
427 ccrc = crc((
const uint8_t *)&fo, 2, ccrc);
428 if (ccrc != fo.crc) {
429 if (allocated && msgBuf !=
nullptr) {
437 uint64_t remoteTime = 0;
439 if (strlen((
const char *)msgBuf) + 2 <= msgLen) {
440 lastMsg = pSched->getUptime();
442 (
const char *)&msgBuf[strlen((
const char *)msgBuf) + 1];
443 if (strlen(pM) + strlen((
const char *)msgBuf) + 2 <= msgLen) {
444 switch ((LinkCmd)hd.cmd) {
445 case LinkCmd::MUPING:
448 remoteTime = atol((
const char *)msgBuf);
449 handleTime(remoteTime);
450 lastMsg = pSched->getUptime();
451 if (connectionLed != -1) {
455 if (!linkConnected) {
456 linkConnected =
true;
457 pSched->publish(name +
"/link/" + remoteName,
462 internalPub((
const char *)msgBuf, pM);
467 if (allocated && msgBuf !=
nullptr) {
480 if (linkConnected || linkState != SYNC) {
481 if (linkState != SYNC) {
482 if ((
unsigned long)(pSched->getUptime() - lastRead) > readTimeout) {
485 pSched->publish(name +
"/link/" + remoteName,
"disconnected", name);
487 linkConnected =
false;
488 if (allocated && msgBuf !=
nullptr) {
495 if ((
unsigned long)(pSched->getUptime() - lastMsg) > pingReceiveTimeout) {
497 pSched->publish(name +
"/link/" + remoteName,
"disconnected", name);
499 linkConnected =
false;
506 void subsMsg(String topic, String msg, String originator) {
507 if (originator == remoteName) {
513 for (
unsigned int i = 0; i < outgoingBlockList.length(); i++) {
514 if (Scheduler::mqttmatch(topic, outgoingBlockList[i])) {
519 String pre = remoteName +
"/";
520 if (topic.substring(0, pre.length()) == pre) {
523 sendOut(remoteName +
"/" + topic, msg);
munet MuSerial Class
Definition: muserial.h:76
unsigned long connectionLedBlinkDurationMs
milli-secs the connectionLed is flashed on receiving a ping.
Definition: muserial.h:136
void begin(Scheduler *_pSched)
Definition: muserial.h:156
bool outgoingBlockRemove(String topic)
Definition: muserial.h:201
bool incomingBlockRemove(String topic)
Definition: muserial.h:237
MuSerial(String name, HardwareSerial *pSerial, unsigned long baudRate=115200, uint8_t connectionLed=-1)
Definition: muserial.h:139
bool incomingBlockSet(String topic)
Definition: muserial.h:220
bool activeLogic
Definition: muserial.h:134
bool outgoingBlockSet(String topic)
Definition: muserial.h:183
The muwerk namespace.
Definition: mqtt.h:21