add MqttLogger
This commit is contained in:
20
lib/MqttLogger/LICENSE.txt
Normal file
20
lib/MqttLogger/LICENSE.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2008-2020 Nicholas O'Leary
|
||||
|
||||
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.
|
||||
71
lib/MqttLogger/README.md
Normal file
71
lib/MqttLogger/README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Remote logging to a MQTT server with the same print() interface as Serial
|
||||
|
||||
This library provides an object that can be used just like `Serial` for printing logs,
|
||||
however the text sent with `print()` etc. is published on a MQTT broker instead of
|
||||
printing over the Serial console. This comes in handy when working with devices like the
|
||||
ESP8266/ESP32 that are connected over WiFi. I use it for debugging my robots
|
||||
that are based on ESP32.
|
||||
|
||||
The library uses [PubSubClient](https://github.com/knolleary/pubsubclient) for sending
|
||||
the MQTT messages.
|
||||
|
||||
When no MQTT connection is available, the `MqttLogger` object behaves just like
|
||||
`Serial`, i.e. your `print()` text is shown on the `Serial` console. The logger offers
|
||||
the following modes that can be passed as the third argument to the constructor
|
||||
when instantiating the object:
|
||||
|
||||
* `MqttLoggerMode::MqttAndSerialFallback` - this is the default mode. `print()` will
|
||||
publish to the MQTT server, and only when no MQTT connection is available `Serial`
|
||||
will be used. If you `print()` messages before the MQTT connection is established,
|
||||
these messages will be sent to the `Serial` console.
|
||||
* `MqttLoggerMode::MqttOnly` - no output on `Serial`. Beware: when no connection is
|
||||
available, no output is produced
|
||||
* `MqttLoggerMode::SerialOnly` - no messages are sent to the MQTT server. With this
|
||||
configuration `MqttLogger` can be used as a substitute for logging with `Serial`.
|
||||
* `MqttLoggerMode::MqttAndSerial` - messages are sent both to the MQTT server and to
|
||||
the `Serial` console.
|
||||
|
||||
## Examples
|
||||
|
||||
See directory `examples`. Currently there is only one example in directory `esp32`.
|
||||
|
||||
In this directory, rename the file `wifi_secrets.h.txt` to `wifi_secrets.h`
|
||||
and edit the file. Enter your WiFi ssid and password, the example uses this
|
||||
include file to set up your WiFi connection.
|
||||
|
||||
You'll need a MQTT broker to publish your messages to, I use [Mosquitto](https://mosquitto.org/)
|
||||
installed locally on my laptop. You can also use a free public service like
|
||||
`test.mosquitto.org` or `broker.hivemq.com`, but this makes logging slower
|
||||
(the messages have to be sent to and then downloaded from the online service). Also,
|
||||
make sure no private information is logged!
|
||||
|
||||
The broker url is defined by the constant `mqtt_server` in the example, use
|
||||
`localhost` if you have a local install as recommended.
|
||||
|
||||
For checking the mqtt logs events you'll use a MQTT client. The Mosquitto client
|
||||
can be invoked in a terminal like
|
||||
|
||||
mosquitto_sub -h localhost -t mqttlogger/log
|
||||
|
||||
but any other mqtt client will do (on Android try MQTT Dash, hivemq has a online
|
||||
version at (http://www.hivemq.com/demos/websocket-client/).
|
||||
|
||||
## Compatible Hardware
|
||||
|
||||
All devices that work with the PubSubClient should work with this libary, including:
|
||||
|
||||
- Arduino Ethernet
|
||||
- Arduino Ethernet Shield
|
||||
- Arduino YUN – use the included `YunClient` in place of `EthernetClient`, and
|
||||
be sure to do a `Bridge.begin()` first
|
||||
- Arduino WiFi Shield - if you want to send packets > 90 bytes with this shield,
|
||||
enable the `MQTT_MAX_TRANSFER_SIZE` define in `PubSubClient.h`.
|
||||
- Sparkfun WiFly Shield – [library](https://github.com/dpslwk/WiFly)
|
||||
- TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library)
|
||||
- Intel Galileo/Edison
|
||||
- ESP8266
|
||||
- ESP32
|
||||
|
||||
## License
|
||||
|
||||
This code is released under the MIT License.
|
||||
94
lib/MqttLogger/examples/esp32/esp32.ino
Normal file
94
lib/MqttLogger/examples/esp32/esp32.ino
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <MqttLogger.h>
|
||||
#include "wifi_secrets.h"
|
||||
|
||||
const char *ssid = WIFI_SSID;
|
||||
const char *password = WIFI_PASSWORD;
|
||||
const char *mqtt_server = "broker.hivemq.com";
|
||||
|
||||
WiFiClient espClient;
|
||||
PubSubClient client(espClient);
|
||||
|
||||
// default mode is MqttLoggerMode::MqttAndSerialFallback
|
||||
MqttLogger mqttLogger(client,"mqttlogger/log");
|
||||
// other available modes:
|
||||
// MqttLogger mqttLogger(client,"mqttlogger/log",MqttLoggerMode::MqttAndSerial);
|
||||
// MqttLogger mqttLogger(client,"mqttlogger/log",MqttLoggerMode::MqttOnly);
|
||||
// MqttLogger mqttLogger(client,"mqttlogger/log",MqttLoggerMode::SerialOnly);
|
||||
|
||||
// connect to wifi network
|
||||
void wifiConnect()
|
||||
{
|
||||
mqttLogger.print("Connecting to WiFi: ");
|
||||
mqttLogger.println(ssid);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
mqttLogger.print(".");
|
||||
}
|
||||
mqttLogger.print("WiFi connected: ");
|
||||
mqttLogger.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
// establish mqtt client connection
|
||||
void reconnect()
|
||||
{
|
||||
// Loop until we're reconnected
|
||||
while (!client.connected())
|
||||
{
|
||||
mqttLogger.print("Attempting MQTT connection...");
|
||||
// Attempt to connect
|
||||
if (client.connect("ESP32Logger"))
|
||||
{
|
||||
// as we have a connection here, this will be the first message published to the mqtt server
|
||||
mqttLogger.println("connected.");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mqttLogger.print("failed, rc=");
|
||||
mqttLogger.print(client.state());
|
||||
mqttLogger.println(" try again in 5 seconds");
|
||||
// Wait 5 seconds before retrying
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// arduino setup
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
// MqttLogger uses mqtt when available and Serial as a fallback. Before any connection is established,
|
||||
// MqttLogger works just like Serial
|
||||
mqttLogger.println("Starting setup..");
|
||||
|
||||
// connect to wifi
|
||||
wifiConnect();
|
||||
|
||||
// mqtt client
|
||||
client.setServer(mqtt_server, 1883);
|
||||
//client.setCallback(mqttIncomingCallback);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// here the mqtt connection is established
|
||||
if (!client.connected())
|
||||
{
|
||||
reconnect();
|
||||
}
|
||||
// with a connection, subsequent print() publish on the mqtt broker, but in a buffered fashion
|
||||
|
||||
mqttLogger.print(millis()/1000);
|
||||
delay(1000);
|
||||
mqttLogger.print(" seconds");
|
||||
delay(1000);
|
||||
mqttLogger.print(" online");
|
||||
delay(1000);
|
||||
// this finally flushes the buffer and published on the mqtt broker
|
||||
mqttLogger.println();
|
||||
}
|
||||
3
lib/MqttLogger/examples/esp32/wifi_secrets.h.txt
Normal file
3
lib/MqttLogger/examples/esp32/wifi_secrets.h.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
// rename this file to wifi_secrets.h and provide the wifi secrets below
|
||||
#define WIFI_SSID "your wifi ssid here"
|
||||
#define WIFI_PASSWORD "your wifi password here"
|
||||
18
lib/MqttLogger/library.json
Normal file
18
lib/MqttLogger/library.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "MqttLogger",
|
||||
"keywords": "serial, mqtt, logging",
|
||||
"description": "Remote logging on a mqtt broker with the same interface as Serial.print().",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/androbi-com/MqttLogger.git"
|
||||
},
|
||||
"version": "0.2.3",
|
||||
"exclude": "examples/*/wifi_secrets.h",
|
||||
"examples": "examples/*/*.ino",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
]
|
||||
}
|
||||
11
lib/MqttLogger/library.properties
Normal file
11
lib/MqttLogger/library.properties
Normal file
@@ -0,0 +1,11 @@
|
||||
name=MqttLogger
|
||||
version=0.2.3
|
||||
author=androbi <info@androbi.com>
|
||||
maintainer=androbi <info@androbi.co>
|
||||
sentence=Remote logging on a mqtt broker with the same interface as Serial.print()
|
||||
paragraph=This library is a substitute for Serial as a logging/debug tool when your device has an internet connection (ESP32 etc.) and is not connected over the serial port. The text written by the print() commands is published to a given topic on a MQTT broker. By subscribing to the same topic you can display the log messages remotely. When no MQTT connection is available, Serial is used as a fallback.
|
||||
category=Communication
|
||||
url=https://github.com/androbi-com/MqttLogger
|
||||
architectures=*
|
||||
includes=MqttLogger.h
|
||||
depends=PubSubClient
|
||||
116
lib/MqttLogger/src/MqttLogger.cpp
Normal file
116
lib/MqttLogger/src/MqttLogger.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "MqttLogger.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
MqttLogger::MqttLogger(MqttLoggerMode mode)
|
||||
{
|
||||
this->setMode(mode);
|
||||
this->setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
MqttLogger::MqttLogger(PubSubClient& client, const char* topic, MqttLoggerMode mode)
|
||||
{
|
||||
this->setClient(client);
|
||||
this->setTopic(topic);
|
||||
this->setMode(mode);
|
||||
this->setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
MqttLogger::~MqttLogger()
|
||||
{
|
||||
}
|
||||
|
||||
void MqttLogger::setClient(PubSubClient& client)
|
||||
{
|
||||
this->client = &client;
|
||||
}
|
||||
|
||||
void MqttLogger::setTopic(const char* topic)
|
||||
{
|
||||
this->topic = topic;
|
||||
}
|
||||
|
||||
void MqttLogger::setMode(MqttLoggerMode mode)
|
||||
{
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
uint16_t MqttLogger::getBufferSize()
|
||||
{
|
||||
return this->bufferSize;
|
||||
}
|
||||
|
||||
// allocate or reallocate local buffer, reset end to start of buffer
|
||||
boolean MqttLogger::setBufferSize(uint16_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this->bufferSize == 0)
|
||||
{
|
||||
this->buffer = (uint8_t *)malloc(size);
|
||||
this->bufferEnd = this->buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *newBuffer = (uint8_t *)realloc(this->buffer, size);
|
||||
if (newBuffer != NULL)
|
||||
{
|
||||
this->buffer = newBuffer;
|
||||
this->bufferEnd = this->buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this->bufferSize = size;
|
||||
return (this->buffer != NULL);
|
||||
}
|
||||
|
||||
// send & reset current buffer
|
||||
void MqttLogger::sendBuffer()
|
||||
{
|
||||
if (this->bufferCnt > 0)
|
||||
{
|
||||
bool doSerial = this->mode==MqttLoggerMode::SerialOnly || this->mode==MqttLoggerMode::MqttAndSerial;
|
||||
if (this->mode!=MqttLoggerMode::SerialOnly && this->client != NULL && this->client->connected())
|
||||
{
|
||||
this->client->publish(this->topic, (byte *)this->buffer, this->bufferCnt, 1);
|
||||
} else if (this->mode == MqttLoggerMode::MqttAndSerialFallback)
|
||||
{
|
||||
doSerial = true;
|
||||
}
|
||||
if (doSerial)
|
||||
{
|
||||
Serial.write(this->buffer, this->bufferCnt);
|
||||
Serial.println();
|
||||
}
|
||||
this->bufferCnt=0;
|
||||
}
|
||||
this->bufferEnd=this->buffer;
|
||||
}
|
||||
|
||||
// implement Print::write(uint8_t c): store into a buffer until \n or buffer full
|
||||
size_t MqttLogger::write(uint8_t character)
|
||||
{
|
||||
if (character == '\n') // when newline is printed we send the buffer
|
||||
{
|
||||
this->sendBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->bufferCnt < this->bufferSize) // add char to end of buffer
|
||||
{
|
||||
*(this->bufferEnd++) = character;
|
||||
this->bufferCnt++;
|
||||
}
|
||||
else // buffer is full, first send&reset buffer and then add char to buffer
|
||||
{
|
||||
this->sendBuffer();
|
||||
*(this->bufferEnd++) = character;
|
||||
this->bufferCnt++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
51
lib/MqttLogger/src/MqttLogger.h
Normal file
51
lib/MqttLogger/src/MqttLogger.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
MqttLogger - offer print() interface like Serial but by publishing to a given mqtt topic.
|
||||
Uses Serial as a fallback when no mqtt connection is available.
|
||||
|
||||
Claus Denk
|
||||
https://androbi.com
|
||||
*/
|
||||
|
||||
#ifndef MqttLogger_h
|
||||
#define MqttLogger_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Print.h>
|
||||
#include <PubSubClient.h>
|
||||
|
||||
enum MqttLoggerMode {
|
||||
MqttAndSerialFallback = 0,
|
||||
SerialOnly = 1,
|
||||
MqttOnly = 2,
|
||||
MqttAndSerial = 3,
|
||||
};
|
||||
|
||||
class MqttLogger : public Print
|
||||
{
|
||||
private:
|
||||
const char* topic;
|
||||
uint8_t* buffer;
|
||||
uint8_t* bufferEnd;
|
||||
uint16_t bufferCnt = 0, bufferSize = 0;
|
||||
PubSubClient* client;
|
||||
MqttLoggerMode mode;
|
||||
void sendBuffer();
|
||||
|
||||
public:
|
||||
MqttLogger(MqttLoggerMode mode=MqttLoggerMode::MqttAndSerialFallback);
|
||||
MqttLogger(PubSubClient& client, const char* topic, MqttLoggerMode mode=MqttLoggerMode::MqttAndSerialFallback);
|
||||
~MqttLogger();
|
||||
|
||||
void setClient(PubSubClient& client);
|
||||
void setTopic(const char* topic);
|
||||
void setMode(MqttLoggerMode mode);
|
||||
void setRetained(boolean retained);
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
using Print::write;
|
||||
|
||||
uint16_t getBufferSize();
|
||||
boolean setBufferSize(uint16_t size);
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user