addd ssd1306 lib
This commit is contained in:
7
P1_gateway_FW/lib/MQTT/.editorconfig
Normal file
7
P1_gateway_FW/lib/MQTT/.editorconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[src/*.h,src/*.cpp,examples/**.ino]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
2
P1_gateway_FW/lib/MQTT/.gitignore
vendored
Normal file
2
P1_gateway_FW/lib/MQTT/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
cmake-build-debug/
|
||||
1
P1_gateway_FW/lib/MQTT/.piopm
Normal file
1
P1_gateway_FW/lib/MQTT/.piopm
Normal file
@@ -0,0 +1 @@
|
||||
{"type": "library", "name": "MQTT", "version": "2.4.8", "spec": {"owner": "256dpi", "id": 617, "name": "MQTT", "requirements": null, "url": null}}
|
||||
46
P1_gateway_FW/lib/MQTT/.travis.yml
Normal file
46
P1_gateway_FW/lib/MQTT/.travis.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
language: generic
|
||||
env:
|
||||
global:
|
||||
- IDE_VERSION=1.8.7
|
||||
matrix:
|
||||
- EXAMPLE="AdafruitHuzzahESP8266" BOARD="esp8266:esp8266:huzzah:eesz=4M3M,xtal=80"
|
||||
- EXAMPLE="AdafruitHuzzahESP8266Secure" BOARD="esp8266:esp8266:huzzah:eesz=4M3M,xtal=80"
|
||||
- EXAMPLE="ArduinoEthernetShield" BOARD="arduino:avr:uno"
|
||||
- EXAMPLE="ArduinoMKRGSM1400" BOARD="arduino:samd:mkrgsm1400"
|
||||
- EXAMPLE="ArduinoMKRGSM1400Secure" BOARD="arduino:samd:mkrgsm1400"
|
||||
- EXAMPLE="ArduinoWiFi101Secure" BOARD="arduino:avr:uno"
|
||||
- EXAMPLE="ArduinoWiFiShield" BOARD="arduino:avr:uno"
|
||||
- EXAMPLE="ArduinoYun" BOARD="arduino:avr:yun"
|
||||
- EXAMPLE="ArduinoYunSecure" BOARD="arduino:avr:yun"
|
||||
- EXAMPLE="ESP32DevelopmentBoard" BOARD="espressif:esp32:esp32:FlashFreq=80"
|
||||
- EXAMPLE="ESP32DevelopmentBoardSecure" BOARD="espressif:esp32:esp32:FlashFreq=80"
|
||||
before_install:
|
||||
- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- mv arduino-$IDE_VERSION ~/arduino-ide
|
||||
- export PATH=$PATH:~/arduino-ide
|
||||
- if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
|
||||
arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --install-boards esp8266:esp8266;
|
||||
arduino --pref "boardsmanager.additional.urls=" --save-prefs;
|
||||
fi
|
||||
- if [[ "$BOARD" =~ "espressif:esp32:" ]]; then
|
||||
mkdir -p ~/Arduino/hardware/espressif &&
|
||||
cd ~/Arduino/hardware/espressif &&
|
||||
git clone https://github.com/espressif/arduino-esp32.git esp32 &&
|
||||
cd esp32/tools/ &&
|
||||
python get.py &&
|
||||
cd $TRAVIS_BUILD_DIR;
|
||||
fi
|
||||
- if [[ "$BOARD" =~ "arduino:samd:mkrgsm1400" ]]; then
|
||||
arduino --install-boards arduino:samd;
|
||||
arduino --install-library MKRGSM;
|
||||
fi
|
||||
- arduino --install-library WiFi101
|
||||
install:
|
||||
- mkdir -p ~/Arduino/libraries
|
||||
- ln -s $PWD ~/Arduino/libraries/.
|
||||
script:
|
||||
- arduino --verbose-build --verify --board $BOARD $PWD/examples/$EXAMPLE/$EXAMPLE.ino;
|
||||
39
P1_gateway_FW/lib/MQTT/CMakeLists.txt
Normal file
39
P1_gateway_FW/lib/MQTT/CMakeLists.txt
Normal file
@@ -0,0 +1,39 @@
|
||||
# Uncompilable CMake File to enable project editing with CLion IDE
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(arduino-mqtt)
|
||||
|
||||
include_directories(
|
||||
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino
|
||||
/Users/256dpi/Development/Arduino/libraries/Ethernet/src
|
||||
/Users/256dpi/Development/Arduino/libraries/WiFi101/src
|
||||
/Users/256dpi/Development/Arduino/libraries/MKRGSM/src
|
||||
/Applications/Arduino.app/Contents/Java/libraries/Bridge/src
|
||||
/Users/256dpi/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/ESP8266WiFi/src
|
||||
/Users/256dpi/Library/Arduino15/packages/esp32/libraries/WiFi/src
|
||||
/Users/256dpi/Library/Arduino15/packages/esp32/libraries/WiFiClientSecure/src
|
||||
src)
|
||||
|
||||
include_directories(src/)
|
||||
|
||||
set(CMAKE_CXX_FLAGS -std=c++11)
|
||||
|
||||
set(SOURCE_FILES
|
||||
examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino
|
||||
examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino
|
||||
examples/ArduinoEthernetShield/ArduinoEthernetShield.ino
|
||||
examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino
|
||||
examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino
|
||||
examples/ArduinoWiFi101/ArduinoWiFi101.ino
|
||||
examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino
|
||||
examples/ArduinoWiFiShield/ArduinoWiFiShield.ino
|
||||
examples/ArduinoYun/ArduinoYun.ino
|
||||
examples/ArduinoYunSecure/ArduinoYunSecure.ino
|
||||
examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino
|
||||
examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino
|
||||
src/lwmqtt
|
||||
src/MQTT.h
|
||||
src/MQTTClient.h
|
||||
src/MQTTClient.cpp)
|
||||
|
||||
add_executable(arduino-mqtt ${SOURCE_FILES})
|
||||
21
P1_gateway_FW/lib/MQTT/LICENSE.md
Normal file
21
P1_gateway_FW/lib/MQTT/LICENSE.md
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Joël Gähwiler
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
14
P1_gateway_FW/lib/MQTT/Makefile
Normal file
14
P1_gateway_FW/lib/MQTT/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
all: fmt
|
||||
|
||||
fmt:
|
||||
clang-format -i src/*.h src/*.cpp -style="{BasedOnStyle: Google, ColumnLimit: 120}"
|
||||
|
||||
update:
|
||||
rm -rf ./lwmqtt
|
||||
git clone --branch v0.6.4 https://github.com/256dpi/lwmqtt.git ./lwmqtt
|
||||
mkdir -p ./src/lwmqtt
|
||||
cp -r ./lwmqtt/src/*.c ./src/lwmqtt/
|
||||
cp -r ./lwmqtt/src/*.h ./src/lwmqtt/
|
||||
cp -r ./lwmqtt/include/*.h ./src/lwmqtt/
|
||||
rm -rf ./lwmqtt
|
||||
sed -i '' "s/<lwmqtt.h>/\"lwmqtt.h\"/g" ./src/lwmqtt/*
|
||||
260
P1_gateway_FW/lib/MQTT/README.md
Normal file
260
P1_gateway_FW/lib/MQTT/README.md
Normal file
@@ -0,0 +1,260 @@
|
||||
# arduino-mqtt
|
||||
|
||||
[](https://travis-ci.org/256dpi/arduino-mqtt)
|
||||
[](https://github.com/256dpi/arduino-mqtt/releases)
|
||||
|
||||
This library bundles the [lwmqtt](https://github.com/256dpi/lwmqtt) MQTT 3.1.1 client and adds a thin wrapper to get an Arduino like API.
|
||||
|
||||
Download the latest version from the [release](https://github.com/256dpi/arduino-mqtt/releases) section. Or even better use the builtin Library Manager in the Arduino IDE and search for "MQTT".
|
||||
|
||||
The library is also available on [PlatformIO](https://platformio.org/lib/show/617/MQTT). You can install it by running: `pio lib install "MQTT"`.
|
||||
|
||||
## Compatibility
|
||||
|
||||
The following examples show how you can use the library with various Arduino compatible hardware:
|
||||
|
||||
- [Arduino Yun & Yun-Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYun/ArduinoYun.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYunSecure/ArduinoYunSecure.ino))
|
||||
- [Arduino Ethernet Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino)
|
||||
- [Arduino WiFi Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino)
|
||||
- [Adafruit HUZZAH ESP8266](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino))
|
||||
- [Arduino/Genuino WiFi101 Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101/ArduinoWiFi101.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino))
|
||||
- [Arduino MKR GSM 1400](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino))
|
||||
- [ESP32 Development Board](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino))
|
||||
|
||||
Other shields and boards should also work if they provide a [Client](https://www.arduino.cc/en/Reference/ClientConstructor) based network implementation.
|
||||
|
||||
**Check out the [Wiki](https://github.com/256dpi/arduino-mqtt/wiki) to find more examples.**
|
||||
|
||||
## Notes
|
||||
|
||||
- The maximum size for packets being published and received is set by default to 128 bytes. To change the buffer sizes, you need to use `MQTTClient client(256)` instead of just `MQTTClient client` on the top of your sketch. The passed value denotes the read and write buffer size.
|
||||
|
||||
- On the ESP8266 it has been reported that an additional `delay(10);` after `client.loop();` fixes many stability issues with WiFi connections.
|
||||
|
||||
- To use the library with shiftr.io, you need to provide the token key (username) and token secret (password) as the second and third argument to `client.connect(name, key, secret)`.
|
||||
|
||||
## Example
|
||||
|
||||
The following example uses an Arduino MKR1000 to connect to shiftr.io. You can check on your device after a successful connection here: https://shiftr.io/try.
|
||||
|
||||
```c++
|
||||
#include <SPI.h>
|
||||
#include <WiFi101.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
Initialize the object using the hostname of the broker, the brokers port (default: `1883`) and the underlying Client class for network transport:
|
||||
|
||||
```c++
|
||||
void begin(Client &client);
|
||||
void begin(const char hostname[], Client &client);
|
||||
void begin(const char hostname[], int port, Client &client);
|
||||
void begin(IPAddress address, Client &client);
|
||||
void begin(IPAddress address, int port, Client &client);
|
||||
```
|
||||
|
||||
- Specify port `8883` when using secure clients for encrypted connections.
|
||||
- Local domain names (e.g. `Computer.local` on OSX) are not supported by Arduino. You need to set the IP address directly.
|
||||
|
||||
The hostname and port can also be changed after calling `begin()`:
|
||||
|
||||
```c++
|
||||
void setHost(const char hostname[]);
|
||||
void setHost(const char hostname[], int port);
|
||||
void setHost(IPAddress address);
|
||||
void setHost(IPAddress address, int port);
|
||||
```
|
||||
|
||||
Set a will message (last testament) that gets registered on the broker after connecting. `setWill()` has to be called before calling `connect()`:
|
||||
|
||||
```c++
|
||||
void setWill(const char topic[]);
|
||||
void setWill(const char topic[], const char payload[]);
|
||||
void setWill(const char topic[], const char payload[], bool retained, int qos);
|
||||
void clearWill();
|
||||
```
|
||||
|
||||
Register a callback to receive messages:
|
||||
|
||||
```c++
|
||||
void onMessage(MQTTClientCallbackSimple);
|
||||
// Callback signature: void messageReceived(String &topic, String &payload) {}
|
||||
|
||||
void onMessageAdvanced(MQTTClientCallbackAdvanced);
|
||||
// Callback signature: void messageReceived(MQTTClient *client, char topic[], char payload[], int payload_length) {}
|
||||
```
|
||||
|
||||
- The set callback is mostly called during a call to `loop()` but may also be called during a call to `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` if messages have been received before receiving the required acknowledgement. Therefore, it is strongly recommended to not call `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` directly in the callback.
|
||||
- In case you need a reference to an object that manages the client, use the `void * ref` property on the client to store a pointer, and access it directly from the advanced callback..
|
||||
|
||||
Set more advanced options:
|
||||
|
||||
```c++
|
||||
void setKeepAlive(int keepAlive);
|
||||
void setCleanSession(bool cleanSession);
|
||||
void setTimeout(int timeout);
|
||||
void setOptions(int keepAlive, bool cleanSession, int timeout);
|
||||
```
|
||||
|
||||
- The `keepAlive` option controls the keep alive interval in seconds (default: 10).
|
||||
- The `cleanSession` option controls the session retention on the broker side (default: true).
|
||||
- The `timeout` option controls the default timeout for all commands in milliseconds (default: 1000).
|
||||
|
||||
Set a custom clock source "custom millis" callback to enable deep sleep applications:
|
||||
|
||||
```c++
|
||||
void setClockSource(MQTTClientClockSource);
|
||||
// Callback signature: uint32_t clockSource() {}
|
||||
```
|
||||
|
||||
- The specified callback is used by the internal timers to get a monotonic time in milliseconds. Since the clock source for the built-in `millis` is stopped when the the Arduino goes into deep sleep, you need to provide a custom callback that first syncs with a built-in or external Real Time Clock (RTC). You can pass `NULL` to reset to the default implementation.
|
||||
|
||||
Connect to broker using the supplied client id and an optional username and password:
|
||||
|
||||
```c++
|
||||
bool connect(const char clientID[], bool skip = false);
|
||||
bool connect(const char clientID[], const char username[], bool skip = false);
|
||||
bool connect(const char clientID[], const char username[], const char password[], bool skip = false);
|
||||
```
|
||||
|
||||
- If the `skip` option is set to true, the client will skip the network level connection and jump to the MQTT level connection. This option can be used in order to establish and verify TLS connections manually before giving control to the MQTT client.
|
||||
- The functions return a boolean that indicates if the connection has been established successfully (true).
|
||||
|
||||
Publishes a message to the broker with an optional payload:
|
||||
|
||||
```c++
|
||||
bool publish(const String &topic);
|
||||
bool publish(const char topic[]);
|
||||
bool publish(const String &topic, const String &payload);
|
||||
bool publish(const String &topic, const String &payload, bool retained, int qos);
|
||||
bool publish(const char topic[], const String &payload);
|
||||
bool publish(const char topic[], const String &payload, bool retained, int qos);
|
||||
bool publish(const char topic[], const char payload[]);
|
||||
bool publish(const char topic[], const char payload[], bool retained, int qos);
|
||||
bool publish(const char topic[], const char payload[], int length);
|
||||
bool publish(const char topic[], const char payload[], int length, bool retained, int qos);
|
||||
```
|
||||
|
||||
- The functions return a boolean that indicates if the publish has been successful (true).
|
||||
|
||||
Subscribe to a topic:
|
||||
|
||||
```c++
|
||||
bool subscribe(const String &topic);
|
||||
bool subscribe(const String &topic, int qos);
|
||||
bool subscribe(const char topic[]);
|
||||
bool subscribe(const char topic[], int qos);
|
||||
```
|
||||
|
||||
- The functions return a boolean that indicates if the subscribe has been successful (true).
|
||||
|
||||
Unsubscribe from a topic:
|
||||
|
||||
```c++
|
||||
bool unsubscribe(const String &topic);
|
||||
bool unsubscribe(const char topic[]);
|
||||
```
|
||||
|
||||
- The functions return a boolean that indicates if the unsubscribe has been successful (true).
|
||||
|
||||
Sends and receives packets:
|
||||
|
||||
```c++
|
||||
bool loop();
|
||||
```
|
||||
|
||||
- This function should be called in every `loop`.
|
||||
- The function returns a boolean that indicates if the loop has been successful (true).
|
||||
|
||||
Check if the client is currently connected:
|
||||
|
||||
```c++
|
||||
bool connected();
|
||||
```
|
||||
|
||||
Access low-level information for debugging:
|
||||
|
||||
```c++
|
||||
lwmqtt_err_t lastError();
|
||||
lwmqtt_return_code_t returnCode();
|
||||
```
|
||||
|
||||
- The error codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11).
|
||||
- The return codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L243).
|
||||
|
||||
Disconnect from the broker:
|
||||
|
||||
```c++
|
||||
bool disconnect();
|
||||
```
|
||||
|
||||
- The function returns a boolean that indicates if the disconnect has been successful (true).
|
||||
|
||||
## Release Management
|
||||
|
||||
- Update version in `library.properties`.
|
||||
- Create release on GitHub.
|
||||
@@ -0,0 +1,74 @@
|
||||
// This example uses an Adafruit Huzzah ESP8266
|
||||
// to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
delay(10); // <- fixes some issues with WiFi stability
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// This example uses an Adafruit Huzzah ESP8266
|
||||
// to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClientSecure net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// do not verify tls certificate
|
||||
// check the following example for methods to verify the server:
|
||||
// https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino
|
||||
net.setInsecure();
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
//
|
||||
// MQTT brokers usually use port 8883 for secure connections.
|
||||
client.begin("broker.shiftr.io", 8883, net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
delay(10); // <- fixes some issues with WiFi stability
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// This example uses an Arduino Uno together with
|
||||
// an Ethernet Shield to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <Ethernet.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
byte ip[] = {192, 168, 1, 177}; // <- change to match your network
|
||||
|
||||
EthernetClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("connecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Ethernet.begin(mac, ip);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// This example uses an Arduino MKR GSM 1400 board
|
||||
// to connect to shiftr.io.
|
||||
//
|
||||
// IMPORTANT: This example uses the new MKRGSM library.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Sandeep Mistry
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <MKRGSM.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char pin[] = "";
|
||||
const char apn[] = "apn";
|
||||
const char login[] = "login";
|
||||
const char password[] = "password";
|
||||
|
||||
GSMClient net;
|
||||
GPRS gprs;
|
||||
GSM gsmAccess;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
// connection state
|
||||
bool connected = false;
|
||||
|
||||
Serial.print("connecting to cellular network ...");
|
||||
|
||||
// After starting the modem with gsmAccess.begin()
|
||||
// attach to the GPRS network with the APN, login and password
|
||||
while (!connected) {
|
||||
if ((gsmAccess.begin(pin) == GSM_READY) &&
|
||||
(gprs.attachGPRS(apn, login, password) == GPRS_READY)) {
|
||||
connected = true;
|
||||
} else {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// This example uses an Arduino MKR GSM 1400 board
|
||||
// to securely connect to shiftr.io.
|
||||
//
|
||||
// IMPORTANT: This example uses the new MKRGSM library.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Sandeep Mistry
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <MKRGSM.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char pin[] = "";
|
||||
const char apn[] = "apn";
|
||||
const char login[] = "login";
|
||||
const char password[] = "password";
|
||||
|
||||
GSMSSLClient net;
|
||||
GPRS gprs;
|
||||
GSM gsmAccess;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
// connection state
|
||||
bool connected = false;
|
||||
|
||||
Serial.print("connecting to cellular network ...");
|
||||
|
||||
// After starting the modem with gsmAccess.begin()
|
||||
// attach to the GPRS network with the APN, login and password
|
||||
while (!connected) {
|
||||
if ((gsmAccess.begin(pin) == GSM_READY) &&
|
||||
(gprs.attachGPRS(apn, login, password) == GPRS_READY)) {
|
||||
connected = true;
|
||||
} else {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
//
|
||||
// MQTT brokers usually use port 8883 for secure connections.
|
||||
client.begin("broker.shiftr.io", 8883, net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// This example uses an Arduino/Genuino Zero together with
|
||||
// a WiFi101 Shield or a MKR1000 to connect to shiftr.io.
|
||||
//
|
||||
// IMPORTANT: This example uses the new WiFi101 library.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Gilberto Conti
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <WiFi101.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// This example uses an Arduino/Genuino Zero together with
|
||||
// a WiFi101 Shield or a MKR1000 to connect to shiftr.io.
|
||||
//
|
||||
// IMPORTANT: This example uses the new WiFi101 library.
|
||||
//
|
||||
// IMPORTANT: You need to install/update the SSL certificates first:
|
||||
// https://github.com/arduino-libraries/WiFi101-FirmwareUpdater#to-update-ssl-certificates
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Gilberto Conti
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <WiFi101.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiSSLClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
//
|
||||
// MQTT brokers usually use port 8883 for secure connections.
|
||||
client.begin("broker.shiftr.io", 8883, net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// This example uses an Arduino Uno together with
|
||||
// a WiFi Shield to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
65
P1_gateway_FW/lib/MQTT/examples/ArduinoYun/ArduinoYun.ino
Normal file
65
P1_gateway_FW/lib/MQTT/examples/ArduinoYun/ArduinoYun.ino
Normal file
@@ -0,0 +1,65 @@
|
||||
// This example uses an Arduino Yun or a Yun-Shield
|
||||
// and the MQTTClient to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <Bridge.h>
|
||||
#include <BridgeClient.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
BridgeClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("connecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Bridge.begin();
|
||||
Serial.begin(115200);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// This example uses an Arduino Yun or a Yun-Shield
|
||||
// and the MQTTClient to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <Bridge.h>
|
||||
#include <BridgeSSLClient.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
BridgeSSLClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("connecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Bridge.begin();
|
||||
Serial.begin(115200);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
//
|
||||
// MQTT brokers usually use port 8883 for secure connections.
|
||||
client.begin("broker.shiftr.io", 8883, net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// This example uses an ESP32 Development Board
|
||||
// to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClient net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
client.begin("broker.shiftr.io", net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
delay(10); // <- fixes some issues with WiFi stability
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// This example uses an ESP32 Development Board
|
||||
// to connect to shiftr.io.
|
||||
//
|
||||
// You can check on your device after a successful
|
||||
// connection here: https://shiftr.io/try.
|
||||
//
|
||||
// by Joël Gähwiler
|
||||
// https://github.com/256dpi/arduino-mqtt
|
||||
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <MQTT.h>
|
||||
|
||||
const char ssid[] = "ssid";
|
||||
const char pass[] = "pass";
|
||||
|
||||
WiFiClientSecure net;
|
||||
MQTTClient client;
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
|
||||
void connect() {
|
||||
Serial.print("checking wifi...");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("\nconnecting...");
|
||||
while (!client.connect("arduino", "try", "try")) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("\nconnected!");
|
||||
|
||||
client.subscribe("/hello");
|
||||
// client.unsubscribe("/hello");
|
||||
}
|
||||
|
||||
void messageReceived(String &topic, String &payload) {
|
||||
Serial.println("incoming: " + topic + " - " + payload);
|
||||
|
||||
// Note: Do not use the client in the callback to publish, subscribe or
|
||||
// unsubscribe as it may cause deadlocks when other things arrive while
|
||||
// sending and receiving acknowledgments. Instead, change a global variable,
|
||||
// or push to a queue and handle it in the loop after calling `client.loop()`.
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
|
||||
// by Arduino. You need to set the IP address directly.
|
||||
//
|
||||
// MQTT brokers usually use port 8883 for secure connections.
|
||||
client.begin("broker.shiftr.io", 8883, net);
|
||||
client.onMessage(messageReceived);
|
||||
|
||||
connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
client.loop();
|
||||
delay(10); // <- fixes some issues with WiFi stability
|
||||
|
||||
if (!client.connected()) {
|
||||
connect();
|
||||
}
|
||||
|
||||
// publish a message roughly every second.
|
||||
if (millis() - lastMillis > 1000) {
|
||||
lastMillis = millis();
|
||||
client.publish("/hello", "world");
|
||||
}
|
||||
}
|
||||
9
P1_gateway_FW/lib/MQTT/library.properties
Normal file
9
P1_gateway_FW/lib/MQTT/library.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
name=MQTT
|
||||
version=2.4.8
|
||||
author=Joel Gaehwiler <joel.gaehwiler@gmail.com>
|
||||
maintainer=Joel Gaehwiler <joel.gaehwiler@gmail.com>
|
||||
sentence=MQTT library for Arduino
|
||||
paragraph=This library bundles the lwmqtt client and adds a thin wrapper to get an Arduino like API.
|
||||
category=Communication
|
||||
url=https://github.com/256dpi/arduino-mqtt
|
||||
architectures=*
|
||||
6
P1_gateway_FW/lib/MQTT/src/MQTT.h
Normal file
6
P1_gateway_FW/lib/MQTT/src/MQTT.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef MQTT_H
|
||||
#define MQTT_H
|
||||
|
||||
#include "MQTTClient.h"
|
||||
|
||||
#endif
|
||||
422
P1_gateway_FW/lib/MQTT/src/MQTTClient.cpp
Normal file
422
P1_gateway_FW/lib/MQTT/src/MQTTClient.cpp
Normal file
@@ -0,0 +1,422 @@
|
||||
#include "MQTTClient.h"
|
||||
|
||||
inline void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout) {
|
||||
// cast timer reference
|
||||
auto t = (lwmqtt_arduino_timer_t *)ref;
|
||||
|
||||
// set future end time
|
||||
if (t->millis != nullptr) {
|
||||
t->end = (uint32_t)(t->millis() + timeout);
|
||||
} else {
|
||||
t->end = (uint32_t)(millis() + timeout);
|
||||
}
|
||||
}
|
||||
|
||||
inline int32_t lwmqtt_arduino_timer_get(void *ref) {
|
||||
// cast timer reference
|
||||
auto t = (lwmqtt_arduino_timer_t *)ref;
|
||||
|
||||
// get difference to end time
|
||||
if (t->millis != nullptr) {
|
||||
return (int32_t)(t->end - t->millis());
|
||||
} else {
|
||||
return (int32_t)(t->end - millis());
|
||||
}
|
||||
}
|
||||
|
||||
inline lwmqtt_err_t lwmqtt_arduino_network_read(void *ref, uint8_t *buffer, size_t len, size_t *read,
|
||||
uint32_t timeout) {
|
||||
// cast network reference
|
||||
auto n = (lwmqtt_arduino_network_t *)ref;
|
||||
|
||||
// set timeout
|
||||
uint32_t start = millis();
|
||||
|
||||
// reset counter
|
||||
*read = 0;
|
||||
|
||||
// read until all bytes have been read or timeout has been reached
|
||||
while (len > 0 && (millis() - start < timeout)) {
|
||||
// read from connection
|
||||
int r = n->client->read(buffer, len);
|
||||
|
||||
// handle read data
|
||||
if (r > 0) {
|
||||
buffer += r;
|
||||
*read += r;
|
||||
len -= r;
|
||||
continue;
|
||||
}
|
||||
|
||||
// wait/unblock for some time (RTOS based boards may otherwise fail since
|
||||
// the wifi task cannot provide the data)
|
||||
delay(0);
|
||||
|
||||
// otherwise check status
|
||||
if (!n->client->connected()) {
|
||||
return LWMQTT_NETWORK_FAILED_READ;
|
||||
}
|
||||
}
|
||||
|
||||
// check counter
|
||||
if (*read == 0) {
|
||||
return LWMQTT_NETWORK_TIMEOUT;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
inline lwmqtt_err_t lwmqtt_arduino_network_write(void *ref, uint8_t *buffer, size_t len, size_t *sent,
|
||||
uint32_t /*timeout*/) {
|
||||
// cast network reference
|
||||
auto n = (lwmqtt_arduino_network_t *)ref;
|
||||
|
||||
// write bytes
|
||||
*sent = n->client->write(buffer, len);
|
||||
if (*sent <= 0) {
|
||||
return LWMQTT_NETWORK_FAILED_WRITE;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
static void MQTTClientHandler(lwmqtt_client_t * /*client*/, void *ref, lwmqtt_string_t topic,
|
||||
lwmqtt_message_t message) {
|
||||
// get callback
|
||||
auto cb = (MQTTClientCallback *)ref;
|
||||
|
||||
// null terminate topic
|
||||
char terminated_topic[topic.len + 1];
|
||||
memcpy(terminated_topic, topic.data, topic.len);
|
||||
terminated_topic[topic.len] = '\0';
|
||||
|
||||
// null terminate payload if available
|
||||
if (message.payload != nullptr) {
|
||||
message.payload[message.payload_len] = '\0';
|
||||
}
|
||||
|
||||
// call the advanced callback and return if available
|
||||
if (cb->advanced != nullptr) {
|
||||
cb->advanced(cb->client, terminated_topic, (char *)message.payload, (int)message.payload_len);
|
||||
return;
|
||||
}
|
||||
|
||||
// return if simple callback is not set
|
||||
if (cb->simple == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create topic string
|
||||
String str_topic = String(terminated_topic);
|
||||
|
||||
// create payload string
|
||||
String str_payload;
|
||||
if (message.payload != nullptr) {
|
||||
str_payload = String((const char *)message.payload);
|
||||
}
|
||||
|
||||
// call simple callback
|
||||
cb->simple(str_topic, str_payload);
|
||||
}
|
||||
|
||||
MQTTClient::MQTTClient(int bufSize) {
|
||||
// allocate buffers
|
||||
this->bufSize = (size_t)bufSize;
|
||||
this->readBuf = (uint8_t *)malloc((size_t)bufSize + 1);
|
||||
this->writeBuf = (uint8_t *)malloc((size_t)bufSize);
|
||||
}
|
||||
|
||||
MQTTClient::~MQTTClient() {
|
||||
// free will
|
||||
this->clearWill();
|
||||
|
||||
// free hostname
|
||||
if (this->hostname != nullptr) {
|
||||
free((void *)this->hostname);
|
||||
}
|
||||
|
||||
// free buffers
|
||||
free(this->readBuf);
|
||||
free(this->writeBuf);
|
||||
}
|
||||
|
||||
void MQTTClient::begin(Client &_client) {
|
||||
// set client
|
||||
this->netClient = &_client;
|
||||
|
||||
// initialize client
|
||||
lwmqtt_init(&this->client, this->writeBuf, this->bufSize, this->readBuf, this->bufSize);
|
||||
|
||||
// set timers
|
||||
lwmqtt_set_timers(&this->client, &this->timer1, &this->timer2, lwmqtt_arduino_timer_set, lwmqtt_arduino_timer_get);
|
||||
|
||||
// set network
|
||||
lwmqtt_set_network(&this->client, &this->network, lwmqtt_arduino_network_read, lwmqtt_arduino_network_write);
|
||||
|
||||
// set callback
|
||||
lwmqtt_set_callback(&this->client, (void *)&this->callback, MQTTClientHandler);
|
||||
}
|
||||
|
||||
void MQTTClient::onMessage(MQTTClientCallbackSimple cb) {
|
||||
// set callback
|
||||
this->callback.client = this;
|
||||
this->callback.simple = cb;
|
||||
this->callback.advanced = nullptr;
|
||||
}
|
||||
|
||||
void MQTTClient::onMessageAdvanced(MQTTClientCallbackAdvanced cb) {
|
||||
// set callback
|
||||
this->callback.client = this;
|
||||
this->callback.simple = nullptr;
|
||||
this->callback.advanced = cb;
|
||||
}
|
||||
|
||||
void MQTTClient::setClockSource(MQTTClientClockSource cb) {
|
||||
this->timer1.millis = cb;
|
||||
this->timer2.millis = cb;
|
||||
}
|
||||
|
||||
void MQTTClient::setHost(IPAddress _address, int _port) {
|
||||
// set address and port
|
||||
this->address = _address;
|
||||
this->port = _port;
|
||||
}
|
||||
|
||||
void MQTTClient::setHost(const char _hostname[], int _port) {
|
||||
// free hostname if set
|
||||
if (this->hostname != nullptr) {
|
||||
free((void *)this->hostname);
|
||||
}
|
||||
|
||||
// set hostname and port
|
||||
this->hostname = strdup(_hostname);
|
||||
this->port = _port;
|
||||
}
|
||||
|
||||
void MQTTClient::setWill(const char topic[], const char payload[], bool retained, int qos) {
|
||||
// return if topic is missing
|
||||
if (topic == nullptr || strlen(topic) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear existing will
|
||||
this->clearWill();
|
||||
|
||||
// allocate will
|
||||
this->will = (lwmqtt_will_t *)malloc(sizeof(lwmqtt_will_t));
|
||||
memset(this->will, 0, sizeof(lwmqtt_will_t));
|
||||
|
||||
// set topic
|
||||
this->will->topic = lwmqtt_string(strdup(topic));
|
||||
|
||||
// set payload if available
|
||||
if (payload != nullptr && strlen(payload) > 0) {
|
||||
this->will->payload = lwmqtt_string(strdup(payload));
|
||||
}
|
||||
|
||||
// set flags
|
||||
this->will->retained = retained;
|
||||
this->will->qos = (lwmqtt_qos_t)qos;
|
||||
}
|
||||
|
||||
void MQTTClient::clearWill() {
|
||||
// return if not set
|
||||
if (this->will == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// free payload if set
|
||||
if (this->will->payload.len > 0) {
|
||||
free(this->will->payload.data);
|
||||
}
|
||||
|
||||
// free topic if set
|
||||
if (this->will->topic.len > 0) {
|
||||
free(this->will->topic.data);
|
||||
}
|
||||
|
||||
// free will
|
||||
free(this->will);
|
||||
this->will = nullptr;
|
||||
}
|
||||
|
||||
void MQTTClient::setKeepAlive(int _keepAlive) { this->keepAlive = _keepAlive; }
|
||||
|
||||
void MQTTClient::setCleanSession(bool _cleanSession) { this->cleanSession = _cleanSession; }
|
||||
|
||||
void MQTTClient::setTimeout(int _timeout) { this->timeout = _timeout; }
|
||||
|
||||
bool MQTTClient::publish(const char topic[], const char payload[], int length, bool retained, int qos) {
|
||||
// return immediately if not connected
|
||||
if (!this->connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare message
|
||||
lwmqtt_message_t message = lwmqtt_default_message;
|
||||
message.payload = (uint8_t *)payload;
|
||||
message.payload_len = (size_t)length;
|
||||
message.retained = retained;
|
||||
message.qos = lwmqtt_qos_t(qos);
|
||||
|
||||
// publish message
|
||||
this->_lastError = lwmqtt_publish(&this->client, lwmqtt_string(topic), message, this->timeout);
|
||||
if (this->_lastError != LWMQTT_SUCCESS) {
|
||||
// close connection
|
||||
this->close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MQTTClient::connect(const char clientID[], const char username[], const char password[], bool skip) {
|
||||
// close left open connection if still connected
|
||||
if (!skip && this->connected()) {
|
||||
this->close();
|
||||
}
|
||||
|
||||
// save client
|
||||
this->network.client = this->netClient;
|
||||
|
||||
// connect to host
|
||||
if (!skip) {
|
||||
int ret;
|
||||
if (this->hostname != nullptr) {
|
||||
ret = this->netClient->connect(this->hostname, (uint16_t)this->port);
|
||||
} else {
|
||||
ret = this->netClient->connect(this->address, (uint16_t)this->port);
|
||||
}
|
||||
if (ret <= 0) {
|
||||
this->_lastError = LWMQTT_NETWORK_FAILED_CONNECT;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// prepare options
|
||||
lwmqtt_options_t options = lwmqtt_default_options;
|
||||
options.keep_alive = this->keepAlive;
|
||||
options.clean_session = this->cleanSession;
|
||||
options.client_id = lwmqtt_string(clientID);
|
||||
|
||||
// set username and password if available
|
||||
if (username != nullptr) {
|
||||
options.username = lwmqtt_string(username);
|
||||
|
||||
if (password != nullptr) {
|
||||
options.password = lwmqtt_string(password);
|
||||
}
|
||||
}
|
||||
|
||||
// connect to broker
|
||||
this->_lastError = lwmqtt_connect(&this->client, options, this->will, &this->_returnCode, this->timeout);
|
||||
if (this->_lastError != LWMQTT_SUCCESS) {
|
||||
// close connection
|
||||
this->close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// set flag
|
||||
this->_connected = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MQTTClient::subscribe(const char topic[], int qos) {
|
||||
// return immediately if not connected
|
||||
if (!this->connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// subscribe to topic
|
||||
this->_lastError = lwmqtt_subscribe_one(&this->client, lwmqtt_string(topic), (lwmqtt_qos_t)qos, this->timeout);
|
||||
if (this->_lastError != LWMQTT_SUCCESS) {
|
||||
// close connection
|
||||
this->close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MQTTClient::unsubscribe(const char topic[]) {
|
||||
// return immediately if not connected
|
||||
if (!this->connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// unsubscribe from topic
|
||||
this->_lastError = lwmqtt_unsubscribe_one(&this->client, lwmqtt_string(topic), this->timeout);
|
||||
if (this->_lastError != LWMQTT_SUCCESS) {
|
||||
// close connection
|
||||
this->close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MQTTClient::loop() {
|
||||
// return immediately if not connected
|
||||
if (!this->connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get available bytes on the network
|
||||
auto available = (size_t)this->netClient->available();
|
||||
|
||||
// yield if data is available
|
||||
if (available > 0) {
|
||||
this->_lastError = lwmqtt_yield(&this->client, available, this->timeout);
|
||||
if (this->_lastError != LWMQTT_SUCCESS) {
|
||||
// close connection
|
||||
this->close();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// keep the connection alive
|
||||
this->_lastError = lwmqtt_keep_alive(&this->client, this->timeout);
|
||||
if (this->_lastError != LWMQTT_SUCCESS) {
|
||||
// close connection
|
||||
this->close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MQTTClient::connected() {
|
||||
// a client is connected if the network is connected, a client is available and
|
||||
// the connection has been properly initiated
|
||||
return this->netClient != nullptr && this->netClient->connected() == 1 && this->_connected;
|
||||
}
|
||||
|
||||
bool MQTTClient::disconnect() {
|
||||
// return immediately if not connected anymore
|
||||
if (!this->connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// cleanly disconnect
|
||||
this->_lastError = lwmqtt_disconnect(&this->client, this->timeout);
|
||||
|
||||
// close
|
||||
this->close();
|
||||
|
||||
return this->_lastError == LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
void MQTTClient::close() {
|
||||
// set flag
|
||||
this->_connected = false;
|
||||
|
||||
// close network
|
||||
this->netClient->stop();
|
||||
}
|
||||
151
P1_gateway_FW/lib/MQTT/src/MQTTClient.h
Normal file
151
P1_gateway_FW/lib/MQTT/src/MQTTClient.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef MQTT_CLIENT_H
|
||||
#define MQTT_CLIENT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Client.h>
|
||||
#include <Stream.h>
|
||||
|
||||
extern "C" {
|
||||
#include "lwmqtt/lwmqtt.h"
|
||||
}
|
||||
|
||||
typedef uint32_t (*MQTTClientClockSource)();
|
||||
|
||||
typedef struct {
|
||||
uint32_t end;
|
||||
MQTTClientClockSource millis;
|
||||
} lwmqtt_arduino_timer_t;
|
||||
|
||||
typedef struct {
|
||||
Client *client;
|
||||
} lwmqtt_arduino_network_t;
|
||||
|
||||
class MQTTClient;
|
||||
|
||||
typedef void (*MQTTClientCallbackSimple)(String &topic, String &payload);
|
||||
typedef void (*MQTTClientCallbackAdvanced)(MQTTClient *client, char topic[], char bytes[], int length);
|
||||
|
||||
typedef struct {
|
||||
MQTTClient *client = nullptr;
|
||||
MQTTClientCallbackSimple simple = nullptr;
|
||||
MQTTClientCallbackAdvanced advanced = nullptr;
|
||||
} MQTTClientCallback;
|
||||
|
||||
class MQTTClient {
|
||||
private:
|
||||
size_t bufSize = 0;
|
||||
uint8_t *readBuf = nullptr;
|
||||
uint8_t *writeBuf = nullptr;
|
||||
|
||||
uint16_t keepAlive = 10;
|
||||
bool cleanSession = true;
|
||||
uint32_t timeout = 1000;
|
||||
|
||||
Client *netClient = nullptr;
|
||||
const char *hostname = nullptr;
|
||||
IPAddress address;
|
||||
int port = 0;
|
||||
lwmqtt_will_t *will = nullptr;
|
||||
MQTTClientCallback callback;
|
||||
|
||||
lwmqtt_arduino_network_t network = {nullptr};
|
||||
lwmqtt_arduino_timer_t timer1 = {0, nullptr};
|
||||
lwmqtt_arduino_timer_t timer2 = {0, nullptr};
|
||||
lwmqtt_client_t client = lwmqtt_client_t();
|
||||
|
||||
bool _connected = false;
|
||||
lwmqtt_return_code_t _returnCode = (lwmqtt_return_code_t)0;
|
||||
lwmqtt_err_t _lastError = (lwmqtt_err_t)0;
|
||||
|
||||
public:
|
||||
void *ref = nullptr;
|
||||
|
||||
explicit MQTTClient(int bufSize = 128);
|
||||
|
||||
~MQTTClient();
|
||||
|
||||
void begin(Client &_client);
|
||||
void begin(const char _hostname[], Client &_client) { this->begin(_hostname, 1883, _client); }
|
||||
void begin(const char _hostname[], int _port, Client &_client) {
|
||||
this->begin(_client);
|
||||
this->setHost(_hostname, _port);
|
||||
}
|
||||
void begin(IPAddress _address, Client &_client) { this->begin(_address, 1883, _client); }
|
||||
void begin(IPAddress _address, int _port, Client &_client) {
|
||||
this->begin(_client);
|
||||
this->setHost(_address, _port);
|
||||
}
|
||||
|
||||
void onMessage(MQTTClientCallbackSimple cb);
|
||||
void onMessageAdvanced(MQTTClientCallbackAdvanced cb);
|
||||
|
||||
void setClockSource(MQTTClientClockSource cb);
|
||||
|
||||
void setHost(const char _hostname[]) { this->setHost(_hostname, 1883); }
|
||||
void setHost(const char hostname[], int port);
|
||||
void setHost(IPAddress _address) { this->setHost(_address, 1883); }
|
||||
void setHost(IPAddress _address, int port);
|
||||
|
||||
void setWill(const char topic[]) { this->setWill(topic, ""); }
|
||||
void setWill(const char topic[], const char payload[]) { this->setWill(topic, payload, false, 0); }
|
||||
void setWill(const char topic[], const char payload[], bool retained, int qos);
|
||||
void clearWill();
|
||||
|
||||
void setKeepAlive(int keepAlive);
|
||||
void setCleanSession(bool cleanSession);
|
||||
void setTimeout(int timeout);
|
||||
|
||||
void setOptions(int _keepAlive, bool _cleanSession, int _timeout) {
|
||||
this->setKeepAlive(_keepAlive);
|
||||
this->setCleanSession(_cleanSession);
|
||||
this->setTimeout(_timeout);
|
||||
}
|
||||
|
||||
bool connect(const char clientId[], bool skip = false) { return this->connect(clientId, nullptr, nullptr, skip); }
|
||||
bool connect(const char clientId[], const char username[], bool skip = false) {
|
||||
return this->connect(clientId, username, nullptr, skip);
|
||||
}
|
||||
bool connect(const char clientID[], const char username[], const char password[], bool skip = false);
|
||||
|
||||
bool publish(const String &topic) { return this->publish(topic.c_str(), ""); }
|
||||
bool publish(const char topic[]) { return this->publish(topic, ""); }
|
||||
bool publish(const String &topic, const String &payload) { return this->publish(topic.c_str(), payload.c_str()); }
|
||||
bool publish(const String &topic, const String &payload, bool retained, int qos) {
|
||||
return this->publish(topic.c_str(), payload.c_str(), retained, qos);
|
||||
}
|
||||
bool publish(const char topic[], const String &payload) { return this->publish(topic, payload.c_str()); }
|
||||
bool publish(const char topic[], const String &payload, bool retained, int qos) {
|
||||
return this->publish(topic, payload.c_str(), retained, qos);
|
||||
}
|
||||
bool publish(const char topic[], const char payload[]) {
|
||||
return this->publish(topic, (char *)payload, (int)strlen(payload));
|
||||
}
|
||||
bool publish(const char topic[], const char payload[], bool retained, int qos) {
|
||||
return this->publish(topic, (char *)payload, (int)strlen(payload), retained, qos);
|
||||
}
|
||||
bool publish(const char topic[], const char payload[], int length) {
|
||||
return this->publish(topic, payload, length, false, 0);
|
||||
}
|
||||
bool publish(const char topic[], const char payload[], int length, bool retained, int qos);
|
||||
|
||||
bool subscribe(const String &topic) { return this->subscribe(topic.c_str()); }
|
||||
bool subscribe(const String &topic, int qos) { return this->subscribe(topic.c_str(), qos); }
|
||||
bool subscribe(const char topic[]) { return this->subscribe(topic, 0); }
|
||||
bool subscribe(const char topic[], int qos);
|
||||
|
||||
bool unsubscribe(const String &topic) { return this->unsubscribe(topic.c_str()); }
|
||||
bool unsubscribe(const char topic[]);
|
||||
|
||||
bool loop();
|
||||
bool connected();
|
||||
|
||||
lwmqtt_err_t lastError() { return this->_lastError; }
|
||||
lwmqtt_return_code_t returnCode() { return this->_returnCode; }
|
||||
|
||||
bool disconnect();
|
||||
|
||||
private:
|
||||
void close();
|
||||
};
|
||||
|
||||
#endif
|
||||
618
P1_gateway_FW/lib/MQTT/src/lwmqtt/client.c
Normal file
618
P1_gateway_FW/lib/MQTT/src/lwmqtt/client.c
Normal file
@@ -0,0 +1,618 @@
|
||||
#include "packet.h"
|
||||
|
||||
void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf,
|
||||
size_t read_buf_size) {
|
||||
client->last_packet_id = 1;
|
||||
client->keep_alive_interval = 0;
|
||||
client->pong_pending = false;
|
||||
|
||||
client->write_buf = write_buf;
|
||||
client->write_buf_size = write_buf_size;
|
||||
client->read_buf = read_buf;
|
||||
client->read_buf_size = read_buf_size;
|
||||
|
||||
client->callback = NULL;
|
||||
client->callback_ref = NULL;
|
||||
|
||||
client->network = NULL;
|
||||
client->network_read = NULL;
|
||||
client->network_write = NULL;
|
||||
|
||||
client->keep_alive_timer = NULL;
|
||||
client->command_timer = NULL;
|
||||
client->timer_set = NULL;
|
||||
client->timer_get = NULL;
|
||||
}
|
||||
|
||||
void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write) {
|
||||
client->network = ref;
|
||||
client->network_read = read;
|
||||
client->network_write = write;
|
||||
}
|
||||
|
||||
void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set,
|
||||
lwmqtt_timer_get_t get) {
|
||||
client->keep_alive_timer = keep_alive_timer;
|
||||
client->command_timer = command_timer;
|
||||
client->timer_set = set;
|
||||
client->timer_get = get;
|
||||
|
||||
client->timer_set(client->keep_alive_timer, 0);
|
||||
client->timer_set(client->command_timer, 0);
|
||||
}
|
||||
|
||||
void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb) {
|
||||
client->callback_ref = ref;
|
||||
client->callback = cb;
|
||||
}
|
||||
|
||||
static uint16_t lwmqtt_get_next_packet_id(lwmqtt_client_t *client) {
|
||||
// check overflow
|
||||
if (client->last_packet_id == 65535) {
|
||||
client->last_packet_id = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// increment packet id
|
||||
client->last_packet_id++;
|
||||
|
||||
return client->last_packet_id;
|
||||
}
|
||||
|
||||
static lwmqtt_err_t lwmqtt_read_from_network(lwmqtt_client_t *client, size_t offset, size_t len) {
|
||||
// check read buffer capacity
|
||||
if (client->read_buf_size < offset + len) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// prepare counter
|
||||
size_t read = 0;
|
||||
|
||||
// read while data is missing
|
||||
while (read < len) {
|
||||
// check remaining time
|
||||
int32_t remaining_time = client->timer_get(client->command_timer);
|
||||
if (remaining_time <= 0) {
|
||||
return LWMQTT_NETWORK_TIMEOUT;
|
||||
}
|
||||
|
||||
// read
|
||||
size_t partial_read = 0;
|
||||
lwmqtt_err_t err = client->network_read(client->network, client->read_buf + offset + read, len - read,
|
||||
&partial_read, (uint32_t)remaining_time);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// increment counter
|
||||
read += partial_read;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
static lwmqtt_err_t lwmqtt_write_to_network(lwmqtt_client_t *client, size_t offset, size_t len) {
|
||||
// prepare counter
|
||||
size_t written = 0;
|
||||
|
||||
// write while data is left
|
||||
while (written < len) {
|
||||
// check remaining time
|
||||
int32_t remaining_time = client->timer_get(client->command_timer);
|
||||
if (remaining_time <= 0) {
|
||||
return LWMQTT_NETWORK_TIMEOUT;
|
||||
}
|
||||
|
||||
// write
|
||||
size_t partial_write = 0;
|
||||
lwmqtt_err_t err = client->network_write(client->network, client->write_buf + offset + written, len - written,
|
||||
&partial_write, (uint32_t)remaining_time);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// increment counter
|
||||
written += partial_write;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
static lwmqtt_err_t lwmqtt_read_packet_in_buffer(lwmqtt_client_t *client, size_t *read,
|
||||
lwmqtt_packet_type_t *packet_type) {
|
||||
// preset packet type
|
||||
*packet_type = LWMQTT_NO_PACKET;
|
||||
|
||||
// read or wait for header byte
|
||||
lwmqtt_err_t err = lwmqtt_read_from_network(client, 0, 1);
|
||||
if (err == LWMQTT_NETWORK_TIMEOUT) {
|
||||
// this is ok as no data has been read at all
|
||||
return LWMQTT_SUCCESS;
|
||||
} else if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// detect packet type
|
||||
err = lwmqtt_detect_packet_type(client->read_buf, 1, packet_type);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// prepare variables
|
||||
size_t len = 0;
|
||||
uint32_t rem_len = 0;
|
||||
|
||||
do {
|
||||
// adjust len
|
||||
len++;
|
||||
|
||||
// read next byte
|
||||
err = lwmqtt_read_from_network(client, len, 1);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// attempt to detect remaining length
|
||||
err = lwmqtt_detect_remaining_length(client->read_buf + 1, len, &rem_len);
|
||||
} while (err == LWMQTT_BUFFER_TOO_SHORT);
|
||||
|
||||
// check final error
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// read the rest of the buffer if needed
|
||||
if (rem_len > 0) {
|
||||
err = lwmqtt_read_from_network(client, 1 + len, rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust counter
|
||||
*read += 1 + len + rem_len;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
static lwmqtt_err_t lwmqtt_send_packet_in_buffer(lwmqtt_client_t *client, size_t length) {
|
||||
// write to network
|
||||
lwmqtt_err_t err = lwmqtt_write_to_network(client, 0, length);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// reset keep alive timer
|
||||
client->timer_set(client->keep_alive_timer, client->keep_alive_interval);
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
static lwmqtt_err_t lwmqtt_cycle(lwmqtt_client_t *client, size_t *read, lwmqtt_packet_type_t *packet_type) {
|
||||
// read next packet from the network
|
||||
lwmqtt_err_t err = lwmqtt_read_packet_in_buffer(client, read, packet_type);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
} else if (*packet_type == LWMQTT_NO_PACKET) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
switch (*packet_type) {
|
||||
// handle publish packets
|
||||
case LWMQTT_PUBLISH_PACKET: {
|
||||
// decode publish packet
|
||||
bool dup;
|
||||
uint16_t packet_id;
|
||||
lwmqtt_string_t topic;
|
||||
lwmqtt_message_t msg;
|
||||
err = lwmqtt_decode_publish(client->read_buf, client->read_buf_size, &dup, &packet_id, &topic, &msg);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// call callback if set
|
||||
if (client->callback != NULL) {
|
||||
client->callback(client, client->callback_ref, topic, msg);
|
||||
}
|
||||
|
||||
// break early on qos zero
|
||||
if (msg.qos == LWMQTT_QOS0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// define ack packet
|
||||
lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET;
|
||||
if (msg.qos == LWMQTT_QOS1) {
|
||||
ack_type = LWMQTT_PUBACK_PACKET;
|
||||
} else if (msg.qos == LWMQTT_QOS2) {
|
||||
ack_type = LWMQTT_PUBREC_PACKET;
|
||||
}
|
||||
|
||||
// encode ack packet
|
||||
size_t len;
|
||||
err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, ack_type, false, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send ack packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// handle pubrec packets
|
||||
case LWMQTT_PUBREC_PACKET: {
|
||||
// decode pubrec packet
|
||||
bool dup;
|
||||
uint16_t packet_id;
|
||||
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREC_PACKET, &dup, &packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// encode pubrel packet
|
||||
size_t len;
|
||||
err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBREL_PACKET, 0, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send pubrel packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// handle pubrel packets
|
||||
case LWMQTT_PUBREL_PACKET: {
|
||||
// decode pubrec packet
|
||||
bool dup;
|
||||
uint16_t packet_id;
|
||||
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREL_PACKET, &dup, &packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// encode pubcomp packet
|
||||
size_t len;
|
||||
err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBCOMP_PACKET, 0, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send pubcomp packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// handle pingresp packets
|
||||
case LWMQTT_PINGRESP_PACKET: {
|
||||
// set flag
|
||||
client->pong_pending = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// handle all other packets
|
||||
default: { break; }
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
static lwmqtt_err_t lwmqtt_cycle_until(lwmqtt_client_t *client, lwmqtt_packet_type_t *packet_type, size_t available,
|
||||
lwmqtt_packet_type_t needle) {
|
||||
// prepare counter
|
||||
size_t read = 0;
|
||||
|
||||
// loop until timeout has been reached
|
||||
do {
|
||||
// do one cycle
|
||||
lwmqtt_err_t err = lwmqtt_cycle(client, &read, packet_type);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// return when one packet has been successfully read when no availability has been given
|
||||
if (needle == LWMQTT_NO_PACKET && available == 0) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
// otherwise check if needle has been found
|
||||
if (*packet_type == needle) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
} while (client->timer_get(client->command_timer) > 0 && (available == 0 || read < available));
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// cycle until timeout has been reached
|
||||
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
|
||||
lwmqtt_err_t err = lwmqtt_cycle_until(client, &packet_type, available, LWMQTT_NO_PACKET);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will,
|
||||
lwmqtt_return_code_t *return_code, uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// save keep alive interval
|
||||
client->keep_alive_interval = (uint32_t)(options.keep_alive) * 1000;
|
||||
|
||||
// set keep alive timer
|
||||
client->timer_set(client->keep_alive_timer, client->keep_alive_interval);
|
||||
|
||||
// reset pong pending flag
|
||||
client->pong_pending = false;
|
||||
|
||||
// initialize return code
|
||||
*return_code = LWMQTT_UNKNOWN_RETURN_CODE;
|
||||
|
||||
// encode connect packet
|
||||
size_t len;
|
||||
lwmqtt_err_t err = lwmqtt_encode_connect(client->write_buf, client->write_buf_size, &len, options, will);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// wait for connack packet
|
||||
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
|
||||
err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_CONNACK_PACKET);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
} else if (packet_type != LWMQTT_CONNACK_PACKET) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// decode connack packet
|
||||
bool session_present;
|
||||
err = lwmqtt_decode_connack(client->read_buf, client->read_buf_size, &session_present, return_code);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// return error if connection was not accepted
|
||||
if (*return_code != LWMQTT_CONNECTION_ACCEPTED) {
|
||||
return LWMQTT_CONNECTION_DENIED;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos,
|
||||
uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// encode subscribe packet
|
||||
size_t len;
|
||||
lwmqtt_err_t err = lwmqtt_encode_subscribe(client->write_buf, client->write_buf_size, &len,
|
||||
lwmqtt_get_next_packet_id(client), count, topic_filter, qos);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// wait for suback packet
|
||||
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
|
||||
err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_SUBACK_PACKET);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
} else if (packet_type != LWMQTT_SUBACK_PACKET) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// decode packet
|
||||
int suback_count = 0;
|
||||
lwmqtt_qos_t granted_qos[count];
|
||||
uint16_t packet_id;
|
||||
err = lwmqtt_decode_suback(client->read_buf, client->read_buf_size, &packet_id, count, &suback_count, granted_qos);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check suback codes
|
||||
for (int i = 0; i < suback_count; i++) {
|
||||
if (granted_qos[i] == LWMQTT_QOS_FAILURE) {
|
||||
return LWMQTT_FAILED_SUBSCRIPTION;
|
||||
}
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos,
|
||||
uint32_t timeout) {
|
||||
return lwmqtt_subscribe(client, 1, &topic_filter, &qos, timeout);
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// encode unsubscribe packet
|
||||
size_t len;
|
||||
lwmqtt_err_t err = lwmqtt_encode_unsubscribe(client->write_buf, client->write_buf_size, &len,
|
||||
lwmqtt_get_next_packet_id(client), count, topic_filter);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send unsubscribe packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// wait for unsuback packet
|
||||
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
|
||||
err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_UNSUBACK_PACKET);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
} else if (packet_type != LWMQTT_UNSUBACK_PACKET) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// decode unsuback packet
|
||||
bool dup;
|
||||
uint16_t packet_id;
|
||||
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_UNSUBACK_PACKET, &dup, &packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout) {
|
||||
return lwmqtt_unsubscribe(client, 1, &topic_filter, timeout);
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t message,
|
||||
uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// add packet id if at least qos 1
|
||||
uint16_t packet_id = 0;
|
||||
if (message.qos == LWMQTT_QOS1 || message.qos == LWMQTT_QOS2) {
|
||||
packet_id = lwmqtt_get_next_packet_id(client);
|
||||
}
|
||||
|
||||
// encode publish packet
|
||||
size_t len = 0;
|
||||
lwmqtt_err_t err =
|
||||
lwmqtt_encode_publish(client->write_buf, client->write_buf_size, &len, 0, packet_id, topic, message);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// immediately return on qos zero
|
||||
if (message.qos == LWMQTT_QOS0) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
// define ack packet
|
||||
lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET;
|
||||
if (message.qos == LWMQTT_QOS1) {
|
||||
ack_type = LWMQTT_PUBACK_PACKET;
|
||||
} else if (message.qos == LWMQTT_QOS2) {
|
||||
ack_type = LWMQTT_PUBCOMP_PACKET;
|
||||
}
|
||||
|
||||
// wait for ack packet
|
||||
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
|
||||
err = lwmqtt_cycle_until(client, &packet_type, 0, ack_type);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
} else if (packet_type != ack_type) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// decode ack packet
|
||||
bool dup;
|
||||
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, ack_type, &dup, &packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// encode disconnect packet
|
||||
size_t len;
|
||||
lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_DISCONNECT_PACKET);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send disconnected packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout) {
|
||||
// set command timer
|
||||
client->timer_set(client->command_timer, timeout);
|
||||
|
||||
// return immediately if keep alive interval is zero
|
||||
if (client->keep_alive_interval == 0) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
// return immediately if no ping is due
|
||||
if (client->timer_get(client->keep_alive_timer) > 0) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
// a ping is due
|
||||
|
||||
// fail immediately if a pong is already pending
|
||||
if (client->pong_pending) {
|
||||
return LWMQTT_PONG_TIMEOUT;
|
||||
}
|
||||
|
||||
// encode pingreq packet
|
||||
size_t len;
|
||||
lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_PINGREQ_PACKET);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// send packet
|
||||
err = lwmqtt_send_packet_in_buffer(client, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// set flag
|
||||
client->pong_pending = true;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
249
P1_gateway_FW/lib/MQTT/src/lwmqtt/helpers.c
Normal file
249
P1_gateway_FW/lib/MQTT/src/lwmqtt/helpers.c
Normal file
@@ -0,0 +1,249 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num) { return (byte & (uint8_t)((~(0xFF << num)) << pos)) >> pos; }
|
||||
|
||||
void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num) {
|
||||
*byte = (*byte & ~(uint8_t)((~(0xFF << num)) << pos)) | (value << pos);
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len) {
|
||||
// check zero length
|
||||
if (len == 0) {
|
||||
*data = NULL;
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
// check buffer size
|
||||
if ((size_t)(buf_end - (*buf)) < len) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// read data
|
||||
*data = *buf;
|
||||
|
||||
// advance pointer
|
||||
*buf += len;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len) {
|
||||
// check zero length
|
||||
if (len == 0) {
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
// check buffer size
|
||||
if ((size_t)(buf_end - (*buf)) < len) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// write data
|
||||
memcpy(*buf, data, len);
|
||||
|
||||
// advance pointer
|
||||
*buf += len;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num) {
|
||||
// check buffer size
|
||||
if ((size_t)(buf_end - (*buf)) < 2) {
|
||||
*num = 0;
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// read two byte integer
|
||||
*num = (uint16_t)256 * (*buf)[0] + (*buf)[1];
|
||||
|
||||
// adjust pointer
|
||||
*buf += 2;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num) {
|
||||
// check buffer size
|
||||
if ((size_t)(buf_end - (*buf)) < 2) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// write bytes
|
||||
(*buf)[0] = (uint8_t)(num / 256);
|
||||
(*buf)[1] = (uint8_t)(num % 256);
|
||||
|
||||
// adjust pointer
|
||||
*buf += 2;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str) {
|
||||
// read length
|
||||
uint16_t len;
|
||||
lwmqtt_err_t err = lwmqtt_read_num(buf, buf_end, &len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// read data
|
||||
err = lwmqtt_read_data(buf, buf_end, (uint8_t **)&str->data, len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// set length
|
||||
str->len = len;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str) {
|
||||
// write string length
|
||||
lwmqtt_err_t err = lwmqtt_write_num(buf, buf_end, str.len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write data
|
||||
err = lwmqtt_write_data(buf, buf_end, (uint8_t *)str.data, str.len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte) {
|
||||
// check buffer size
|
||||
if ((size_t)(buf_end - (*buf)) < 1) {
|
||||
*byte = 0;
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// read byte
|
||||
*byte = (*buf)[0];
|
||||
|
||||
// adjust pointer
|
||||
*buf += 1;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte) {
|
||||
// check buffer size
|
||||
if ((size_t)(buf_end - (*buf)) < 1) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// write byte
|
||||
(*buf)[0] = byte;
|
||||
|
||||
// adjust pointer
|
||||
*buf += 1;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len) {
|
||||
if (varnum < 128) {
|
||||
*len = 1;
|
||||
return LWMQTT_SUCCESS;
|
||||
} else if (varnum < 16384) {
|
||||
*len = 2;
|
||||
return LWMQTT_SUCCESS;
|
||||
} else if (varnum < 2097151) {
|
||||
*len = 3;
|
||||
return LWMQTT_SUCCESS;
|
||||
} else if (varnum < 268435455) {
|
||||
*len = 4;
|
||||
return LWMQTT_SUCCESS;
|
||||
} else {
|
||||
*len = 0;
|
||||
return LWMQTT_VARNUM_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum) {
|
||||
// prepare last byte
|
||||
uint8_t byte;
|
||||
|
||||
// prepare multiplier
|
||||
uint32_t multiplier = 1;
|
||||
|
||||
// prepare length
|
||||
size_t len = 0;
|
||||
|
||||
// initialize number
|
||||
*varnum = 0;
|
||||
|
||||
// decode variadic number
|
||||
do {
|
||||
// increment length
|
||||
len++;
|
||||
|
||||
// return error if buffer is to small
|
||||
if ((size_t)(buf_end - (*buf)) < len) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// return error if the length has overflowed
|
||||
if (len > 4) {
|
||||
return LWMQTT_VARNUM_OVERFLOW;
|
||||
}
|
||||
|
||||
// read byte
|
||||
byte = (*buf)[len - 1];
|
||||
|
||||
// add byte to number
|
||||
*varnum += (byte & 127) * multiplier;
|
||||
|
||||
// increase multiplier
|
||||
multiplier *= 128;
|
||||
} while ((byte & 128) != 0);
|
||||
|
||||
// adjust pointer
|
||||
*buf += len;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum) {
|
||||
// init len counter
|
||||
size_t len = 0;
|
||||
|
||||
// encode variadic number
|
||||
do {
|
||||
// check overflow
|
||||
if (len == 4) {
|
||||
return LWMQTT_VARNUM_OVERFLOW;
|
||||
}
|
||||
|
||||
// return error if buffer is to small
|
||||
if ((size_t)(buf_end - (*buf)) < len + 1) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// calculate current byte
|
||||
uint8_t byte = (uint8_t)(varnum % 128);
|
||||
|
||||
// change remaining length
|
||||
varnum /= 128;
|
||||
|
||||
// set the top bit of this byte if there are more to encode
|
||||
if (varnum > 0) {
|
||||
byte |= 0x80;
|
||||
}
|
||||
|
||||
// write byte
|
||||
(*buf)[len++] = byte;
|
||||
} while (varnum > 0);
|
||||
|
||||
// adjust pointer
|
||||
*buf += len;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
137
P1_gateway_FW/lib/MQTT/src/lwmqtt/helpers.h
Normal file
137
P1_gateway_FW/lib/MQTT/src/lwmqtt/helpers.h
Normal file
@@ -0,0 +1,137 @@
|
||||
#ifndef LWMQTT_HELPERS_H
|
||||
#define LWMQTT_HELPERS_H
|
||||
|
||||
#include "lwmqtt.h"
|
||||
|
||||
/**
|
||||
* Reads bits from a byte.
|
||||
*
|
||||
* @param byte - The byte to read from.
|
||||
* @param pos - The position of the first bit.
|
||||
* @param num - The number of bits to read.
|
||||
* @return The read bits as a byte.
|
||||
*/
|
||||
uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num);
|
||||
|
||||
/**
|
||||
* Write bits to a byte.
|
||||
*
|
||||
* @param byte - The byte to write bits to.
|
||||
* @param value - The bits to write as a byte.
|
||||
* @param pos - The position of the first bit.
|
||||
* @param num - The number of bits to write.
|
||||
*/
|
||||
void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num);
|
||||
|
||||
/**
|
||||
* Reads arbitrary data from the specified buffer. The pointer is incremented by bytes read.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param data - Pointer to beginning of data.
|
||||
* @param len - The amount of data to read.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len);
|
||||
|
||||
/**
|
||||
* Writes arbitrary data to the specified buffer. The pointer is incremented by the bytes written.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param data - Pointer to the to be written data.
|
||||
* @param len - The amount of data to write.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* Reads two byte number from the specified buffer. The pointer is incremented by two.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param num - The read number.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num);
|
||||
|
||||
/**
|
||||
* Writes a two byte number to the specified buffer. The pointer is incremented by two.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param num - The number to write.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num);
|
||||
|
||||
/**
|
||||
* Reads a string from the specified buffer into the passed object. The pointer is incremented by the bytes read.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param str - The object into which the data is to be read.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str);
|
||||
|
||||
/**
|
||||
* Writes a string to the specified buffer. The pointer is incremented by the bytes written.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param str - The string to write.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str);
|
||||
|
||||
/**
|
||||
* Reads one byte from the buffer. The pointer is incremented by one.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param byte - The read byte.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte);
|
||||
|
||||
/**
|
||||
* Writes one byte to the specified buffer. The pointer is incremented by one.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param byte - The byte to write.
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte);
|
||||
|
||||
/**
|
||||
* Returns the amount of bytes required by the variable number.
|
||||
*
|
||||
* @param varnum - The number to check.
|
||||
* @param len - The required length;
|
||||
* @return LWMQTT_SUCCESS or LWMQTT_VARNUM_OVERFLOW.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len);
|
||||
|
||||
/**
|
||||
* Reads a variable number from the specified buffer. The pointer is incremented by the bytes read.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param varnum - The read varnum.
|
||||
* @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum);
|
||||
|
||||
/**
|
||||
* Writes a variable number to the specified buffer. The pointer is incremented by the bytes written.
|
||||
*
|
||||
* @param buf - Pointer to the buffer.
|
||||
* @param buf_end - Pointer to the end of the buffer.
|
||||
* @param varnum - The number to write.
|
||||
* @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum);
|
||||
|
||||
#endif
|
||||
381
P1_gateway_FW/lib/MQTT/src/lwmqtt/lwmqtt.h
Normal file
381
P1_gateway_FW/lib/MQTT/src/lwmqtt/lwmqtt.h
Normal file
@@ -0,0 +1,381 @@
|
||||
#ifndef LWMQTT_H
|
||||
#define LWMQTT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* The error type used by all exposed APIs.
|
||||
*
|
||||
* If a function returns an error that operates on a connected client (e.g publish, keep_alive, etc.) the caller should
|
||||
* switch into a disconnected state, close and cleanup the current connection and start over by creating a new
|
||||
* connection.
|
||||
*/
|
||||
typedef enum {
|
||||
LWMQTT_SUCCESS = 0,
|
||||
LWMQTT_BUFFER_TOO_SHORT = -1,
|
||||
LWMQTT_VARNUM_OVERFLOW = -2,
|
||||
LWMQTT_NETWORK_FAILED_CONNECT = -3,
|
||||
LWMQTT_NETWORK_TIMEOUT = -4,
|
||||
LWMQTT_NETWORK_FAILED_READ = -5,
|
||||
LWMQTT_NETWORK_FAILED_WRITE = -6,
|
||||
LWMQTT_REMAINING_LENGTH_OVERFLOW = -7,
|
||||
LWMQTT_REMAINING_LENGTH_MISMATCH = -8,
|
||||
LWMQTT_MISSING_OR_WRONG_PACKET = -9,
|
||||
LWMQTT_CONNECTION_DENIED = -10,
|
||||
LWMQTT_FAILED_SUBSCRIPTION = -11,
|
||||
LWMQTT_SUBACK_ARRAY_OVERFLOW = -12,
|
||||
LWMQTT_PONG_TIMEOUT = -13,
|
||||
} lwmqtt_err_t;
|
||||
|
||||
/**
|
||||
* A common string object.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t len;
|
||||
char *data;
|
||||
} lwmqtt_string_t;
|
||||
|
||||
/**
|
||||
* The initializer for string objects.
|
||||
*/
|
||||
#define lwmqtt_default_string \
|
||||
{ 0, NULL }
|
||||
|
||||
/**
|
||||
* Returns a string object for the passed C string.
|
||||
*
|
||||
* @param str - The C string.
|
||||
* @return A string object.
|
||||
*/
|
||||
lwmqtt_string_t lwmqtt_string(const char *str);
|
||||
|
||||
/**
|
||||
* Compares a string object to a C string.
|
||||
*
|
||||
* @param a - The string object to compare.
|
||||
* @param b - The C string to compare.
|
||||
* @return Similarity e.g. strcmp().
|
||||
*/
|
||||
int lwmqtt_strcmp(lwmqtt_string_t a, const char *b);
|
||||
|
||||
/**
|
||||
* The available QOS levels.
|
||||
*/
|
||||
typedef enum { LWMQTT_QOS0 = 0, LWMQTT_QOS1 = 1, LWMQTT_QOS2 = 2, LWMQTT_QOS_FAILURE = 128 } lwmqtt_qos_t;
|
||||
|
||||
/**
|
||||
* The message object used to publish and receive messages.
|
||||
*/
|
||||
typedef struct {
|
||||
lwmqtt_qos_t qos;
|
||||
bool retained;
|
||||
uint8_t *payload;
|
||||
size_t payload_len;
|
||||
} lwmqtt_message_t;
|
||||
|
||||
/**
|
||||
* The initializer for message objects.
|
||||
*/
|
||||
#define lwmqtt_default_message \
|
||||
{ LWMQTT_QOS0, false, NULL, 0 }
|
||||
|
||||
/**
|
||||
* Forward declaration of the client object.
|
||||
*/
|
||||
typedef struct lwmqtt_client_t lwmqtt_client_t;
|
||||
|
||||
/**
|
||||
* The callback used to read from a network object.
|
||||
*
|
||||
* The callbacks is expected to read up to the amount of bytes in to the passed buffer. It should block the specified
|
||||
* timeout and wait for more incoming data.
|
||||
*
|
||||
* @param ref - A custom reference.
|
||||
* @param buf - The buffer.
|
||||
* @param len - The length of the buffer.
|
||||
* @param read - Variable that must be set with the amount of read bytes.
|
||||
* @param timeout - The timeout in milliseconds for the operation.
|
||||
*/
|
||||
typedef lwmqtt_err_t (*lwmqtt_network_read_t)(void *ref, uint8_t *buf, size_t len, size_t *read, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* The callback used to write to a network object.
|
||||
*
|
||||
* The callback is expected to write up to the amount of bytes from the passed buffer. It should wait up to the
|
||||
* specified timeout to write the specified data to the network.
|
||||
*
|
||||
* @param ref - A custom reference.
|
||||
* @param buf - The buffer.
|
||||
* @param len - The length of the buffer.
|
||||
* @param sent - Variable that must be set with the amount of written bytes.
|
||||
* @param timeout - The timeout in milliseconds for the operation.
|
||||
*/
|
||||
typedef lwmqtt_err_t (*lwmqtt_network_write_t)(void *ref, uint8_t *buf, size_t len, size_t *sent, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* The callback used to set a timer.
|
||||
*
|
||||
* @param ref - A custom reference.
|
||||
* @param timeout - The amount of milliseconds until the deadline.
|
||||
*/
|
||||
typedef void (*lwmqtt_timer_set_t)(void *ref, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* The callback used to get a timers value.
|
||||
*
|
||||
* @param - A custom reference.
|
||||
* @return The amount of milliseconds until the deadline. May return negative numbers if the deadline has been reached.
|
||||
*/
|
||||
typedef int32_t (*lwmqtt_timer_get_t)(void *ref);
|
||||
|
||||
/**
|
||||
* The callback used to forward incoming messages.
|
||||
*
|
||||
* Note: The callback is mostly executed because of a call to lwmqtt_yield() that processes incoming messages. However,
|
||||
* it is possible that the callback is also executed during a call to lwmqtt_subscribe(), lwmqtt_publish() or
|
||||
* lwmqtt_unsubscribe() if incoming messages are received between the required acknowledgements. It is therefore not
|
||||
* recommended to call any further lwmqtt methods in the callback as this might result in weird call stacks. The
|
||||
* callback should place the received messages in a queue and dispatch them after the caller has returned.
|
||||
*/
|
||||
typedef void (*lwmqtt_callback_t)(lwmqtt_client_t *client, void *ref, lwmqtt_string_t str, lwmqtt_message_t msg);
|
||||
|
||||
/**
|
||||
* The client object.
|
||||
*/
|
||||
struct lwmqtt_client_t {
|
||||
uint16_t last_packet_id;
|
||||
uint32_t keep_alive_interval;
|
||||
bool pong_pending;
|
||||
|
||||
size_t write_buf_size, read_buf_size;
|
||||
uint8_t *write_buf, *read_buf;
|
||||
|
||||
lwmqtt_callback_t callback;
|
||||
void *callback_ref;
|
||||
|
||||
void *network;
|
||||
lwmqtt_network_read_t network_read;
|
||||
lwmqtt_network_write_t network_write;
|
||||
|
||||
void *keep_alive_timer;
|
||||
void *command_timer;
|
||||
lwmqtt_timer_set_t timer_set;
|
||||
lwmqtt_timer_get_t timer_get;
|
||||
};
|
||||
|
||||
/**
|
||||
* Will initialize the specified client object.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param write_buf - The write buffer.
|
||||
* @param write_buf_size - The write buffer size.
|
||||
* @param read_buf - The read buffer.
|
||||
* @param read_buf_size - The read buffer size.
|
||||
*/
|
||||
void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf,
|
||||
size_t read_buf_size);
|
||||
|
||||
/**
|
||||
* Will set the network reference and callbacks for this client object.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param ref - The reference to the network object.
|
||||
* @param read - The read callback.
|
||||
* @param write - The write callback.
|
||||
*/
|
||||
void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write);
|
||||
|
||||
/**
|
||||
* Will set the timer references and callbacks for this client object.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param keep_alive_timer - The reference to the keep alive timer.
|
||||
* @param command_timer - The reference to the command timer.
|
||||
* @param set - The set callback.
|
||||
* @param get - The get callback.
|
||||
*/
|
||||
void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set,
|
||||
lwmqtt_timer_get_t get);
|
||||
|
||||
/**
|
||||
* Will set the callback used to receive incoming messages.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param ref - A custom reference that will passed to the callback.
|
||||
* @param cb - The callback to be called.
|
||||
*/
|
||||
void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb);
|
||||
|
||||
/**
|
||||
* The object defining the last will of a client.
|
||||
*/
|
||||
typedef struct {
|
||||
lwmqtt_string_t topic;
|
||||
lwmqtt_qos_t qos;
|
||||
bool retained;
|
||||
lwmqtt_string_t payload;
|
||||
} lwmqtt_will_t;
|
||||
|
||||
/**
|
||||
* The default initializer for the will object.
|
||||
*/
|
||||
#define lwmqtt_default_will \
|
||||
{ lwmqtt_default_string, LWMQTT_QOS0, false, lwmqtt_default_string }
|
||||
|
||||
/**
|
||||
* The object containing the connection options for a client.
|
||||
*/
|
||||
typedef struct {
|
||||
lwmqtt_string_t client_id;
|
||||
uint16_t keep_alive;
|
||||
bool clean_session;
|
||||
lwmqtt_string_t username;
|
||||
lwmqtt_string_t password;
|
||||
} lwmqtt_options_t;
|
||||
|
||||
/**
|
||||
* The default initializer for the options object.
|
||||
*/
|
||||
#define lwmqtt_default_options \
|
||||
{ lwmqtt_default_string, 60, true, lwmqtt_default_string, lwmqtt_default_string }
|
||||
|
||||
/**
|
||||
* The available return codes transported by the connack packet.
|
||||
*/
|
||||
typedef enum {
|
||||
LWMQTT_CONNECTION_ACCEPTED = 0,
|
||||
LWMQTT_UNACCEPTABLE_PROTOCOL = 1,
|
||||
LWMQTT_IDENTIFIER_REJECTED = 2,
|
||||
LWMQTT_SERVER_UNAVAILABLE = 3,
|
||||
LWMQTT_BAD_USERNAME_OR_PASSWORD = 4,
|
||||
LWMQTT_NOT_AUTHORIZED = 5,
|
||||
LWMQTT_UNKNOWN_RETURN_CODE = 6
|
||||
} lwmqtt_return_code_t;
|
||||
|
||||
/**
|
||||
* Will send a connect packet and wait for a connack response and set the return code.
|
||||
*
|
||||
* The network object must already be connected to the server. An error is returned if the broker rejects the
|
||||
* connection.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param options - The options object.
|
||||
* @param will - The will object.
|
||||
* @param return_code - The variable that will receive the return code.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will,
|
||||
lwmqtt_return_code_t *return_code, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will send a publish packet and wait for all acks to complete.
|
||||
*
|
||||
* Note: The message callback might be called with incoming messages as part of this call.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param topic - The topic.
|
||||
* @param message - The message.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t msg, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will send a subscribe packet with multiple topic filters plus QOS levels and wait for the suback to complete.
|
||||
*
|
||||
* Note: The message callback might be called with incoming messages as part of this call.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param count - The number of topic filters and QOS levels.
|
||||
* @param topic_filter - The list of topic filters.
|
||||
* @param qos - The list of QOS levels.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos,
|
||||
uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will send a subscribe packet with a single topic filter plus QOS level and wait for the suback to complete.
|
||||
*
|
||||
* Note: The message callback might be called with incoming messages as part of this call.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param topic_filter - The topic filter.
|
||||
* @param qos - The QOS level.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos,
|
||||
uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will send an unsubscribe packet with multiple topic filters and wait for the unsuback to complete.
|
||||
*
|
||||
* Note: The message callback might be called with incoming messages as part of this call.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param count - The number of topic filters.
|
||||
* @param topic_filter - The topic filter.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will send an unsubscribe packet with a single topic filter and wait for the unsuback to complete.
|
||||
*
|
||||
* Note: The message callback might be called with incoming messages as part of this call.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param topic_filter - The topic filter.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will send a disconnect packet and finish the client.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will yield control to the client and receive incoming packets from the network.
|
||||
*
|
||||
* Single-threaded applications may peek on the network and assess if data is available to read before calling yield and
|
||||
* potentially block until the timeout is reached. Multi-threaded applications may select on the socket and block until
|
||||
* data is available and then yield to the client if data is available. All applications may specify the amount of bytes
|
||||
* available to read in order to constrain the yield to only receive packets that are already in-flight.
|
||||
*
|
||||
* If no availability info is given the yield will return after one packet has been successfully read or the deadline
|
||||
* has been reached but no single bytes has been received.
|
||||
*
|
||||
* Note: The message callback might be called with incoming messages as part of this call.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param available - The available bytes to read.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Will yield control to the client to keep the connection alive.
|
||||
*
|
||||
* This functions must be called at a rate slightly lower than 25% of the configured keep alive. If keep alive is zero,
|
||||
* the function must not be called at all.
|
||||
*
|
||||
* @param client - The client object.
|
||||
* @param timeout - The command timeout.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout);
|
||||
|
||||
#endif // LWMQTT_H
|
||||
742
P1_gateway_FW/lib/MQTT/src/lwmqtt/packet.c
Normal file
742
P1_gateway_FW/lib/MQTT/src/lwmqtt/packet.c
Normal file
@@ -0,0 +1,742 @@
|
||||
#include "packet.h"
|
||||
|
||||
lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type) {
|
||||
// set default packet type
|
||||
*packet_type = LWMQTT_NO_PACKET;
|
||||
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// prepare header
|
||||
uint8_t header;
|
||||
|
||||
// read header
|
||||
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// get packet type
|
||||
*packet_type = (lwmqtt_packet_type_t)lwmqtt_read_bits(header, 4, 4);
|
||||
|
||||
// check if packet type is correct and can be received
|
||||
switch (*packet_type) {
|
||||
case LWMQTT_CONNACK_PACKET:
|
||||
case LWMQTT_PUBLISH_PACKET:
|
||||
case LWMQTT_PUBACK_PACKET:
|
||||
case LWMQTT_PUBREC_PACKET:
|
||||
case LWMQTT_PUBREL_PACKET:
|
||||
case LWMQTT_PUBCOMP_PACKET:
|
||||
case LWMQTT_SUBACK_PACKET:
|
||||
case LWMQTT_UNSUBACK_PACKET:
|
||||
case LWMQTT_PINGRESP_PACKET:
|
||||
return LWMQTT_SUCCESS;
|
||||
default:
|
||||
*packet_type = LWMQTT_NO_PACKET;
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len) {
|
||||
// prepare pointer
|
||||
uint8_t *ptr = buf;
|
||||
|
||||
// attempt to decode remaining length
|
||||
lwmqtt_err_t err = lwmqtt_read_varnum(&ptr, buf + buf_len, rem_len);
|
||||
if (err == LWMQTT_VARNUM_OVERFLOW) {
|
||||
*rem_len = 0;
|
||||
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
|
||||
} else if (err != LWMQTT_SUCCESS) {
|
||||
*rem_len = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options,
|
||||
lwmqtt_will_t *will) {
|
||||
// prepare pointers
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// fixed header is 10
|
||||
uint32_t rem_len = 10;
|
||||
|
||||
// add client id to remaining length
|
||||
rem_len += options.client_id.len + 2;
|
||||
|
||||
// add will if present to remaining length
|
||||
if (will != NULL) {
|
||||
rem_len += will->topic.len + 2 + will->payload.len + 2;
|
||||
}
|
||||
|
||||
// add username if present to remaining length
|
||||
if (options.username.len > 0) {
|
||||
rem_len += options.username.len + 2;
|
||||
|
||||
// add password if present to remaining length
|
||||
if (options.password.len > 0) {
|
||||
rem_len += options.password.len + 2;
|
||||
}
|
||||
}
|
||||
|
||||
// check remaining length length
|
||||
int rem_len_len;
|
||||
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
|
||||
if (err == LWMQTT_VARNUM_OVERFLOW) {
|
||||
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
|
||||
}
|
||||
|
||||
// prepare header
|
||||
uint8_t header = 0;
|
||||
lwmqtt_write_bits(&header, LWMQTT_CONNECT_PACKET, 4, 4);
|
||||
|
||||
// write header
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write remaining length
|
||||
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write version string
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, lwmqtt_string("MQTT"));
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write version number
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, 4);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// prepare flags
|
||||
uint8_t flags = 0;
|
||||
|
||||
// set clean session
|
||||
lwmqtt_write_bits(&flags, (uint8_t)(options.clean_session), 1, 1);
|
||||
|
||||
// set will flags if present
|
||||
if (will != NULL) {
|
||||
lwmqtt_write_bits(&flags, 1, 2, 1);
|
||||
lwmqtt_write_bits(&flags, will->qos, 3, 2);
|
||||
lwmqtt_write_bits(&flags, (uint8_t)(will->retained), 5, 1);
|
||||
}
|
||||
|
||||
// set username flag if present
|
||||
if (options.username.len > 0) {
|
||||
lwmqtt_write_bits(&flags, 1, 7, 1);
|
||||
|
||||
// set password flag if present
|
||||
if (options.password.len > 0) {
|
||||
lwmqtt_write_bits(&flags, 1, 6, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// write flags
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, flags);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write keep alive
|
||||
err = lwmqtt_write_num(&buf_ptr, buf_end, options.keep_alive);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write client id
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, options.client_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write will if present
|
||||
if (will != NULL) {
|
||||
// write topic
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, will->topic);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write payload length
|
||||
err = lwmqtt_write_num(&buf_ptr, buf_end, (uint16_t)will->payload.len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write payload
|
||||
err = lwmqtt_write_data(&buf_ptr, buf_end, (uint8_t *)will->payload.data, will->payload.len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// write username if present
|
||||
if (options.username.len > 0) {
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, options.username);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// write password if present
|
||||
if (options.username.len > 0 && options.password.len > 0) {
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, options.password);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// set written length
|
||||
*len = buf_ptr - buf;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present,
|
||||
lwmqtt_return_code_t *return_code) {
|
||||
// prepare pointers
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// read header
|
||||
uint8_t header;
|
||||
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check packet type
|
||||
if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_CONNACK_PACKET) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// read remaining length
|
||||
uint32_t rem_len;
|
||||
err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check remaining length
|
||||
if (rem_len != 2) {
|
||||
return LWMQTT_REMAINING_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
// read flags
|
||||
uint8_t flags;
|
||||
err = lwmqtt_read_byte(&buf_ptr, buf_end, &flags);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// read return code
|
||||
uint8_t raw_return_code;
|
||||
err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_return_code);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// get session present
|
||||
*session_present = lwmqtt_read_bits(flags, 7, 1) == 1;
|
||||
|
||||
// get return code
|
||||
switch (raw_return_code) {
|
||||
case 0:
|
||||
*return_code = LWMQTT_CONNECTION_ACCEPTED;
|
||||
break;
|
||||
case 1:
|
||||
*return_code = LWMQTT_UNACCEPTABLE_PROTOCOL;
|
||||
break;
|
||||
case 2:
|
||||
*return_code = LWMQTT_IDENTIFIER_REJECTED;
|
||||
break;
|
||||
case 3:
|
||||
*return_code = LWMQTT_SERVER_UNAVAILABLE;
|
||||
break;
|
||||
case 4:
|
||||
*return_code = LWMQTT_BAD_USERNAME_OR_PASSWORD;
|
||||
break;
|
||||
case 5:
|
||||
*return_code = LWMQTT_NOT_AUTHORIZED;
|
||||
break;
|
||||
default:
|
||||
*return_code = LWMQTT_UNKNOWN_RETURN_CODE;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// write header
|
||||
uint8_t header = 0;
|
||||
lwmqtt_write_bits(&header, packet_type, 4, 4);
|
||||
lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write remaining length
|
||||
err = lwmqtt_write_varnum(&buf_ptr, buf_end, 0);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// set length
|
||||
*len = buf_ptr - buf;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup,
|
||||
uint16_t *packet_id) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// read header
|
||||
uint8_t header = 0;
|
||||
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check packet type
|
||||
if (lwmqtt_read_bits(header, 4, 4) != packet_type) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// get dup
|
||||
*dup = lwmqtt_read_bits(header, 3, 1) == 1;
|
||||
|
||||
// read remaining length
|
||||
uint32_t rem_len;
|
||||
err = lwmqtt_read_varnum(&buf_ptr, buf + buf_len, &rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check remaining length
|
||||
if (rem_len != 2) {
|
||||
return LWMQTT_REMAINING_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
// read packet id
|
||||
err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup,
|
||||
uint16_t packet_id) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// prepare header
|
||||
uint8_t header = 0;
|
||||
|
||||
// set packet type
|
||||
lwmqtt_write_bits(&header, packet_type, 4, 4);
|
||||
|
||||
// set dup
|
||||
lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1);
|
||||
|
||||
// set qos
|
||||
lwmqtt_write_bits(&header, (uint8_t)(packet_type == LWMQTT_PUBREL_PACKET ? LWMQTT_QOS1 : LWMQTT_QOS0), 1, 2);
|
||||
|
||||
// write header
|
||||
lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write remaining length
|
||||
err = lwmqtt_write_varnum(&buf_ptr, buf_end, 2);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write packet id
|
||||
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// set written length
|
||||
*len = buf_ptr - buf;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic,
|
||||
lwmqtt_message_t *msg) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// read header
|
||||
uint8_t header;
|
||||
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check packet type
|
||||
if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_PUBLISH_PACKET) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// get dup
|
||||
*dup = lwmqtt_read_bits(header, 3, 1) == 1;
|
||||
|
||||
// get retained
|
||||
msg->retained = lwmqtt_read_bits(header, 0, 1) == 1;
|
||||
|
||||
// get qos
|
||||
switch (lwmqtt_read_bits(header, 1, 2)) {
|
||||
case 0:
|
||||
msg->qos = LWMQTT_QOS0;
|
||||
break;
|
||||
case 1:
|
||||
msg->qos = LWMQTT_QOS1;
|
||||
break;
|
||||
case 2:
|
||||
msg->qos = LWMQTT_QOS2;
|
||||
break;
|
||||
default:
|
||||
msg->qos = LWMQTT_QOS0;
|
||||
break;
|
||||
}
|
||||
|
||||
// read remaining length
|
||||
uint32_t rem_len;
|
||||
err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check remaining length (topic length)
|
||||
if (rem_len < 2) {
|
||||
return LWMQTT_REMAINING_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
// check buffer capacity
|
||||
if ((uint32_t)(buf_end - buf_ptr) < rem_len) {
|
||||
return LWMQTT_BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
// reset buf end
|
||||
buf_end = buf_ptr + rem_len;
|
||||
|
||||
// read topic
|
||||
err = lwmqtt_read_string(&buf_ptr, buf_end, topic);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// read packet id if qos is at least 1
|
||||
if (msg->qos > 0) {
|
||||
err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
*packet_id = 0;
|
||||
}
|
||||
|
||||
// set payload length
|
||||
msg->payload_len = buf_end - buf_ptr;
|
||||
|
||||
// read payload
|
||||
err = lwmqtt_read_data(&buf_ptr, buf_end, &msg->payload, buf_end - buf_ptr);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id,
|
||||
lwmqtt_string_t topic, lwmqtt_message_t msg) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// calculate remaining length
|
||||
uint32_t rem_len = 2 + topic.len + (uint32_t)msg.payload_len;
|
||||
if (msg.qos > 0) {
|
||||
rem_len += 2;
|
||||
}
|
||||
|
||||
// check remaining length length
|
||||
int rem_len_len;
|
||||
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
|
||||
if (err == LWMQTT_VARNUM_OVERFLOW) {
|
||||
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
|
||||
}
|
||||
|
||||
// prepare header
|
||||
uint8_t header = 0;
|
||||
|
||||
// set packet type
|
||||
lwmqtt_write_bits(&header, LWMQTT_PUBLISH_PACKET, 4, 4);
|
||||
|
||||
// set dup
|
||||
lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1);
|
||||
|
||||
// set qos
|
||||
lwmqtt_write_bits(&header, msg.qos, 1, 2);
|
||||
|
||||
// set retained
|
||||
lwmqtt_write_bits(&header, (uint8_t)(msg.retained), 0, 1);
|
||||
|
||||
// write header
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write remaining length
|
||||
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write topic
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, topic);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write packet id if qos is at least 1
|
||||
if (msg.qos > 0) {
|
||||
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// write payload
|
||||
err = lwmqtt_write_data(&buf_ptr, buf_end, msg.payload, msg.payload_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// set length
|
||||
*len = buf_ptr - buf;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
|
||||
lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// calculate remaining length
|
||||
uint32_t rem_len = 2;
|
||||
for (int i = 0; i < count; i++) {
|
||||
rem_len += 2 + topic_filters[i].len + 1;
|
||||
}
|
||||
|
||||
// check remaining length length
|
||||
int rem_len_len;
|
||||
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
|
||||
if (err == LWMQTT_VARNUM_OVERFLOW) {
|
||||
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
|
||||
}
|
||||
|
||||
// prepare header
|
||||
uint8_t header = 0;
|
||||
|
||||
// set packet type
|
||||
lwmqtt_write_bits(&header, LWMQTT_SUBSCRIBE_PACKET, 4, 4);
|
||||
|
||||
// set qos
|
||||
lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2);
|
||||
|
||||
// write header
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write remaining length
|
||||
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write packet id
|
||||
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write all subscriptions
|
||||
for (int i = 0; i < count; i++) {
|
||||
// write topic
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write qos level
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, (uint8_t)qos_levels[i]);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// set length
|
||||
*len = buf_ptr - buf;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count,
|
||||
lwmqtt_qos_t *granted_qos_levels) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// read header
|
||||
uint8_t header;
|
||||
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check packet type
|
||||
if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_SUBACK_PACKET) {
|
||||
return LWMQTT_MISSING_OR_WRONG_PACKET;
|
||||
}
|
||||
|
||||
// read remaining length
|
||||
uint32_t rem_len;
|
||||
err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// check remaining length (packet id + min. one suback code)
|
||||
if (rem_len < 3) {
|
||||
return LWMQTT_REMAINING_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
// read packet id
|
||||
err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// read all suback codes
|
||||
for (*count = 0; *count < (int)rem_len - 2; (*count)++) {
|
||||
// check max count
|
||||
if (*count > max_count) {
|
||||
return LWMQTT_SUBACK_ARRAY_OVERFLOW;
|
||||
}
|
||||
|
||||
// read qos level
|
||||
uint8_t raw_qos_level;
|
||||
err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_qos_level);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// set qos level
|
||||
switch (raw_qos_level) {
|
||||
case 0:
|
||||
granted_qos_levels[*count] = LWMQTT_QOS0;
|
||||
break;
|
||||
case 1:
|
||||
granted_qos_levels[*count] = LWMQTT_QOS1;
|
||||
break;
|
||||
case 2:
|
||||
granted_qos_levels[*count] = LWMQTT_QOS2;
|
||||
break;
|
||||
default:
|
||||
granted_qos_levels[*count] = LWMQTT_QOS_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
|
||||
lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
|
||||
lwmqtt_string_t *topic_filters) {
|
||||
// prepare pointer
|
||||
uint8_t *buf_ptr = buf;
|
||||
uint8_t *buf_end = buf + buf_len;
|
||||
|
||||
// calculate remaining length
|
||||
uint32_t rem_len = 2;
|
||||
for (int i = 0; i < count; i++) {
|
||||
rem_len += 2 + topic_filters[i].len;
|
||||
}
|
||||
|
||||
// check remaining length length
|
||||
int rem_len_len;
|
||||
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
|
||||
if (err == LWMQTT_VARNUM_OVERFLOW) {
|
||||
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
|
||||
}
|
||||
|
||||
// prepare header
|
||||
uint8_t header = 0;
|
||||
|
||||
// set packet type
|
||||
lwmqtt_write_bits(&header, LWMQTT_UNSUBSCRIBE_PACKET, 4, 4);
|
||||
|
||||
// set qos
|
||||
lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2);
|
||||
|
||||
// write header
|
||||
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write remaining length
|
||||
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write packet id
|
||||
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// write topics
|
||||
for (int i = 0; i < count; i++) {
|
||||
err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]);
|
||||
if (err != LWMQTT_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// set length
|
||||
*len = buf_ptr - buf;
|
||||
|
||||
return LWMQTT_SUCCESS;
|
||||
}
|
||||
185
P1_gateway_FW/lib/MQTT/src/lwmqtt/packet.h
Normal file
185
P1_gateway_FW/lib/MQTT/src/lwmqtt/packet.h
Normal file
@@ -0,0 +1,185 @@
|
||||
#ifndef LWMQTT_PACKET_H
|
||||
#define LWMQTT_PACKET_H
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
/**
|
||||
* The available packet types.
|
||||
*/
|
||||
typedef enum {
|
||||
LWMQTT_NO_PACKET = 0,
|
||||
LWMQTT_CONNECT_PACKET = 1,
|
||||
LWMQTT_CONNACK_PACKET,
|
||||
LWMQTT_PUBLISH_PACKET,
|
||||
LWMQTT_PUBACK_PACKET,
|
||||
LWMQTT_PUBREC_PACKET,
|
||||
LWMQTT_PUBREL_PACKET,
|
||||
LWMQTT_PUBCOMP_PACKET,
|
||||
LWMQTT_SUBSCRIBE_PACKET,
|
||||
LWMQTT_SUBACK_PACKET,
|
||||
LWMQTT_UNSUBSCRIBE_PACKET,
|
||||
LWMQTT_UNSUBACK_PACKET,
|
||||
LWMQTT_PINGREQ_PACKET,
|
||||
LWMQTT_PINGRESP_PACKET,
|
||||
LWMQTT_DISCONNECT_PACKET
|
||||
} lwmqtt_packet_type_t;
|
||||
|
||||
/**
|
||||
* Will detect the packet type from the at least one byte long buffer.
|
||||
*
|
||||
* @param buf - The buffer from which the packet type will be detected.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param packet_type - The packet type.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type);
|
||||
|
||||
/**
|
||||
* Will detect the remaining length form the at least on byte long buffer.
|
||||
*
|
||||
* It will return LWMQTT_BUFFER_TOO_SHORT if the buffer is to short and an additional byte should be read from the
|
||||
* network. In case the remaining length is overflowed it will return LWMQTT_REMAINING_LENGTH_OVERFLOW.
|
||||
*
|
||||
* @param buf - The buffer from which the remaining length will be detected.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param rem_len - The detected remaining length.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len);
|
||||
|
||||
/**
|
||||
* Encodes a connect packet into the supplied buffer.
|
||||
*
|
||||
* @param buf - The buffer into which the packet will be encoded.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param len - The encoded length of the packet.
|
||||
* @param options - The options to be used to build the connect packet.
|
||||
* @param will - The last will and testament.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options,
|
||||
lwmqtt_will_t *will);
|
||||
|
||||
/**
|
||||
* Decodes a connack packet from the supplied buffer.
|
||||
*
|
||||
* @param buf - The raw buffer data.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param session_present - The session present flag.
|
||||
* @param return_code - The return code.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present,
|
||||
lwmqtt_return_code_t *return_code);
|
||||
|
||||
/**
|
||||
* Encodes a zero (disconnect, pingreq) packet into the supplied buffer.
|
||||
*
|
||||
* @param buf - The buffer into which the packet will be encoded.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param len - The encoded length of the packet.
|
||||
* @param packet_type - The packets type.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type);
|
||||
|
||||
/**
|
||||
* Decodes an ack (puback, pubrec, pubrel, pubcomp, unsuback) packet from the supplied buffer.
|
||||
*
|
||||
* @param buf - The raw buffer data.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param packet_type - The packet type.
|
||||
* @param dup - The dup flag.
|
||||
* @param packet_id - The packet id.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup,
|
||||
uint16_t *packet_id);
|
||||
|
||||
/**
|
||||
* Encodes an ack (puback, pubrec, pubrel, pubcomp) packet into the supplied buffer.
|
||||
*
|
||||
* @param buf - The buffer into which the packet will be encoded.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param len - The encoded length of the packet.
|
||||
* @param packet_type - The packets type.
|
||||
* @param dup - The dup flag.
|
||||
* @param packet_id - The packet id.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup,
|
||||
uint16_t packet_id);
|
||||
|
||||
/**
|
||||
* Decodes a publish packet from the supplied buffer.
|
||||
*
|
||||
* @param buf - The raw buffer data.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param dup - The dup flag.
|
||||
* @param packet_id - The packet id.
|
||||
* @param topic - The topic.
|
||||
* @parma msg - The message.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic,
|
||||
lwmqtt_message_t *msg);
|
||||
|
||||
/**
|
||||
* Encodes a publish packet into the supplied buffer.
|
||||
*
|
||||
* @param buf - The buffer into which the packet will be encoded.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param len - The encoded length of the packet.
|
||||
* @param dup - The dup flag.
|
||||
* @param packet_id - The packet id.
|
||||
* @param topic - The topic.
|
||||
* @param msg - The message.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id,
|
||||
lwmqtt_string_t topic, lwmqtt_message_t msg);
|
||||
|
||||
/**
|
||||
* Encodes a subscribe packet into the supplied buffer.
|
||||
*
|
||||
* @param buf - The buffer into which the packet will be encoded.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param len - The encoded length of the packet.
|
||||
* @param packet_id - The packet id.
|
||||
* @param count - The number of members in the topic_filters and qos_levels array.
|
||||
* @param topic_filters - The array of topic filter.
|
||||
* @param qos_levels - The array of requested QoS levels.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
|
||||
lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels);
|
||||
|
||||
/**
|
||||
* Decodes a suback packet from the supplied buffer.
|
||||
*
|
||||
* @param buf - The raw buffer data.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param packet_id - The packet id.
|
||||
* @param max_count - The maximum number of members allowed in the granted_qos_levels array.
|
||||
* @param count - The number of members in the granted_qos_levels array.
|
||||
* @param granted_qos_levels - The granted QoS levels.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count,
|
||||
lwmqtt_qos_t *granted_qos_levels);
|
||||
|
||||
/**
|
||||
* Encodes the supplied unsubscribe data into the supplied buffer, ready for sending
|
||||
*
|
||||
* @param buf - The buffer into which the packet will be encoded.
|
||||
* @param buf_len - The length of the specified buffer.
|
||||
* @param len - The encoded length of the packet.
|
||||
* @param packet_id - The packet id.
|
||||
* @param count - The number of members in the topic_filters array.
|
||||
* @param topic_filters - The array of topic filters.
|
||||
* @return An error value.
|
||||
*/
|
||||
lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
|
||||
lwmqtt_string_t *topic_filters);
|
||||
|
||||
#endif // LWMQTT_PACKET_H
|
||||
38
P1_gateway_FW/lib/MQTT/src/lwmqtt/string.c
Normal file
38
P1_gateway_FW/lib/MQTT/src/lwmqtt/string.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "lwmqtt.h"
|
||||
|
||||
lwmqtt_string_t lwmqtt_string(const char *str) {
|
||||
// check for null
|
||||
if (str == NULL) {
|
||||
return (lwmqtt_string_t){0, NULL};
|
||||
}
|
||||
|
||||
// get length
|
||||
uint16_t len = (uint16_t)strlen(str);
|
||||
|
||||
// check zero length
|
||||
if (len == 0) {
|
||||
return (lwmqtt_string_t){0, NULL};
|
||||
}
|
||||
|
||||
return (lwmqtt_string_t){len, (char *)str};
|
||||
}
|
||||
|
||||
int lwmqtt_strcmp(lwmqtt_string_t a, const char *b) {
|
||||
// get string of b
|
||||
lwmqtt_string_t b_str = lwmqtt_string(b);
|
||||
|
||||
// return if both are zero length
|
||||
if (a.len == 0 && b_str.len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return if lengths are different
|
||||
if (a.len != b_str.len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// compare memory of same length
|
||||
return strncmp(a.data, b_str.data, a.len);
|
||||
}
|
||||
Reference in New Issue
Block a user