Compare commits
11 Commits
11d4a046e1
...
master
Author | SHA1 | Date | |
---|---|---|---|
9e22556d36 | |||
1ac129a027
|
|||
44647d686f | |||
3d52c14d53
|
|||
f27e286e57
|
|||
dab7dd22a5
|
|||
7497aa9921
|
|||
931eddce41
|
|||
796b25b7ad
|
|||
e4d9be0106 | |||
477f3e2e3f
|
3
Makefile
3
Makefile
@@ -1,11 +1,10 @@
|
|||||||
# Makefile - A simple client for MQTT in C
|
# Makefile - A simple client for MQTT in C
|
||||||
# Derived from the PubSubClient from Nick O'Leary
|
|
||||||
# Wolfgang Hottgenroth <woho@hottis.de>
|
# Wolfgang Hottgenroth <woho@hottis.de>
|
||||||
# https://home.hottis.de/gitlab/wolutator/pubsubc
|
# https://home.hottis.de/gitlab/wolutator/pubsubc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CFLAGS?=-mcpu=cortex-m3 -mthumb -Og -fdata-sections -ffunction-sections -g -gdwarf-2
|
CFLAGS?=-mcpu=cortex-m3 -mthumb -Og -fdata-sections -ffunction-sections -g -gdwarf-2 -Wall -Werror
|
||||||
|
|
||||||
CC=arm-none-eabi-gcc
|
CC=arm-none-eabi-gcc
|
||||||
AR=arm-none-eabi-ar
|
AR=arm-none-eabi-ar
|
||||||
|
80
README.md
80
README.md
@@ -1,5 +1,85 @@
|
|||||||
|
# pubsubc
|
||||||
|
|
||||||
|
This is a minimal MQTT client library in C.
|
||||||
|
|
||||||
|
It comes with an adaption layer for the ioLibrary_Driver for the
|
||||||
|
WizNet chips which can be found here https://github.com/Wiznet/ioLibrary_Driver.
|
||||||
|
|
||||||
|
You find a fork with a Makefile a STMCubeMX generated project here
|
||||||
|
https://home.hottis.de/gitlab/wolutator/ioLibrary_Driver/-/tree/WolfgangsOwnBranch.
|
||||||
|
|
||||||
|
Using this adaption layer you should find it easy to adjust it for
|
||||||
|
other platforms.
|
||||||
|
|
||||||
This work is directly derived from the famous PubSubClient library
|
This work is directly derived from the famous PubSubClient library
|
||||||
of Nick O'Leary, which can be found at https://pubsubclient.knolleary.net/
|
of Nick O'Leary, which can be found at https://pubsubclient.knolleary.net/
|
||||||
|
|
||||||
It is most or less a plain C rewrite.
|
It is most or less a plain C rewrite.
|
||||||
|
|
||||||
|
All honour for this working MQTT client library goes to Nick O'Leary,
|
||||||
|
all blame for bugs in the C port shall go to me.
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
|
||||||
|
The library provides the following functions:
|
||||||
|
|
||||||
|
|
||||||
|
### Initialization
|
||||||
|
|
||||||
|
void mqttClientInit(mqttClient_t *mqttClient, client_t *client, callback_t callback);
|
||||||
|
|
||||||
|
Initializes the MQTT client, handover a client handle according to the definition
|
||||||
|
from ``platformAdaption.h`` and a callback function for incoming messages.
|
||||||
|
|
||||||
|
Implement this callback function for incoming messages with this footprint:
|
||||||
|
|
||||||
|
typedef void (*callback_t)(char*, uint8_t*, uint16_t);
|
||||||
|
|
||||||
|
### Connect
|
||||||
|
|
||||||
|
bool mqttConnect(mqttClient_t *mqttClient,
|
||||||
|
uint8_t *address, uint16_t port,
|
||||||
|
const char *id,
|
||||||
|
const char *user, const char *pass,
|
||||||
|
const char *willTopic, uint8_t willQos,
|
||||||
|
bool willRetain, const char *willMessage,
|
||||||
|
bool cleanSession);
|
||||||
|
|
||||||
|
In the original C++ implementation multiple variants of the ``connect``method are available
|
||||||
|
with less and lesser arguments. Unfortunately, in C this is no option. If you don't care
|
||||||
|
about authentication and the whole will stuff you can call it
|
||||||
|
|
||||||
|
mqttConnect(&mqttClient, brokerAddress, brokerPort, clientId, NULL, NULL, NULL, 0, false, NULL, false);
|
||||||
|
|
||||||
|
### Disconnect
|
||||||
|
|
||||||
|
void mqttDisconnect(mqttClient_t *mqttClient);
|
||||||
|
|
||||||
|
### Publish
|
||||||
|
|
||||||
|
bool publish(mqttClient_t *mqttClient,
|
||||||
|
const char *topic,
|
||||||
|
const uint8_t *payload, uint16_t plength,
|
||||||
|
bool retained);
|
||||||
|
|
||||||
|
### Subscribe and Unsubscribe
|
||||||
|
|
||||||
|
bool subscribe(mqttClient_t *mqttClient,
|
||||||
|
const char *topic, uint8_t qos);
|
||||||
|
|
||||||
|
bool unsubscribe(mqttClient_t *mqttClient,
|
||||||
|
const char* topic);
|
||||||
|
|
||||||
|
### Loop
|
||||||
|
|
||||||
|
bool mqttLoop(mqttClient_t *mqttClient);
|
||||||
|
|
||||||
|
Call this function in your idle loop. For my own part, I've implemented a time-triggered system
|
||||||
|
and call it with a period of 100ms.
|
||||||
|
|
||||||
|
### Connection status
|
||||||
|
|
||||||
|
bool mqttConnected(mqttClient_t *mqttClient);
|
||||||
|
|
||||||
|
@@ -17,24 +17,24 @@ int clientConnect(client_t *client, uint8_t *host, uint16_t port) {
|
|||||||
int8_t res = socket(client->sockNum, Sn_MR_TCP, port, SF_IO_NONBLOCK);
|
int8_t res = socket(client->sockNum, Sn_MR_TCP, port, SF_IO_NONBLOCK);
|
||||||
if (res != client->sockNum) {
|
if (res != client->sockNum) {
|
||||||
close(client->sockNum);
|
close(client->sockNum);
|
||||||
return INVALID_RESPONSE;
|
return PSC_INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
logMsg("clientConnect: socket initialized");
|
logMsg("clientConnect: socket initialized");
|
||||||
|
|
||||||
res = connect(client->sockNum, host, port);
|
res = connect(client->sockNum, host, port);
|
||||||
if (res != SOCK_BUSY) {
|
if (res != SOCK_BUSY) {
|
||||||
close(client->sockNum);
|
close(client->sockNum);
|
||||||
return INVALID_RESPONSE;
|
return PSC_INVALID_RESPONSE;
|
||||||
}
|
}
|
||||||
uint32_t startTime = HAL_GetTick();
|
uint32_t startTime = HAL_GetTick();
|
||||||
while (startTime + TIMEOUT_MS > HAL_GetTick()) {
|
while (startTime + PSC_TIMEOUT_MS > HAL_GetTick()) {
|
||||||
uint8_t sockState = getSn_SR(client->sockNum);
|
uint8_t sockState = getSn_SR(client->sockNum);
|
||||||
if (sockState == SOCK_ESTABLISHED) {
|
if (sockState == SOCK_ESTABLISHED) {
|
||||||
logMsg("clientConnect: connection established");
|
logMsg("clientConnect: connection established");
|
||||||
return SUCCESS;
|
return PSC_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TIMED_OUT;
|
return PSC_TIMED_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int clientAvailable(client_t *client) {
|
int clientAvailable(client_t *client) {
|
||||||
@@ -46,11 +46,11 @@ void clientStop(client_t *client) {
|
|||||||
|
|
||||||
if (res != SOCK_BUSY) {
|
if (res != SOCK_BUSY) {
|
||||||
close(client->sockNum);
|
close(client->sockNum);
|
||||||
logMsg("clientStop: disconnect returns 0x%02x, invalid response, ignore it", res);
|
logMsg("clientStop: disconnect returns %d, invalid response, ignore it", res);
|
||||||
} else {
|
} else {
|
||||||
bool successfullyClosed = false;
|
bool successfullyClosed = false;
|
||||||
uint32_t startTime = HAL_GetTick();
|
uint32_t startTime = HAL_GetTick();
|
||||||
while (startTime + TIMEOUT_MS > HAL_GetTick()) {
|
while (startTime + PSC_TIMEOUT_MS > HAL_GetTick()) {
|
||||||
uint8_t sockState = getSn_SR(client->sockNum);
|
uint8_t sockState = getSn_SR(client->sockNum);
|
||||||
if (sockState == SOCK_CLOSED) {
|
if (sockState == SOCK_CLOSED) {
|
||||||
logMsg("clientStop: connection closed");
|
logMsg("clientStop: connection closed");
|
||||||
@@ -72,7 +72,7 @@ int clientRead(client_t *client) {
|
|||||||
int res = -1;
|
int res = -1;
|
||||||
if (clientAvailable(client) >= 1) {
|
if (clientAvailable(client) >= 1) {
|
||||||
uint8_t buf;
|
uint8_t buf;
|
||||||
int32_t res = recv(client->sockNum, &buf, 1);
|
res = recv(client->sockNum, &buf, 1);
|
||||||
if (res == 1) {
|
if (res == 1) {
|
||||||
res = (int) buf;
|
res = (int) buf;
|
||||||
}
|
}
|
||||||
@@ -99,4 +99,6 @@ bool clientConnected(client_t *client) {
|
|||||||
|
|
||||||
uint32_t millis() {
|
uint32_t millis() {
|
||||||
return HAL_GetTick();
|
return HAL_GetTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -14,13 +14,13 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
const int SUCCESS = 1;
|
#define PSC_SUCCESS 1
|
||||||
const int TIMED_OUT = -1;
|
#define PSC_TIMED_OUT -1
|
||||||
const int INVALID_SERVER = -2;
|
#define PSC_INVALID_SERVER -2
|
||||||
const int TRUNCATED = -3;
|
#define PSC_TRUNCATED -3
|
||||||
const int INVALID_RESPONSE = -4;
|
#define PSC_INVALID_RESPONSE -4
|
||||||
|
|
||||||
const uint32_t TIMEOUT_MS = 1000;
|
#define PSC_TIMEOUT_MS 1000
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@@ -150,14 +150,14 @@ void mqttClientInit(mqttClient_t *mqttClient, client_t *client, callback_t callb
|
|||||||
memset(mqttClient->buffer, 0, mqttClient->bufferSize);
|
memset(mqttClient->buffer, 0, mqttClient->bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool connect(mqttClient_t *mqttClient,
|
bool mqttConnect(mqttClient_t *mqttClient,
|
||||||
uint8_t *address, uint16_t port,
|
uint8_t *address, uint16_t port,
|
||||||
const char *id,
|
const char *id,
|
||||||
const char *user, const char *pass,
|
const char *user, const char *pass,
|
||||||
const char *willTopic, uint8_t willQos,
|
const char *willTopic, uint8_t willQos,
|
||||||
bool willRetain, const char *willMessage,
|
bool willRetain, const char *willMessage,
|
||||||
bool cleanSession) {
|
bool cleanSession) {
|
||||||
if (!connected(mqttClient)) {
|
if (!mqttConnected(mqttClient)) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if(clientConnected(mqttClient->client)) {
|
if(clientConnected(mqttClient->client)) {
|
||||||
@@ -259,7 +259,7 @@ bool connect(mqttClient_t *mqttClient,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void disconnect(mqttClient_t *mqttClient) {
|
void mqttDisconnect(mqttClient_t *mqttClient) {
|
||||||
mqttClient->buffer[0] = MQTTDISCONNECT;
|
mqttClient->buffer[0] = MQTTDISCONNECT;
|
||||||
mqttClient->buffer[1] = 0;
|
mqttClient->buffer[1] = 0;
|
||||||
clientWrite(mqttClient->client, mqttClient->buffer, 2);
|
clientWrite(mqttClient->client, mqttClient->buffer, 2);
|
||||||
@@ -269,8 +269,8 @@ void disconnect(mqttClient_t *mqttClient) {
|
|||||||
mqttClient->lastInActivity = mqttClient->lastOutActivity = millis();
|
mqttClient->lastInActivity = mqttClient->lastOutActivity = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loop(mqttClient_t *mqttClient) {
|
bool mqttLoop(mqttClient_t *mqttClient) {
|
||||||
if (connected(mqttClient)) {
|
if (mqttConnected(mqttClient)) {
|
||||||
uint32_t t = millis();
|
uint32_t t = millis();
|
||||||
if ((t - mqttClient->lastInActivity > mqttClient->keepAlive*1000UL) ||
|
if ((t - mqttClient->lastInActivity > mqttClient->keepAlive*1000UL) ||
|
||||||
(t - mqttClient->lastOutActivity > mqttClient->keepAlive*1000UL)) {
|
(t - mqttClient->lastOutActivity > mqttClient->keepAlive*1000UL)) {
|
||||||
@@ -325,7 +325,7 @@ bool loop(mqttClient_t *mqttClient) {
|
|||||||
} else if (type == MQTTPINGRESP) {
|
} else if (type == MQTTPINGRESP) {
|
||||||
mqttClient->pingOutstanding = false;
|
mqttClient->pingOutstanding = false;
|
||||||
}
|
}
|
||||||
} else if (!connected(mqttClient)) {
|
} else if (!mqttConnected(mqttClient)) {
|
||||||
// readPacket has closed the connection
|
// readPacket has closed the connection
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ bool loop(mqttClient_t *mqttClient) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool connected(mqttClient_t *mqttClient) {
|
bool mqttConnected(mqttClient_t *mqttClient) {
|
||||||
bool rc;
|
bool rc;
|
||||||
if (mqttClient->client == NULL ) {
|
if (mqttClient->client == NULL ) {
|
||||||
rc = false;
|
rc = false;
|
||||||
@@ -358,7 +358,7 @@ bool publish(mqttClient_t *mqttClient,
|
|||||||
const char *topic,
|
const char *topic,
|
||||||
const uint8_t *payload, uint16_t plength,
|
const uint8_t *payload, uint16_t plength,
|
||||||
bool retained) {
|
bool retained) {
|
||||||
if (connected(mqttClient)) {
|
if (mqttConnected(mqttClient)) {
|
||||||
if (mqttClient->bufferSize < MQTT_MAX_HEADER_SIZE + 2 + strnlen(topic, mqttClient->bufferSize) + plength) {
|
if (mqttClient->bufferSize < MQTT_MAX_HEADER_SIZE + 2 + strnlen(topic, mqttClient->bufferSize) + plength) {
|
||||||
// Too long
|
// Too long
|
||||||
return false;
|
return false;
|
||||||
@@ -395,7 +395,7 @@ bool subscribe(mqttClient_t *mqttClient,
|
|||||||
// Too long
|
// Too long
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (connected(mqttClient)) {
|
if (mqttConnected(mqttClient)) {
|
||||||
// Leave room in the buffer for header and variable length field
|
// Leave room in the buffer for header and variable length field
|
||||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||||
mqttClient->nextMsgId++;
|
mqttClient->nextMsgId++;
|
||||||
@@ -421,7 +421,7 @@ bool unsubscribe(mqttClient_t *mqttClient,
|
|||||||
// Too long
|
// Too long
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (connected(mqttClient)) {
|
if (mqttConnected(mqttClient)) {
|
||||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||||
mqttClient->nextMsgId++;
|
mqttClient->nextMsgId++;
|
||||||
if (mqttClient->nextMsgId == 0) {
|
if (mqttClient->nextMsgId == 0) {
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
// MQTT_MAX_PACKET_SIZE : Maximum packet size. Override with setBufferSize().
|
// MQTT_MAX_PACKET_SIZE : Maximum packet size. Override with setBufferSize().
|
||||||
#ifndef MQTT_MAX_PACKET_SIZE
|
#ifndef MQTT_MAX_PACKET_SIZE
|
||||||
#define MQTT_MAX_PACKET_SIZE 256
|
#define MQTT_MAX_PACKET_SIZE 512
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MQTT_KEEPALIVE : keepAlive interval in Seconds. Override with setKeepAlive()
|
// MQTT_KEEPALIVE : keepAlive interval in Seconds. Override with setKeepAlive()
|
||||||
@@ -100,7 +100,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
void mqttClientInit(mqttClient_t *mqttClient, client_t *client, callback_t callback);
|
void mqttClientInit(mqttClient_t *mqttClient, client_t *client, callback_t callback);
|
||||||
bool connect(mqttClient_t *mqttClient,
|
bool mqttConnect(mqttClient_t *mqttClient,
|
||||||
uint8_t *address, uint16_t port,
|
uint8_t *address, uint16_t port,
|
||||||
const char *id,
|
const char *id,
|
||||||
const char *user, const char *pass,
|
const char *user, const char *pass,
|
||||||
@@ -108,7 +108,7 @@ bool connect(mqttClient_t *mqttClient,
|
|||||||
bool willRetain, const char *willMessage,
|
bool willRetain, const char *willMessage,
|
||||||
bool cleanSession);
|
bool cleanSession);
|
||||||
|
|
||||||
void disconnect(mqttClient_t *mqttClient);
|
void mqttDisconnect(mqttClient_t *mqttClient);
|
||||||
|
|
||||||
bool publish(mqttClient_t *mqttClient,
|
bool publish(mqttClient_t *mqttClient,
|
||||||
const char *topic,
|
const char *topic,
|
||||||
@@ -120,8 +120,8 @@ bool subscribe(mqttClient_t *mqttClient,
|
|||||||
bool unsubscribe(mqttClient_t *mqttClient,
|
bool unsubscribe(mqttClient_t *mqttClient,
|
||||||
const char* topic);
|
const char* topic);
|
||||||
|
|
||||||
bool loop(mqttClient_t *mqttClient);
|
bool mqttLoop(mqttClient_t *mqttClient);
|
||||||
|
|
||||||
bool connected(mqttClient_t *mqttClient);
|
bool mqttConnected(mqttClient_t *mqttClient);
|
||||||
|
|
||||||
#endif // _PUBSUBC_H_
|
#endif // _PUBSUBC_H_
|
||||||
|
Reference in New Issue
Block a user