LoboMQ
Loading...
Searching...
No Matches
PubSub.cpp
Go to the documentation of this file.
1
9#include "LoboMQ/PubSub.h"
10
11Elog *logger;
12
13bool configureESPNOW(uint8_t *mac) {
14 logger->log(DEBUG, "Setting up ESP-NOW and connection with broker at %02X:%02X:%02X:%02X:%02X:%02X.",
15 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
16 WiFi.mode(WIFI_STA);
17 if (esp_now_init() != ESP_OK) { //initialize ESP-NOW
18 logger->log(ERROR, "Couldn't initialize ESP-NOW");
19 return false;
20 }
21
22 //Setup ESPNOW and peer
23 if(esp_now_is_peer_exist(mac)) {
24 return true; //peer already registered
25 } else {
26 esp_now_peer_info_t peerInfo;
27 memset(&peerInfo, 0, sizeof(peerInfo));
28 memcpy(peerInfo.peer_addr, mac, 6);
29 peerInfo.channel = 0;
30 peerInfo.encrypt = false;
31
32 esp_err_t result = esp_now_add_peer(&peerInfo);
33 if (result != ESP_OK) {
34 logger->log(ERROR, "Couldn't register peer: %d.", result);
35 return false;
36 }
37 return true;
38 }
39}
40
41int fixTopicAndCheckLength(char *topic) {
42 if (topic == NULL) //if no topic was given
44
45 size_t len = strlen(topic);
46 if (len == 0 || len > MAXTOPICLENGTH) //if empty or has many characters
48
49 if (topic[0] == '/') { //if leading '/', remove
50 memmove(topic, topic + 1, len); //move characters one position to the left
51 len--;
52 if (len == 0)
54 }
55
56 if (topic[len-1] == '/') { //if trailing '/'
57 topic[len-1] = '\0'; //null-terminate the string to remove the trailing '/'
58 len--;
59 if (len == 0)
61 }
62
63 return LMQ_ERR_SUCCESS;
64}
65
66bool isASCII(char c) {
67 return c >= 0 && c <= 127;
68}
69
70int pubTopicCheck(char *topic) {
71 if (fixTopicAndCheckLength(topic) == LMQ_ERR_INVAL_TOPIC) //removes initial or final '/' and checks its length
73
74 for (size_t i = 0; i < strlen(topic); i++) {
75 if (topic[i] == '+' || topic[i] == '#' || !isASCII(topic[i])) //if there's '+', '#' or a non-ASCII character
77 }
79}
80
81int subTopicCheck(char *topic) {
82 if (fixTopicAndCheckLength(topic) == LMQ_ERR_INVAL_TOPIC) //removes initial or final '/' and checks its length
84
85 char prev = '\0';
86 for (int i = 0; i < strlen(topic); i++) { //runs through every character
87 char c = topic[i];
88 if (!isASCII(c))
90
91 if (c == '+') { //if '+' was found
92 if ((prev != '\0' && prev != '/') || (topic[i+1] != '\0' && topic[i+1] != '/'))
93 //(not first char && not after '/') || (not last char && not followed by '/')
95 } else if (c == '#') { //if '#' was found
96 if ((prev != '\0' && prev != '/') || topic[i+1] != '\0')
97 //(not first char && not after '/') || not last char
99 }
100 prev = c;
101 }
102 return LMQ_ERR_VALID_TOPIC;
103}
104
105LMQErrType publish(uint8_t *mac, char *topic, void *payload, size_t payloadSize, Elog *_logger) {
106 logger = _logger;
107 if (!configureESPNOW(mac)) {
109 }
110 if (pubTopicCheck(topic) == LMQ_ERR_INVAL_TOPIC) {
111 logger->log(ERROR, "Invalid topic: '%s'", topic);
112 return LMQ_ERR_INVAL_TOPIC;
113 }
114
115 //Create and fill publish message
116 PublishContent pubMsg;
117 pubMsg.type = MSGTYPE_PUBLISH;
118 strcpy(pubMsg.topic, topic);
119 pubMsg.contentSize = payloadSize;
120 memcpy(&pubMsg.content, payload, payloadSize);
121
122 //Send message
123 esp_err_t result = esp_now_send(mac, (uint8_t *) &pubMsg, sizeof(pubMsg));
124 if (result != ESP_OK) {
125 logger->log(ERROR, "Error sending message: %d.", result);
127 }
128 logger->log(INFO, "Message of %dB published successfully to '%s'.", payloadSize, topic);
129
130 return LMQ_ERR_SUCCESS;
131}
132
133LMQErrType subscribe(uint8_t *mac, char *topic, Elog *_logger) {
134 logger = _logger;
135 if (!configureESPNOW(mac)) {
137 }
138 if (subTopicCheck(topic) == LMQ_ERR_INVAL_TOPIC) {
139 logger->log(ERROR, "Invalid topic: '%s'.", topic);
140 return LMQ_ERR_INVAL_TOPIC;
141 }
142
143 //Create subscribe message
145 subMsg.type = MSGTYPE_SUBSCRIBE;
146 strcpy(subMsg.topic, topic);
147
148 //Send message
149 esp_err_t result = esp_now_send(mac, (uint8_t *) &subMsg, sizeof(subMsg));
150 if (result != ESP_OK) {
151 logger->log(ERROR, "Error sending message: %d.", result);
153 }
154 logger->log(INFO, "Subscribed to '%s'.", subMsg.topic);
155
156 return LMQ_ERR_SUCCESS;
157}
158
159LMQErrType unsubscribe(uint8_t *mac, char *topic, Elog *_logger) {
160 logger = _logger;
161 if (!configureESPNOW(mac)) {
163 }
164 if (subTopicCheck(topic) == LMQ_ERR_INVAL_TOPIC) {
165 logger->log(ERROR, "Invalid topic: '%s'.", topic);
166 return LMQ_ERR_INVAL_TOPIC;
167 }
168
169 //Create subscribe message
171 unsubMsg.type = MSGTYPE_UNSUBSCRIBE;
172 strcpy(unsubMsg.topic, topic);
173
174 //Send message
175 esp_err_t result = esp_now_send(mac, (uint8_t *) &unsubMsg, sizeof(unsubMsg));
176 if (result != ESP_OK) {
177 logger->log(ERROR, "Error sending message: %d.", result);
179 }
180 logger->log(INFO, "Unsubscribed from '%s'.", unsubMsg.topic);
181 return LMQ_ERR_SUCCESS;
182
183 return LMQ_ERR_SUCCESS;
184}
185
186bool isLMQMessage(const uint8_t *incomingData) {
187 MessageType msgType = ((MessageBase*)incomingData)->type;
188 return msgType == MSGTYPE_PUBLISH;
189}
190
191PayloadContent getLMQPayload(const uint8_t *incomingData) {
192 PublishContent *pubMsg;
193 memcpy(&pubMsg, &incomingData, sizeof(pubMsg));
194 PayloadContent content;
195 content.contentSize = pubMsg->contentSize;
196 memcpy(content.content, &pubMsg->content, content.contentSize);
197 return content;
198}
LMQErrType
Enumerates every error code that can be returned by the library functions.
Definition Includes.h:28
@ LMQ_ERR_INVAL_TOPIC
Invalid topic (no topic, too big, contains wildcard characters in wrong positions,...
Definition Includes.h:36
@ LMQ_ERR_BAD_ESP_CONFIG
Couldn't initialize ESP-NOW.
Definition Includes.h:39
@ LMQ_ERR_SUCCESS
No error, operation successful.
Definition Includes.h:30
@ LMQ_ERR_ESP_SEND_FAIL
Couldn't send the message.
Definition Includes.h:42
@ LMQ_ERR_VALID_TOPIC
No error, valid topic.
Definition Includes.h:33
LMQErrType unsubscribe(uint8_t *mac, char *topic, Elog *_logger)
Unsubscribes from a topic on the broker.
Definition PubSub.cpp:159
LMQErrType subscribe(uint8_t *mac, char *topic, Elog *_logger)
Subscribes to a topic on the broker.
Definition PubSub.cpp:133
LMQErrType publish(uint8_t *mac, char *topic, void *payload, size_t payloadSize, Elog *_logger)
Publishes a message to the broker.
Definition PubSub.cpp:105
PayloadContent getLMQPayload(const uint8_t *incomingData)
Gets the payload content inside a published message This function extracts the payload from the bytes...
Definition PubSub.cpp:191
bool isLMQMessage(const uint8_t *incomingData)
Checks if the data received is a MQ message.
Definition PubSub.cpp:186
MessageType
Enumerates every type of message sent between the broker and the clients.
Definition PubSub.h:25
@ MSGTYPE_UNSUBSCRIBE
Unsubscribe message, sent from subscriber to broker.
Definition PubSub.h:29
@ MSGTYPE_PUBLISH
Publish message, sent from publisher to broker or from broker to subscriber.
Definition PubSub.h:31
@ MSGTYPE_SUBSCRIBE
Subscribe message, sent from subscriber to broker.
Definition PubSub.h:27
Structure that contains the fields used by every message.
Definition PubSub.h:38
Structure representing the content of a payload This structure holds properties of the content receiv...
Definition PubSub.h:147
void * content[MAXCONTENTSIZE]
Array to hold content.
Definition PubSub.h:149
size_t contentSize
Size of the content.
Definition PubSub.h:148
Structure that contains the fields used by a publish message, apart from those inherited from the Mes...
Definition PubSub.h:65
char topic[MAXTOPICLENGTH]
Topic where the message is published to.
Definition PubSub.h:66
size_t contentSize
Size of the content.
Definition PubSub.h:67
void * content[MAXCONTENTSIZE]
Any content stored as bytes.
Definition PubSub.h:68
Structure that contains the fields used by a subscribe message, apart from those inherited from the M...
Definition PubSub.h:47
char topic[MAXTOPICLENGTH]
Topic that the subscriber shows interest in.
Definition PubSub.h:48
Structure that contains the fields used by a unsubscribe message, apart from those inherited from the...
Definition PubSub.h:56
char topic[MAXTOPICLENGTH]
Topic that the subscriber no longer shows interest in.
Definition PubSub.h:57