Compare commits
No commits in common. "master" and "revert-500-master" have entirely different histories.
master
...
revert-500
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,7 +1 @@
|
||||
build
|
||||
pubsub.a
|
||||
tests/bin
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
|
@ -1,12 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
millis_t millis() {
|
||||
return HAL_GetTick();
|
||||
}
|
||||
|
||||
void yield() {
|
||||
// does nothing
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#ifndef _ARDUINO_H_
|
||||
#define _ARDUINO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <Print.h>
|
||||
#include <IPAddress.h>
|
||||
#include <Stream.h>
|
||||
#include <Client.h>
|
||||
#include <stubs.h>
|
||||
|
||||
|
||||
typedef uint32_t millis_t;
|
||||
typedef bool boolean;
|
||||
|
||||
|
||||
millis_t millis();
|
||||
void yield();
|
||||
|
||||
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
|
||||
#endif // _ARDUINO_H_
|
122
AAL/Client.cpp
122
AAL/Client.cpp
@ -1,122 +0,0 @@
|
||||
#include <socket.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Client.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
class Client {
|
||||
public:
|
||||
Client();
|
||||
int connect(const char *host, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int available();
|
||||
void stop();
|
||||
int read();
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
size_t write(uint8_t b);
|
||||
void flush();
|
||||
uint8_t connected();
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
Client::Client(uint8_t sockNum) : sockNum(sockNum) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
int Client::connect(const char *host, uint16_t) {
|
||||
// DNS request required
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Client::connect(IPAddress ip, uint16_t port) {
|
||||
int8_t res = socket(this->sockNum, Sn_MR_TCP, port, SF_IO_NONBLOCK);
|
||||
if (res != this->sockNum) {
|
||||
close(this->sockNum);
|
||||
return INVALID_RESPONSE;
|
||||
}
|
||||
logMsg("Client::connect: socket initialized");
|
||||
|
||||
res = ::connect(this->sockNum, ip.raw_address(), port);
|
||||
if (res != SOCK_BUSY) {
|
||||
close(this->sockNum);
|
||||
return INVALID_RESPONSE;
|
||||
}
|
||||
uint32_t startTime = HAL_GetTick();
|
||||
while (startTime + TIMEOUT_MS > HAL_GetTick()) {
|
||||
uint8_t sockState = getSn_SR(this->sockNum);
|
||||
if (sockState == SOCK_ESTABLISHED) {
|
||||
logMsg("Client::connect: connection established");
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
return TIMED_OUT;
|
||||
}
|
||||
|
||||
int Client::available() {
|
||||
return getSn_RX_RSR(this->sockNum);
|
||||
}
|
||||
|
||||
void Client::stop() {
|
||||
int8_t res = disconnect(this->sockNum);
|
||||
|
||||
if (res != SOCK_BUSY) {
|
||||
close(this->sockNum);
|
||||
logMsg("Client::stop: disconnect returns 0x%02x, invalid response, ignore it", res);
|
||||
} else {
|
||||
bool successfullyClosed = false;
|
||||
uint32_t startTime = HAL_GetTick();
|
||||
while (startTime + TIMEOUT_MS > HAL_GetTick()) {
|
||||
uint8_t sockState = getSn_SR(this->sockNum);
|
||||
if (sockState == SOCK_CLOSED) {
|
||||
logMsg("Client::stop: connection closed");
|
||||
successfullyClosed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (successfullyClosed) {
|
||||
logMsg("Client::stop: done");
|
||||
close(this->sockNum);
|
||||
} else {
|
||||
logMsg("Client::stop: timeout when closing, ignore");
|
||||
close(this->sockNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Client::read() {
|
||||
int res = -1;
|
||||
if (this->available() >= 1) {
|
||||
uint8_t buf;
|
||||
int32_t res = recv(this->sockNum, &buf, 1);
|
||||
if (res == 1) {
|
||||
res = (int) buf;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t Client::write(const uint8_t *buf, size_t size) {
|
||||
int32_t res = send(this->sockNum, (uint8_t*) buf, size);
|
||||
return (res == size) ? size : 0;
|
||||
}
|
||||
|
||||
size_t Client::write(uint8_t b) {
|
||||
return this->write(&b, 1);
|
||||
}
|
||||
|
||||
void Client::flush() {
|
||||
// does nothing
|
||||
}
|
||||
|
||||
uint8_t Client::connected() {
|
||||
return (getSn_SR(this->sockNum) == SOCK_ESTABLISHED) ? 1 : 0;
|
||||
}
|
||||
|
35
AAL/Client.h
35
AAL/Client.h
@ -1,35 +0,0 @@
|
||||
#ifndef _CLIENT_H_
|
||||
#define _CLIENT_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
|
||||
const int SUCCESS = 1;
|
||||
const int TIMED_OUT = -1;
|
||||
const int INVALID_SERVER = -2;
|
||||
const int TRUNCATED = -3;
|
||||
const int INVALID_RESPONSE = -4;
|
||||
|
||||
|
||||
const uint32_t TIMEOUT_MS = 1000;
|
||||
|
||||
class Client {
|
||||
private:
|
||||
const uint8_t sockNum;
|
||||
public:
|
||||
Client(const uint8_t sockNum);
|
||||
int connect(const char *host, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int available();
|
||||
void stop();
|
||||
int read();
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
size_t write(uint8_t b);
|
||||
void flush();
|
||||
uint8_t connected();
|
||||
};
|
||||
|
||||
#endif // _CLIENT_H_
|
@ -1,16 +0,0 @@
|
||||
#include <IPAddress.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
IPAddress::IPAddress() {
|
||||
memset(_address, 0, sizeof(_address));
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4) {
|
||||
_address[0] = o1;
|
||||
_address[1] = o2;
|
||||
_address[2] = o3;
|
||||
_address[3] = o4;
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
#ifndef _IPADDRESS_H_
|
||||
#define _IPADDRESS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class IPAddress {
|
||||
private:
|
||||
uint8_t _address[4];
|
||||
uint8_t *raw_address() { return _address; };
|
||||
public:
|
||||
IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4);
|
||||
IPAddress();
|
||||
|
||||
friend class Client;
|
||||
};
|
||||
|
||||
|
||||
#endif // _IPADDRESS_H_
|
@ -1,7 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
#include <Print.h>
|
||||
|
||||
|
||||
Print::Print() {
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef _PRINT_H_
|
||||
#define _PRINT_H_
|
||||
|
||||
class Print {
|
||||
public:
|
||||
Print();
|
||||
};
|
||||
|
||||
#endif // _PRINT_H_
|
@ -1,12 +0,0 @@
|
||||
#include <Stream.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
Stream::Stream() {
|
||||
|
||||
}
|
||||
|
||||
size_t Stream::write(uint8_t c) {
|
||||
return 0;
|
||||
}
|
13
AAL/Stream.h
13
AAL/Stream.h
@ -1,13 +0,0 @@
|
||||
#ifndef _STREAM_H_
|
||||
#define _STREAM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
Stream();
|
||||
size_t write(uint8_t c);
|
||||
};
|
||||
|
||||
#endif // _STREAM_H_
|
@ -1,9 +0,0 @@
|
||||
#ifndef _STUBS_H_
|
||||
#define _STUBS_H_
|
||||
|
||||
uint32_t HAL_GetTick(void);
|
||||
int logMsg(const char *format, ...);
|
||||
|
||||
|
||||
|
||||
#endif // _STUBS_H_
|
17
CHANGES.txt
17
CHANGES.txt
@ -1,20 +1,3 @@
|
||||
2.8
|
||||
* Add setBufferSize() to override MQTT_MAX_PACKET_SIZE
|
||||
* Add setKeepAlive() to override MQTT_KEEPALIVE
|
||||
* Add setSocketTimeout() to overide MQTT_SOCKET_TIMEOUT
|
||||
* Added check to prevent subscribe/unsubscribe to empty topics
|
||||
* Declare wifi mode prior to connect in ESP example
|
||||
* Use `strnlen` to avoid overruns
|
||||
* Support pre-connected Client objects
|
||||
|
||||
2.7
|
||||
* Fix remaining-length handling to prevent buffer overrun
|
||||
* Add large-payload API - beginPublish/write/publish/endPublish
|
||||
* Add yield call to improve reliability on ESP
|
||||
* Add Clean Session flag to connect options
|
||||
* Add ESP32 support for functional callback signature
|
||||
* Various other fixes
|
||||
|
||||
2.4
|
||||
* Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely
|
||||
whilst waiting for inbound data
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2008-2020 Nicholas O'Leary
|
||||
Copyright (c) 2008-2015 Nicholas O'Leary
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
30
Makefile
30
Makefile
@ -1,30 +0,0 @@
|
||||
CFLAGS?=-mcpu=cortex-m3 -mthumb -Og -fdata-sections -ffunction-sections -g -gdwarf-2
|
||||
|
||||
CC=arm-none-eabi-gcc
|
||||
CXX=arm-none-eabi-g++
|
||||
AR=arm-none-eabi-ar
|
||||
|
||||
CFLAGS+=-I../ioLibrary_Driver/Ethernet -Isrc -IAAL
|
||||
|
||||
OBJDIR=build
|
||||
VPATH=src AAL
|
||||
|
||||
OBJS=$(addprefix $(OBJDIR)/,PubSubClient.o IPAddress.o Stream.o Arduino.o Print.o Client.o)
|
||||
|
||||
all: $(OBJS)
|
||||
$(AR) rcs pubsub.a $^
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJS): | $(OBJDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -rf $(OBJDIR)
|
@ -13,12 +13,10 @@ Full API documentation is available here: https://pubsubclient.knolleary.net
|
||||
## Limitations
|
||||
|
||||
- It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1.
|
||||
- The maximum message size, including header, is **256 bytes** by default. This
|
||||
is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h` or can be changed
|
||||
by calling `PubSubClient::setBufferSize(size)`.
|
||||
- The maximum message size, including header, is **128 bytes** by default. This
|
||||
is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h`.
|
||||
- The keepalive interval is set to 15 seconds by default. This is configurable
|
||||
via `MQTT_KEEPALIVE` in `PubSubClient.h` or can be changed by calling
|
||||
`PubSubClient::setKeepAlive(keepAlive)`.
|
||||
via `MQTT_KEEPALIVE` in `PubSubClient.h`.
|
||||
- The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by
|
||||
changing value of `MQTT_VERSION` in `PubSubClient.h`.
|
||||
|
||||
@ -39,7 +37,6 @@ boards and shields, including:
|
||||
- TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library)
|
||||
- Intel Galileo/Edison
|
||||
- ESP8266
|
||||
- ESP32
|
||||
|
||||
The library cannot currently be used with hardware based on the ENC28J60 chip –
|
||||
such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an
|
||||
|
@ -27,9 +27,9 @@ void setup()
|
||||
{
|
||||
Ethernet.begin(mac, ip);
|
||||
// Note - the default maximum packet size is 128 bytes. If the
|
||||
// combined length of clientId, username and password exceed this use the
|
||||
// following to increase the buffer size:
|
||||
// client.setBufferSize(255);
|
||||
// combined length of clientId, username and password exceed this,
|
||||
// you will need to increase the value of MQTT_MAX_PACKET_SIZE in
|
||||
// PubSubClient.h
|
||||
|
||||
if (client.connect("arduinoClient", "testuser", "testpass")) {
|
||||
client.publish("outTopic","hello world");
|
||||
|
@ -1,21 +1,26 @@
|
||||
/*
|
||||
Basic ESP8266 MQTT example
|
||||
|
||||
This sketch demonstrates the capabilities of the pubsub library in combination
|
||||
with the ESP8266 board/library.
|
||||
|
||||
It connects to an MQTT server then:
|
||||
- publishes "hello world" to the topic "outTopic" every two seconds
|
||||
- subscribes to the topic "inTopic", printing out any messages
|
||||
it receives. NB - it assumes the received payloads are strings not binary
|
||||
- If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
|
||||
else switch it off
|
||||
|
||||
It will reconnect to the server if the connection is lost using a blocking
|
||||
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
|
||||
achieve the same result without blocking the main loop.
|
||||
|
||||
To install the ESP8266 board, (using Arduino 1.6.4+):
|
||||
- Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
|
||||
http://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
- Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
|
||||
- Select your ESP8266 in "Tools -> Board"
|
||||
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
@ -29,9 +34,8 @@ const char* mqtt_server = "broker.mqtt-dashboard.com";
|
||||
|
||||
WiFiClient espClient;
|
||||
PubSubClient client(espClient);
|
||||
unsigned long lastMsg = 0;
|
||||
#define MSG_BUFFER_SIZE (50)
|
||||
char msg[MSG_BUFFER_SIZE];
|
||||
long lastMsg = 0;
|
||||
char msg[50];
|
||||
int value = 0;
|
||||
|
||||
void setup_wifi() {
|
||||
@ -42,7 +46,6 @@ void setup_wifi() {
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
@ -117,11 +120,11 @@ void loop() {
|
||||
}
|
||||
client.loop();
|
||||
|
||||
unsigned long now = millis();
|
||||
long now = millis();
|
||||
if (now - lastMsg > 2000) {
|
||||
lastMsg = now;
|
||||
++value;
|
||||
snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value);
|
||||
snprintf (msg, 50, "hello world #%ld", value);
|
||||
Serial.print("Publish message: ");
|
||||
Serial.println(msg);
|
||||
client.publish("outTopic", msg);
|
||||
|
@ -27,9 +27,6 @@ setServer KEYWORD2
|
||||
setCallback KEYWORD2
|
||||
setClient KEYWORD2
|
||||
setStream KEYWORD2
|
||||
setKeepAlive KEYWORD2
|
||||
setBufferSize KEYWORD2
|
||||
setSocketTimeout KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
@ -6,13 +6,12 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/knolleary/pubsubclient.git"
|
||||
},
|
||||
"version": "2.8",
|
||||
"version": "2.6",
|
||||
"exclude": "tests",
|
||||
"examples": "examples/*/*.ino",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
"espressif"
|
||||
]
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=PubSubClient
|
||||
version=2.8
|
||||
version=2.6
|
||||
author=Nick O'Leary <nick.oleary@gmail.com>
|
||||
maintainer=Nick O'Leary <nick.oleary@gmail.com>
|
||||
sentence=A client library for MQTT messaging.
|
||||
|
@ -1,5 +1,4 @@
|
||||
/*
|
||||
|
||||
PubSubClient.cpp - A simple client for MQTT.
|
||||
Nick O'Leary
|
||||
http://knolleary.net
|
||||
@ -13,20 +12,12 @@ PubSubClient::PubSubClient() {
|
||||
this->_client = NULL;
|
||||
this->stream = NULL;
|
||||
setCallback(NULL);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
|
||||
@ -34,20 +25,12 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
|
||||
setServer(addr, port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
@ -55,10 +38,6 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
@ -66,10 +45,6 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) {
|
||||
@ -77,20 +52,12 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) {
|
||||
setServer(ip, port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
@ -98,10 +65,6 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE,
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
@ -109,10 +72,6 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE,
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) {
|
||||
@ -120,20 +79,12 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) {
|
||||
setServer(domain,port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
@ -141,10 +92,6 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
@ -152,47 +99,29 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
this->bufferSize = 0;
|
||||
setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
setKeepAlive(MQTT_KEEPALIVE);
|
||||
setSocketTimeout(MQTT_SOCKET_TIMEOUT);
|
||||
}
|
||||
|
||||
PubSubClient::~PubSubClient() {
|
||||
free(this->buffer);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id) {
|
||||
return connect(id,NULL,NULL,0,0,0,0,1);
|
||||
return connect(id,NULL,NULL,0,0,0,0);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass) {
|
||||
return connect(id,user,pass,0,0,0,0,1);
|
||||
return connect(id,user,pass,0,0,0,0);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
|
||||
return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1);
|
||||
return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
|
||||
return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession) {
|
||||
if (!connected()) {
|
||||
int result = 0;
|
||||
|
||||
|
||||
if(_client->connected()) {
|
||||
result = 1;
|
||||
if (domain != NULL) {
|
||||
result = _client->connect(this->domain, this->port);
|
||||
} else {
|
||||
if (domain != NULL) {
|
||||
result = _client->connect(this->domain, this->port);
|
||||
} else {
|
||||
result = _client->connect(this->ip, this->port);
|
||||
}
|
||||
result = _client->connect(this->ip, this->port);
|
||||
}
|
||||
|
||||
if (result == 1) {
|
||||
nextMsgId = 1;
|
||||
// Leave room in the buffer for header and variable length field
|
||||
@ -207,17 +136,14 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
|
||||
#define MQTT_HEADER_VERSION_LENGTH 7
|
||||
#endif
|
||||
for (j = 0;j<MQTT_HEADER_VERSION_LENGTH;j++) {
|
||||
this->buffer[length++] = d[j];
|
||||
buffer[length++] = d[j];
|
||||
}
|
||||
|
||||
uint8_t v;
|
||||
if (willTopic) {
|
||||
v = 0x04|(willQos<<3)|(willRetain<<5);
|
||||
v = 0x06|(willQos<<3)|(willRetain<<5);
|
||||
} else {
|
||||
v = 0x00;
|
||||
}
|
||||
if (cleanSession) {
|
||||
v = v|0x02;
|
||||
v = 0x02;
|
||||
}
|
||||
|
||||
if(user != NULL) {
|
||||
@ -227,43 +153,38 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
|
||||
v = v|(0x80>>1);
|
||||
}
|
||||
}
|
||||
this->buffer[length++] = v;
|
||||
|
||||
this->buffer[length++] = ((this->keepAlive) >> 8);
|
||||
this->buffer[length++] = ((this->keepAlive) & 0xFF);
|
||||
buffer[length++] = v;
|
||||
|
||||
CHECK_STRING_LENGTH(length,id)
|
||||
length = writeString(id,this->buffer,length);
|
||||
buffer[length++] = ((MQTT_KEEPALIVE) >> 8);
|
||||
buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF);
|
||||
length = writeString(id,buffer,length);
|
||||
if (willTopic) {
|
||||
CHECK_STRING_LENGTH(length,willTopic)
|
||||
length = writeString(willTopic,this->buffer,length);
|
||||
CHECK_STRING_LENGTH(length,willMessage)
|
||||
length = writeString(willMessage,this->buffer,length);
|
||||
length = writeString(willTopic,buffer,length);
|
||||
length = writeString(willMessage,buffer,length);
|
||||
}
|
||||
|
||||
if(user != NULL) {
|
||||
CHECK_STRING_LENGTH(length,user)
|
||||
length = writeString(user,this->buffer,length);
|
||||
length = writeString(user,buffer,length);
|
||||
if(pass != NULL) {
|
||||
CHECK_STRING_LENGTH(length,pass)
|
||||
length = writeString(pass,this->buffer,length);
|
||||
length = writeString(pass,buffer,length);
|
||||
}
|
||||
}
|
||||
|
||||
write(MQTTCONNECT,this->buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
write(MQTTCONNECT,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
|
||||
lastInActivity = lastOutActivity = millis();
|
||||
|
||||
while (!_client->available()) {
|
||||
unsigned long t = millis();
|
||||
if (t-lastInActivity >= ((int32_t) this->socketTimeout*1000UL)) {
|
||||
if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) {
|
||||
_state = MQTT_CONNECTION_TIMEOUT;
|
||||
_client->stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint8_t llen;
|
||||
uint32_t len = readPacket(&llen);
|
||||
uint16_t len = readPacket(&llen);
|
||||
|
||||
if (len == 4) {
|
||||
if (buffer[3] == 0) {
|
||||
@ -288,9 +209,8 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
|
||||
boolean PubSubClient::readByte(uint8_t * result) {
|
||||
uint32_t previousMillis = millis();
|
||||
while(!_client->available()) {
|
||||
yield();
|
||||
uint32_t currentMillis = millis();
|
||||
if(currentMillis - previousMillis >= ((int32_t) this->socketTimeout * 1000)){
|
||||
if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -309,76 +229,74 @@ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
||||
uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
||||
uint16_t len = 0;
|
||||
if(!readByte(this->buffer, &len)) return 0;
|
||||
bool isPublish = (this->buffer[0]&0xF0) == MQTTPUBLISH;
|
||||
if(!readByte(buffer, &len)) return 0;
|
||||
bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
|
||||
uint32_t multiplier = 1;
|
||||
uint32_t length = 0;
|
||||
uint16_t length = 0;
|
||||
uint8_t digit = 0;
|
||||
uint16_t skip = 0;
|
||||
uint32_t start = 0;
|
||||
uint8_t start = 0;
|
||||
|
||||
do {
|
||||
if (len == 5) {
|
||||
if (len == 6) {
|
||||
// Invalid remaining length encoding - kill the connection
|
||||
_state = MQTT_DISCONNECTED;
|
||||
_client->stop();
|
||||
return 0;
|
||||
}
|
||||
if(!readByte(&digit)) return 0;
|
||||
this->buffer[len++] = digit;
|
||||
buffer[len++] = digit;
|
||||
length += (digit & 127) * multiplier;
|
||||
multiplier <<=7; //multiplier *= 128
|
||||
multiplier *= 128;
|
||||
} while ((digit & 128) != 0);
|
||||
*lengthLength = len-1;
|
||||
|
||||
if (isPublish) {
|
||||
// Read in topic length to calculate bytes to skip over for Stream writing
|
||||
if(!readByte(this->buffer, &len)) return 0;
|
||||
if(!readByte(this->buffer, &len)) return 0;
|
||||
skip = (this->buffer[*lengthLength+1]<<8)+this->buffer[*lengthLength+2];
|
||||
if(!readByte(buffer, &len)) return 0;
|
||||
if(!readByte(buffer, &len)) return 0;
|
||||
skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
|
||||
start = 2;
|
||||
if (this->buffer[0]&MQTTQOS1) {
|
||||
if (buffer[0]&MQTTQOS1) {
|
||||
// skip message id
|
||||
skip += 2;
|
||||
}
|
||||
}
|
||||
uint32_t idx = len;
|
||||
|
||||
for (uint32_t i = start;i<length;i++) {
|
||||
for (uint16_t i = start;i<length;i++) {
|
||||
if(!readByte(&digit)) return 0;
|
||||
if (this->stream) {
|
||||
if (isPublish && idx-*lengthLength-2>skip) {
|
||||
if (isPublish && len-*lengthLength-2>skip) {
|
||||
this->stream->write(digit);
|
||||
}
|
||||
}
|
||||
|
||||
if (len < this->bufferSize) {
|
||||
this->buffer[len] = digit;
|
||||
len++;
|
||||
if (len < MQTT_MAX_PACKET_SIZE) {
|
||||
buffer[len] = digit;
|
||||
}
|
||||
idx++;
|
||||
len++;
|
||||
}
|
||||
|
||||
if (!this->stream && idx > this->bufferSize) {
|
||||
if (!this->stream && len > MQTT_MAX_PACKET_SIZE) {
|
||||
len = 0; // This will cause the packet to be ignored.
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
boolean PubSubClient::loop() {
|
||||
if (connected()) {
|
||||
unsigned long t = millis();
|
||||
if ((t - lastInActivity > this->keepAlive*1000UL) || (t - lastOutActivity > this->keepAlive*1000UL)) {
|
||||
if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
|
||||
if (pingOutstanding) {
|
||||
this->_state = MQTT_CONNECTION_TIMEOUT;
|
||||
_client->stop();
|
||||
return false;
|
||||
} else {
|
||||
this->buffer[0] = MQTTPINGREQ;
|
||||
this->buffer[1] = 0;
|
||||
_client->write(this->buffer,2);
|
||||
buffer[0] = MQTTPINGREQ;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
lastOutActivity = t;
|
||||
lastInActivity = t;
|
||||
pingOutstanding = true;
|
||||
@ -391,35 +309,35 @@ boolean PubSubClient::loop() {
|
||||
uint8_t *payload;
|
||||
if (len > 0) {
|
||||
lastInActivity = t;
|
||||
uint8_t type = this->buffer[0]&0xF0;
|
||||
uint8_t type = buffer[0]&0xF0;
|
||||
if (type == MQTTPUBLISH) {
|
||||
if (callback) {
|
||||
uint16_t tl = (this->buffer[llen+1]<<8)+this->buffer[llen+2]; /* topic length in bytes */
|
||||
memmove(this->buffer+llen+2,this->buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */
|
||||
this->buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */
|
||||
char *topic = (char*) this->buffer+llen+2;
|
||||
uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */
|
||||
memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */
|
||||
buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */
|
||||
char *topic = (char*) buffer+llen+2;
|
||||
// msgId only present for QOS>0
|
||||
if ((this->buffer[0]&0x06) == MQTTQOS1) {
|
||||
msgId = (this->buffer[llen+3+tl]<<8)+this->buffer[llen+3+tl+1];
|
||||
payload = this->buffer+llen+3+tl+2;
|
||||
if ((buffer[0]&0x06) == MQTTQOS1) {
|
||||
msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1];
|
||||
payload = buffer+llen+3+tl+2;
|
||||
callback(topic,payload,len-llen-3-tl-2);
|
||||
|
||||
this->buffer[0] = MQTTPUBACK;
|
||||
this->buffer[1] = 2;
|
||||
this->buffer[2] = (msgId >> 8);
|
||||
this->buffer[3] = (msgId & 0xFF);
|
||||
_client->write(this->buffer,4);
|
||||
buffer[0] = MQTTPUBACK;
|
||||
buffer[1] = 2;
|
||||
buffer[2] = (msgId >> 8);
|
||||
buffer[3] = (msgId & 0xFF);
|
||||
_client->write(buffer,4);
|
||||
lastOutActivity = t;
|
||||
|
||||
} else {
|
||||
payload = this->buffer+llen+3+tl;
|
||||
payload = buffer+llen+3+tl;
|
||||
callback(topic,payload,len-llen-3-tl);
|
||||
}
|
||||
}
|
||||
} else if (type == MQTTPINGREQ) {
|
||||
this->buffer[0] = MQTTPINGRESP;
|
||||
this->buffer[1] = 0;
|
||||
_client->write(this->buffer,2);
|
||||
buffer[0] = MQTTPINGRESP;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
} else if (type == MQTTPINGRESP) {
|
||||
pingOutstanding = false;
|
||||
}
|
||||
@ -434,11 +352,11 @@ boolean PubSubClient::loop() {
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload) {
|
||||
return publish(topic,(const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0,false);
|
||||
return publish(topic,(const uint8_t*)payload,strlen(payload),false);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) {
|
||||
return publish(topic,(const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0,retained);
|
||||
return publish(topic,(const uint8_t*)payload,strlen(payload),retained);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) {
|
||||
@ -447,34 +365,26 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
|
||||
if (connected()) {
|
||||
if (this->bufferSize < MQTT_MAX_HEADER_SIZE + 2+strnlen(topic, this->bufferSize) + plength) {
|
||||
if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) {
|
||||
// Too long
|
||||
return false;
|
||||
}
|
||||
// Leave room in the buffer for header and variable length field
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
length = writeString(topic,this->buffer,length);
|
||||
|
||||
// Add payload
|
||||
length = writeString(topic,buffer,length);
|
||||
uint16_t i;
|
||||
for (i=0;i<plength;i++) {
|
||||
this->buffer[length++] = payload[i];
|
||||
buffer[length++] = payload[i];
|
||||
}
|
||||
|
||||
// Write the header
|
||||
uint8_t header = MQTTPUBLISH;
|
||||
if (retained) {
|
||||
header |= 1;
|
||||
}
|
||||
return write(header,this->buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
return write(header,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish_P(const char* topic, const char* payload, boolean retained) {
|
||||
return publish_P(topic, (const uint8_t*)payload, payload ? strnlen(payload, this->bufferSize) : 0, retained);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
|
||||
uint8_t llen = 0;
|
||||
uint8_t digit;
|
||||
@ -484,33 +394,32 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
|
||||
unsigned int i;
|
||||
uint8_t header;
|
||||
unsigned int len;
|
||||
int expectedLength;
|
||||
|
||||
if (!connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tlen = strnlen(topic, this->bufferSize);
|
||||
tlen = strlen(topic);
|
||||
|
||||
header = MQTTPUBLISH;
|
||||
if (retained) {
|
||||
header |= 1;
|
||||
}
|
||||
this->buffer[pos++] = header;
|
||||
buffer[pos++] = header;
|
||||
len = plength + 2 + tlen;
|
||||
do {
|
||||
digit = len & 127; //digit = len %128
|
||||
len >>= 7; //len = len / 128
|
||||
digit = len % 128;
|
||||
len = len / 128;
|
||||
if (len > 0) {
|
||||
digit |= 0x80;
|
||||
}
|
||||
this->buffer[pos++] = digit;
|
||||
buffer[pos++] = digit;
|
||||
llen++;
|
||||
} while(len>0);
|
||||
|
||||
pos = writeString(topic,this->buffer,pos);
|
||||
pos = writeString(topic,buffer,pos);
|
||||
|
||||
rc += _client->write(this->buffer,pos);
|
||||
rc += _client->write(buffer,pos);
|
||||
|
||||
for (i=0;i<plength;i++) {
|
||||
rc += _client->write((char)pgm_read_byte_near(payload + i));
|
||||
@ -518,22 +427,21 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
|
||||
|
||||
lastOutActivity = millis();
|
||||
|
||||
expectedLength = 1 + llen + 2 + tlen + plength;
|
||||
|
||||
return (rc == expectedLength);
|
||||
return rc == tlen + 4 + plength;
|
||||
}
|
||||
|
||||
boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, boolean retained) {
|
||||
if (connected()) {
|
||||
// Send the header and variable length field
|
||||
uint16_t length = MQTT_MAX_HEADER_SIZE;
|
||||
length = writeString(topic,this->buffer,length);
|
||||
length = writeString(topic,buffer,length);
|
||||
uint16_t i;
|
||||
uint8_t header = MQTTPUBLISH;
|
||||
if (retained) {
|
||||
header |= 1;
|
||||
}
|
||||
size_t hlen = buildHeader(header, this->buffer, plength+length-MQTT_MAX_HEADER_SIZE);
|
||||
uint16_t rc = _client->write(this->buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen));
|
||||
size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE);
|
||||
uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen));
|
||||
lastOutActivity = millis();
|
||||
return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen)));
|
||||
}
|
||||
@ -561,9 +469,8 @@ size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length)
|
||||
uint8_t pos = 0;
|
||||
uint16_t len = length;
|
||||
do {
|
||||
|
||||
digit = len & 127; //digit = len %128
|
||||
len >>= 7; //len = len / 128
|
||||
digit = len % 128;
|
||||
len = len / 128;
|
||||
if (len > 0) {
|
||||
digit |= 0x80;
|
||||
}
|
||||
@ -607,14 +514,10 @@ boolean PubSubClient::subscribe(const char* topic) {
|
||||
}
|
||||
|
||||
boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
|
||||
size_t topicLength = strnlen(topic, this->bufferSize);
|
||||
if (topic == 0) {
|
||||
return false;
|
||||
}
|
||||
if (qos > 1) {
|
||||
return false;
|
||||
}
|
||||
if (this->bufferSize < 9 + topicLength) {
|
||||
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
|
||||
// Too long
|
||||
return false;
|
||||
}
|
||||
@ -625,21 +528,17 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
|
||||
if (nextMsgId == 0) {
|
||||
nextMsgId = 1;
|
||||
}
|
||||
this->buffer[length++] = (nextMsgId >> 8);
|
||||
this->buffer[length++] = (nextMsgId & 0xFF);
|
||||
length = writeString((char*)topic, this->buffer,length);
|
||||
this->buffer[length++] = qos;
|
||||
return write(MQTTSUBSCRIBE|MQTTQOS1,this->buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
buffer[length++] = (nextMsgId >> 8);
|
||||
buffer[length++] = (nextMsgId & 0xFF);
|
||||
length = writeString((char*)topic, buffer,length);
|
||||
buffer[length++] = qos;
|
||||
return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::unsubscribe(const char* topic) {
|
||||
size_t topicLength = strnlen(topic, this->bufferSize);
|
||||
if (topic == 0) {
|
||||
return false;
|
||||
}
|
||||
if (this->bufferSize < 9 + topicLength) {
|
||||
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
|
||||
// Too long
|
||||
return false;
|
||||
}
|
||||
@ -649,18 +548,18 @@ boolean PubSubClient::unsubscribe(const char* topic) {
|
||||
if (nextMsgId == 0) {
|
||||
nextMsgId = 1;
|
||||
}
|
||||
this->buffer[length++] = (nextMsgId >> 8);
|
||||
this->buffer[length++] = (nextMsgId & 0xFF);
|
||||
length = writeString(topic, this->buffer,length);
|
||||
return write(MQTTUNSUBSCRIBE|MQTTQOS1,this->buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
buffer[length++] = (nextMsgId >> 8);
|
||||
buffer[length++] = (nextMsgId & 0xFF);
|
||||
length = writeString(topic, buffer,length);
|
||||
return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PubSubClient::disconnect() {
|
||||
this->buffer[0] = MQTTDISCONNECT;
|
||||
this->buffer[1] = 0;
|
||||
_client->write(this->buffer,2);
|
||||
buffer[0] = MQTTDISCONNECT;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
_state = MQTT_DISCONNECTED;
|
||||
_client->flush();
|
||||
_client->stop();
|
||||
@ -693,8 +592,6 @@ boolean PubSubClient::connected() {
|
||||
_client->flush();
|
||||
_client->stop();
|
||||
}
|
||||
} else {
|
||||
return this->_state == MQTT_CONNECTED;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@ -736,34 +633,3 @@ PubSubClient& PubSubClient::setStream(Stream& stream){
|
||||
int PubSubClient::state() {
|
||||
return this->_state;
|
||||
}
|
||||
|
||||
boolean PubSubClient::setBufferSize(uint16_t size) {
|
||||
if (size == 0) {
|
||||
// Cannot set it back to 0
|
||||
return false;
|
||||
}
|
||||
if (this->bufferSize == 0) {
|
||||
this->buffer = (uint8_t*)malloc(size);
|
||||
} else {
|
||||
uint8_t* newBuffer = (uint8_t*)realloc(this->buffer, size);
|
||||
if (newBuffer != NULL) {
|
||||
this->buffer = newBuffer;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this->bufferSize = size;
|
||||
return (this->buffer != NULL);
|
||||
}
|
||||
|
||||
uint16_t PubSubClient::getBufferSize() {
|
||||
return this->bufferSize;
|
||||
}
|
||||
PubSubClient& PubSubClient::setKeepAlive(uint16_t keepAlive) {
|
||||
this->keepAlive = keepAlive;
|
||||
return *this;
|
||||
}
|
||||
PubSubClient& PubSubClient::setSocketTimeout(uint16_t timeout) {
|
||||
this->socketTimeout = timeout;
|
||||
return *this;
|
||||
}
|
||||
|
@ -21,17 +21,17 @@
|
||||
#define MQTT_VERSION MQTT_VERSION_3_1_1
|
||||
#endif
|
||||
|
||||
// MQTT_MAX_PACKET_SIZE : Maximum packet size. Override with setBufferSize().
|
||||
// MQTT_MAX_PACKET_SIZE : Maximum packet size
|
||||
#ifndef MQTT_MAX_PACKET_SIZE
|
||||
#define MQTT_MAX_PACKET_SIZE 256
|
||||
#define MQTT_MAX_PACKET_SIZE 128
|
||||
#endif
|
||||
|
||||
// MQTT_KEEPALIVE : keepAlive interval in Seconds. Override with setKeepAlive()
|
||||
// MQTT_KEEPALIVE : keepAlive interval in Seconds
|
||||
#ifndef MQTT_KEEPALIVE
|
||||
#define MQTT_KEEPALIVE 15
|
||||
#endif
|
||||
|
||||
// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds. Override with setSocketTimeout()
|
||||
// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds
|
||||
#ifndef MQTT_SOCKET_TIMEOUT
|
||||
#define MQTT_SOCKET_TIMEOUT 15
|
||||
#endif
|
||||
@ -76,28 +76,23 @@
|
||||
// Maximum size of fixed header and variable length size header
|
||||
#define MQTT_MAX_HEADER_SIZE 5
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
#ifdef ESP8266
|
||||
#include <functional>
|
||||
#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
|
||||
#else
|
||||
#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int)
|
||||
#endif
|
||||
|
||||
#define CHECK_STRING_LENGTH(l,s) if (l+2+strnlen(s, this->bufferSize) > this->bufferSize) {_client->stop();return false;}
|
||||
|
||||
class PubSubClient : public Print {
|
||||
private:
|
||||
Client* _client;
|
||||
uint8_t* buffer;
|
||||
uint16_t bufferSize;
|
||||
uint16_t keepAlive;
|
||||
uint16_t socketTimeout;
|
||||
uint8_t buffer[MQTT_MAX_PACKET_SIZE];
|
||||
uint16_t nextMsgId;
|
||||
unsigned long lastOutActivity;
|
||||
unsigned long lastInActivity;
|
||||
bool pingOutstanding;
|
||||
MQTT_CALLBACK_SIGNATURE;
|
||||
uint32_t readPacket(uint8_t*);
|
||||
uint16_t readPacket(uint8_t*);
|
||||
boolean readByte(uint8_t * result);
|
||||
boolean readByte(uint8_t * result, uint16_t * index);
|
||||
boolean write(uint8_t header, uint8_t* buf, uint16_t length);
|
||||
@ -128,31 +123,22 @@ public:
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
|
||||
|
||||
~PubSubClient();
|
||||
|
||||
PubSubClient& setServer(IPAddress ip, uint16_t port);
|
||||
PubSubClient& setServer(uint8_t * ip, uint16_t port);
|
||||
PubSubClient& setServer(const char * domain, uint16_t port);
|
||||
PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE);
|
||||
PubSubClient& setClient(Client& client);
|
||||
PubSubClient& setStream(Stream& stream);
|
||||
PubSubClient& setKeepAlive(uint16_t keepAlive);
|
||||
PubSubClient& setSocketTimeout(uint16_t timeout);
|
||||
|
||||
boolean setBufferSize(uint16_t size);
|
||||
uint16_t getBufferSize();
|
||||
|
||||
boolean connect(const char* id);
|
||||
boolean connect(const char* id, const char* user, const char* pass);
|
||||
boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
|
||||
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
|
||||
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession);
|
||||
void disconnect();
|
||||
boolean publish(const char* topic, const char* payload);
|
||||
boolean publish(const char* topic, const char* payload, boolean retained);
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength);
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
|
||||
boolean publish_P(const char* topic, const char* payload, boolean retained);
|
||||
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained);
|
||||
// Start to publish a message.
|
||||
// This API:
|
||||
@ -177,7 +163,6 @@ public:
|
||||
boolean loop();
|
||||
boolean connected();
|
||||
int state();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -98,33 +98,6 @@ int test_connect_fails_on_bad_rc() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_connect_non_clean_session() {
|
||||
IT("sends a properly formatted non-clean session connect packet and succeeds");
|
||||
ShimClient shimClient;
|
||||
|
||||
shimClient.setAllowConnect(true);
|
||||
byte expectServer[] = { 172, 16, 0, 2 };
|
||||
shimClient.expectConnect(expectServer,1883);
|
||||
byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x0,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31};
|
||||
byte connack[] = { 0x20, 0x02, 0x00, 0x00 };
|
||||
|
||||
shimClient.expect(connect,26);
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
int state = client.state();
|
||||
IS_TRUE(state == MQTT_DISCONNECTED);
|
||||
|
||||
int rc = client.connect((char*)"client_test1",0,0,0,0,0,0,0);
|
||||
IS_TRUE(rc);
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
state = client.state();
|
||||
IS_TRUE(state == MQTT_CONNECTED);
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_connect_accepts_username_password() {
|
||||
IT("accepts a username and password");
|
||||
ShimClient shimClient;
|
||||
@ -280,47 +253,13 @@ int test_connect_disconnect_connect() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_connect_custom_keepalive() {
|
||||
IT("sends a properly formatted connect packet with custom keepalive value");
|
||||
ShimClient shimClient;
|
||||
|
||||
shimClient.setAllowConnect(true);
|
||||
byte expectServer[] = { 172, 16, 0, 2 };
|
||||
shimClient.expectConnect(expectServer,1883);
|
||||
|
||||
// Set keepalive to 300secs == 0x01 0x2c
|
||||
byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x01,0x2c,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31};
|
||||
byte connack[] = { 0x20, 0x02, 0x00, 0x00 };
|
||||
|
||||
shimClient.expect(connect,26);
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
int state = client.state();
|
||||
IS_TRUE(state == MQTT_DISCONNECTED);
|
||||
|
||||
client.setKeepAlive(300);
|
||||
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
state = client.state();
|
||||
IS_TRUE(state == MQTT_CONNECTED);
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
SUITE("Connect");
|
||||
|
||||
test_connect_fails_no_network();
|
||||
test_connect_fails_on_no_response();
|
||||
|
||||
test_connect_properly_formatted();
|
||||
test_connect_non_clean_session();
|
||||
test_connect_accepts_username_password();
|
||||
test_connect_fails_on_bad_rc();
|
||||
test_connect_properly_formatted_hostname();
|
||||
@ -330,7 +269,5 @@ int main()
|
||||
test_connect_with_will();
|
||||
test_connect_with_will_username_password();
|
||||
test_connect_disconnect_connect();
|
||||
|
||||
test_connect_custom_keepalive();
|
||||
FINISH
|
||||
}
|
||||
|
@ -21,6 +21,4 @@ extern "C"{
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte_near(x) *(x)
|
||||
|
||||
#define yield(x) {}
|
||||
|
||||
#endif // Arduino_h
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
class Buffer {
|
||||
private:
|
||||
uint8_t buffer[2048];
|
||||
uint8_t buffer[1024];
|
||||
uint16_t pos;
|
||||
uint16_t length;
|
||||
|
||||
|
@ -134,7 +134,6 @@ int test_publish_too_long() {
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
client.setBufferSize(128);
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
|
@ -20,7 +20,6 @@ void reset_callback() {
|
||||
}
|
||||
|
||||
void callback(char* topic, byte* payload, unsigned int length) {
|
||||
TRACE("Callback received topic=[" << topic << "] length=" << length << "\n")
|
||||
callback_called = true;
|
||||
strcpy(lastTopic,topic);
|
||||
memcpy(lastPayload,payload,length);
|
||||
@ -103,15 +102,10 @@ int test_receive_max_sized_message() {
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
int length = 80; // If this is changed to > 128 then the publish packet below
|
||||
// is no longer valid as it assumes the remaining length
|
||||
// is a single-byte. Don't make that mistake like I just
|
||||
// did and lose a whole evening tracking down the issue.
|
||||
client.setBufferSize(length);
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
|
||||
int length = MQTT_MAX_PACKET_SIZE;
|
||||
byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64};
|
||||
byte bigPublish[length];
|
||||
memset(bigPublish,'A',length);
|
||||
@ -143,13 +137,11 @@ int test_receive_oversized_message() {
|
||||
byte connack[] = { 0x20, 0x02, 0x00, 0x00 };
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
int length = 80; // See comment in test_receive_max_sized_message before changing this value
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
client.setBufferSize(length-1);
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
int length = MQTT_MAX_PACKET_SIZE+1;
|
||||
byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64};
|
||||
byte bigPublish[length];
|
||||
memset(bigPublish,'A',length);
|
||||
@ -182,8 +174,8 @@ int test_drop_invalid_remaining_length_message() {
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x30,0x92,0x92,0x92,0x92,0x01,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64};
|
||||
shimClient.respond(publish,20);
|
||||
byte publish[] = {0x30,0x92,0x92,0x92,0x92,0x92,0x92,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64};
|
||||
shimClient.respond(publish,21);
|
||||
|
||||
rc = client.loop();
|
||||
|
||||
@ -196,58 +188,9 @@ int test_drop_invalid_remaining_length_message() {
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_resize_buffer() {
|
||||
IT("receives a message larger than the default maximum");
|
||||
reset_callback();
|
||||
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connack[] = { 0x20, 0x02, 0x00, 0x00 };
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
int length = 80; // See comment in test_receive_max_sized_message before changing this value
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
client.setBufferSize(length-1);
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64};
|
||||
byte bigPublish[length];
|
||||
memset(bigPublish,'A',length);
|
||||
bigPublish[length] = 'B';
|
||||
memcpy(bigPublish,publish,16);
|
||||
// Send it twice
|
||||
shimClient.respond(bigPublish,length);
|
||||
shimClient.respond(bigPublish,length);
|
||||
|
||||
rc = client.loop();
|
||||
IS_TRUE(rc);
|
||||
|
||||
// First message fails as it is too big
|
||||
IS_FALSE(callback_called);
|
||||
|
||||
// Resize the buffer
|
||||
client.setBufferSize(length);
|
||||
|
||||
rc = client.loop();
|
||||
IS_TRUE(rc);
|
||||
|
||||
IS_TRUE(callback_called);
|
||||
|
||||
IS_TRUE(strcmp(lastTopic,"topic")==0);
|
||||
IS_TRUE(lastLength == length-9);
|
||||
IS_TRUE(memcmp(lastPayload,bigPublish+9,lastLength)==0);
|
||||
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
|
||||
int test_receive_oversized_stream_message() {
|
||||
IT("receive an oversized streamed message");
|
||||
IT("drops an oversized message");
|
||||
reset_callback();
|
||||
|
||||
Stream stream;
|
||||
@ -258,13 +201,11 @@ int test_receive_oversized_stream_message() {
|
||||
byte connack[] = { 0x20, 0x02, 0x00, 0x00 };
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
int length = 80; // See comment in test_receive_max_sized_message before changing this value
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient, stream);
|
||||
client.setBufferSize(length-1);
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
int length = MQTT_MAX_PACKET_SIZE+1;
|
||||
byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64};
|
||||
|
||||
byte bigPublish[length];
|
||||
@ -281,8 +222,7 @@ int test_receive_oversized_stream_message() {
|
||||
|
||||
IS_TRUE(callback_called);
|
||||
IS_TRUE(strcmp(lastTopic,"topic")==0);
|
||||
|
||||
IS_TRUE(lastLength == length-10);
|
||||
IS_TRUE(lastLength == length-9);
|
||||
|
||||
IS_FALSE(stream.error());
|
||||
IS_FALSE(shimClient.error());
|
||||
@ -332,7 +272,6 @@ int main()
|
||||
test_receive_max_sized_message();
|
||||
test_drop_invalid_remaining_length_message();
|
||||
test_receive_oversized_message();
|
||||
test_resize_buffer();
|
||||
test_receive_oversized_stream_message();
|
||||
test_receive_qos1();
|
||||
|
||||
|
@ -106,7 +106,6 @@ int test_subscribe_too_long() {
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
client.setBufferSize(128);
|
||||
int rc = client.connect((char*)"client_test1");
|
||||
IS_TRUE(rc);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user