add MqttLogger
This commit is contained in:
@@ -33,7 +33,7 @@ include_directories(${PROJECT_NAME}
|
|||||||
lib/pubsubclient/src
|
lib/pubsubclient/src
|
||||||
lib/WebServer/src
|
lib/WebServer/src
|
||||||
lib/Ethernet/src
|
lib/Ethernet/src
|
||||||
# include
|
lib/MqttLogger/src
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB SRCFILES
|
file(GLOB SRCFILES
|
||||||
@@ -54,6 +54,7 @@ file(GLOB SRCFILES
|
|||||||
PresenceDetection.cpp
|
PresenceDetection.cpp
|
||||||
PreferencesKeys.h
|
PreferencesKeys.h
|
||||||
Gpio.cpp
|
Gpio.cpp
|
||||||
|
Logger.cpp
|
||||||
Version.h
|
Version.h
|
||||||
# include/RTOS.h
|
# include/RTOS.h
|
||||||
lib/WiFiManager/WiFiManager.cpp
|
lib/WiFiManager/WiFiManager.cpp
|
||||||
@@ -72,6 +73,7 @@ file(GLOB SRCFILES
|
|||||||
lib/BleScanner/src/BleInterfaces.h
|
lib/BleScanner/src/BleInterfaces.h
|
||||||
lib/BleScanner/src/BleScanner.cpp
|
lib/BleScanner/src/BleScanner.cpp
|
||||||
lib/pubsubclient/src/PubSubClient.cpp
|
lib/pubsubclient/src/PubSubClient.cpp
|
||||||
|
lib/MqttLogger/src/MqttLogger.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILESREC
|
file(GLOB_RECURSE SRCFILESREC
|
||||||
|
|||||||
3
Logger.cpp
Normal file
3
Logger.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
Print* Log = nullptr;
|
||||||
7
Logger.h
Normal file
7
Logger.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef MQTT_LOGGER_GLOBAL
|
||||||
|
#define MQTT_LOGGER_GLOBAL
|
||||||
|
|
||||||
|
#include "MqttLogger.h"
|
||||||
|
extern Print* Log;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <RTOS.h>
|
#include <RTOS.h>
|
||||||
#include "PreferencesKeys.h"
|
#include "PreferencesKeys.h"
|
||||||
#include "MqttTopics.h"
|
#include "MqttTopics.h"
|
||||||
|
#include "Logger.h"
|
||||||
#include <NukiLockUtils.h>
|
#include <NukiLockUtils.h>
|
||||||
|
|
||||||
NukiWrapper* nukiInst;
|
NukiWrapper* nukiInst;
|
||||||
@@ -70,12 +71,12 @@ void NukiWrapper::initialize()
|
|||||||
|
|
||||||
_nukiLock.setEventHandler(this);
|
_nukiLock.setEventHandler(this);
|
||||||
|
|
||||||
Serial.print(F("Lock state interval: "));
|
Log->print(F("Lock state interval: "));
|
||||||
Serial.print(_intervalLockstate);
|
Log->print(_intervalLockstate);
|
||||||
Serial.print(F(" | Battery interval: "));
|
Log->print(F(" | Battery interval: "));
|
||||||
Serial.print(_intervalBattery);
|
Log->print(_intervalBattery);
|
||||||
Serial.print(F(" | Publish auth data: "));
|
Log->print(F(" | Publish auth data: "));
|
||||||
Serial.println(_publishAuthData ? "yes" : "no");
|
Log->println(_publishAuthData ? "yes" : "no");
|
||||||
|
|
||||||
if(!_publishAuthData)
|
if(!_publishAuthData)
|
||||||
{
|
{
|
||||||
@@ -91,14 +92,14 @@ void NukiWrapper::update()
|
|||||||
|
|
||||||
if (!_paired)
|
if (!_paired)
|
||||||
{
|
{
|
||||||
Serial.println(F("Nuki start pairing"));
|
Log->println(F("Nuki start pairing"));
|
||||||
|
|
||||||
Nuki::AuthorizationIdType idType = _preferences->getBool(preference_register_as_app) ?
|
Nuki::AuthorizationIdType idType = _preferences->getBool(preference_register_as_app) ?
|
||||||
Nuki::AuthorizationIdType::App :
|
Nuki::AuthorizationIdType::App :
|
||||||
Nuki::AuthorizationIdType::Bridge;
|
Nuki::AuthorizationIdType::Bridge;
|
||||||
|
|
||||||
if (_nukiLock.pairNuki(idType) == Nuki::PairingResult::Success) {
|
if (_nukiLock.pairNuki(idType) == Nuki::PairingResult::Success) {
|
||||||
Serial.println(F("Nuki paired"));
|
Log->println(F("Nuki paired"));
|
||||||
_paired = true;
|
_paired = true;
|
||||||
setupHASS();
|
setupHASS();
|
||||||
}
|
}
|
||||||
@@ -111,9 +112,9 @@ void NukiWrapper::update()
|
|||||||
|
|
||||||
if(_restartBeaconTimeout > 0 && (millis() - _nukiLock.getLastReceivedBeaconTs() > _restartBeaconTimeout * 1000))
|
if(_restartBeaconTimeout > 0 && (millis() - _nukiLock.getLastReceivedBeaconTs() > _restartBeaconTimeout * 1000))
|
||||||
{
|
{
|
||||||
Serial.print("No BLE beacon received from the lock for ");
|
Log->print("No BLE beacon received from the lock for ");
|
||||||
Serial.print((millis() - _nukiLock.getLastReceivedBeaconTs()) / 1000);
|
Log->print((millis() - _nukiLock.getLastReceivedBeaconTs()) / 1000);
|
||||||
Serial.println(" seconds, restarting device.");
|
Log->println(" seconds, restarting device.");
|
||||||
delay(200);
|
delay(200);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
@@ -165,8 +166,8 @@ void NukiWrapper::update()
|
|||||||
|
|
||||||
_network->publishCommandResult(resultStr);
|
_network->publishCommandResult(resultStr);
|
||||||
|
|
||||||
Serial.print(F("Lock action result: "));
|
Log->print(F("Lock action result: "));
|
||||||
Serial.println(resultStr);
|
Log->println(resultStr);
|
||||||
|
|
||||||
_nextLockAction = (NukiLock::LockAction)0xff;
|
_nextLockAction = (NukiLock::LockAction)0xff;
|
||||||
if(_intervalLockstate > 10)
|
if(_intervalLockstate > 10)
|
||||||
@@ -219,8 +220,8 @@ void NukiWrapper::updateKeyTurnerState()
|
|||||||
{
|
{
|
||||||
char lockStateStr[20];
|
char lockStateStr[20];
|
||||||
lockstateToString(_keyTurnerState.lockState, lockStateStr);
|
lockstateToString(_keyTurnerState.lockState, lockStateStr);
|
||||||
Serial.print(F("Nuki lock state: "));
|
Log->print(F("Nuki lock state: "));
|
||||||
Serial.println(lockStateStr);
|
Log->println(lockStateStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_publishAuthData)
|
if(_publishAuthData)
|
||||||
@@ -430,7 +431,7 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
|||||||
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
|
||||||
entry.code = codeInt;
|
entry.code = codeInt;
|
||||||
result = _nukiLock.addKeypadEntry(entry);
|
result = _nukiLock.addKeypadEntry(entry);
|
||||||
Serial.print("Add keypad code: "); Serial.println((int)result);
|
Log->print("Add keypad code: "); Log->println((int)result);
|
||||||
updateKeypad();
|
updateKeypad();
|
||||||
}
|
}
|
||||||
else if(strcmp(command, "delete") == 0)
|
else if(strcmp(command, "delete") == 0)
|
||||||
@@ -441,7 +442,7 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = _nukiLock.deleteKeypadEntry(id);
|
result = _nukiLock.deleteKeypadEntry(id);
|
||||||
Serial.print("Delete keypad code: "); Serial.println((int)result);
|
Log->print("Delete keypad code: "); Log->println((int)result);
|
||||||
updateKeypad();
|
updateKeypad();
|
||||||
}
|
}
|
||||||
else if(strcmp(command, "update") == 0)
|
else if(strcmp(command, "update") == 0)
|
||||||
@@ -475,7 +476,7 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
|||||||
entry.code = codeInt;
|
entry.code = codeInt;
|
||||||
entry.enabled = enabled == 0 ? 0 : 1;
|
entry.enabled = enabled == 0 ? 0 : 1;
|
||||||
result = _nukiLock.updateKeypadEntry(entry);
|
result = _nukiLock.updateKeypadEntry(entry);
|
||||||
Serial.print("Update keypad code: "); Serial.println((int)result);
|
Log->print("Update keypad code: "); Log->println((int)result);
|
||||||
updateKeypad();
|
updateKeypad();
|
||||||
}
|
}
|
||||||
else if(command == "--")
|
else if(command == "--")
|
||||||
@@ -522,18 +523,18 @@ void NukiWrapper::notify(Nuki::EventType eventType)
|
|||||||
|
|
||||||
void NukiWrapper::readConfig()
|
void NukiWrapper::readConfig()
|
||||||
{
|
{
|
||||||
Serial.print(F("Reading config. Result: "));
|
Log->print(F("Reading config. Result: "));
|
||||||
Nuki::CmdResult result = _nukiLock.requestConfig(&_nukiConfig);
|
Nuki::CmdResult result = _nukiLock.requestConfig(&_nukiConfig);
|
||||||
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
_nukiConfigValid = result == Nuki::CmdResult::Success;
|
||||||
Serial.println(result);
|
Log->println(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiWrapper::readAdvancedConfig()
|
void NukiWrapper::readAdvancedConfig()
|
||||||
{
|
{
|
||||||
Serial.print(F("Reading advanced config. Result: "));
|
Log->print(F("Reading advanced config. Result: "));
|
||||||
Nuki::CmdResult result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig);
|
Nuki::CmdResult result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig);
|
||||||
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
_nukiAdvancedConfigValid = result == Nuki::CmdResult::Success;
|
||||||
Serial.println(result);
|
Log->println(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiWrapper::setupHASS()
|
void NukiWrapper::setupHASS()
|
||||||
@@ -552,7 +553,7 @@ void NukiWrapper::setupHASS()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial.println(F("Unable to setup HASS. Invalid config received."));
|
Log->println(F("Unable to setup HASS. Invalid config received."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,6 +572,6 @@ void NukiWrapper::disableHASS()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial.println(F("Unable to disable HASS. Invalid config received."));
|
Log->println(F("Unable to disable HASS. Invalid config received."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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
|
||||||
2
main.cpp
2
main.cpp
@@ -10,6 +10,7 @@
|
|||||||
#include "hardware/WifiEthServer.h"
|
#include "hardware/WifiEthServer.h"
|
||||||
#include "NukiOpenerWrapper.h"
|
#include "NukiOpenerWrapper.h"
|
||||||
#include "Gpio.h"
|
#include "Gpio.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
Network* network = nullptr;
|
Network* network = nullptr;
|
||||||
NetworkLock* networkLock = nullptr;
|
NetworkLock* networkLock = nullptr;
|
||||||
@@ -161,6 +162,7 @@ void setup()
|
|||||||
pinMode(NETWORK_SELECT, INPUT_PULLUP);
|
pinMode(NETWORK_SELECT, INPUT_PULLUP);
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
Log = &Serial;
|
||||||
|
|
||||||
initPreferences();
|
initPreferences();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "W5500Device.h"
|
#include "W5500Device.h"
|
||||||
#include "../Pins.h"
|
#include "../Pins.h"
|
||||||
#include "../PreferencesKeys.h"
|
#include "../PreferencesKeys.h"
|
||||||
|
#include "../Logger.h"
|
||||||
|
|
||||||
W5500Device::W5500Device(const String &hostname, Preferences* preferences)
|
W5500Device::W5500Device(const String &hostname, Preferences* preferences)
|
||||||
: NetworkDevice(hostname),
|
: NetworkDevice(hostname),
|
||||||
@@ -10,20 +11,20 @@ W5500Device::W5500Device(const String &hostname, Preferences* preferences)
|
|||||||
{
|
{
|
||||||
initializeMacAddress(_mac);
|
initializeMacAddress(_mac);
|
||||||
|
|
||||||
Serial.print("MAC Adress: ");
|
Log->print("MAC Adress: ");
|
||||||
for(int i=0; i < 6; i++)
|
for(int i=0; i < 6; i++)
|
||||||
{
|
{
|
||||||
if(_mac[i] < 10)
|
if(_mac[i] < 10)
|
||||||
{
|
{
|
||||||
Serial.print(F("0"));
|
Log->print(F("0"));
|
||||||
}
|
}
|
||||||
Serial.print(_mac[i], 16);
|
Log->print(_mac[i], 16);
|
||||||
if(i < 5)
|
if(i < 5)
|
||||||
{
|
{
|
||||||
Serial.print(F(":"));
|
Log->print(F(":"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Serial.println();
|
Log->println();
|
||||||
}
|
}
|
||||||
|
|
||||||
W5500Device::~W5500Device()
|
W5500Device::~W5500Device()
|
||||||
@@ -39,6 +40,7 @@ void W5500Device::initialize()
|
|||||||
_ethClient = new EthernetClient();
|
_ethClient = new EthernetClient();
|
||||||
_mqttClient = new PubSubClient(*_ethClient);
|
_mqttClient = new PubSubClient(*_ethClient);
|
||||||
_mqttClient->setBufferSize(_mqttMaxBufferSize);
|
_mqttClient->setBufferSize(_mqttMaxBufferSize);
|
||||||
|
Log = new MqttLogger(*_mqttClient, "nuki/log");
|
||||||
|
|
||||||
reconnect();
|
reconnect();
|
||||||
}
|
}
|
||||||
@@ -46,33 +48,31 @@ void W5500Device::initialize()
|
|||||||
|
|
||||||
bool W5500Device::reconnect()
|
bool W5500Device::reconnect()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
_hasDHCPAddress = false;
|
_hasDHCPAddress = false;
|
||||||
|
|
||||||
// start the Ethernet connection:
|
// start the Ethernet connection:
|
||||||
Serial.println(F("Initialize Ethernet with DHCP:"));
|
Log->println(F("Initialize Ethernet with DHCP:"));
|
||||||
|
|
||||||
int dhcpRetryCnt = 0;
|
int dhcpRetryCnt = 0;
|
||||||
|
|
||||||
while(dhcpRetryCnt < 3)
|
while(dhcpRetryCnt < 3)
|
||||||
{
|
{
|
||||||
Serial.print(F("DHCP connect try #"));
|
Log->print(F("DHCP connect try #"));
|
||||||
Serial.print(dhcpRetryCnt);
|
Log->print(dhcpRetryCnt);
|
||||||
Serial.println();
|
Log->println();
|
||||||
dhcpRetryCnt++;
|
dhcpRetryCnt++;
|
||||||
|
|
||||||
if (Ethernet.begin(_mac, 1000, 1000) == 0)
|
if (Ethernet.begin(_mac, 1000, 1000) == 0)
|
||||||
{
|
{
|
||||||
Serial.println(F("Failed to configure Ethernet using DHCP"));
|
Log->println(F("Failed to configure Ethernet using DHCP"));
|
||||||
// Check for Ethernet hardware present
|
// Check for Ethernet hardware present
|
||||||
if (Ethernet.hardwareStatus() == EthernetNoHardware)
|
if (Ethernet.hardwareStatus() == EthernetNoHardware)
|
||||||
{
|
{
|
||||||
Serial.println(F("Ethernet module not found"));
|
Log->println(F("Ethernet module not found"));
|
||||||
}
|
}
|
||||||
if (Ethernet.linkStatus() == LinkOFF)
|
if (Ethernet.linkStatus() == LinkOFF)
|
||||||
{
|
{
|
||||||
Serial.println(F("Ethernet cable is not connected."));
|
Log->println(F("Ethernet cable is not connected."));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress ip;
|
IPAddress ip;
|
||||||
@@ -91,8 +91,8 @@ bool W5500Device::reconnect()
|
|||||||
{
|
{
|
||||||
_hasDHCPAddress = true;
|
_hasDHCPAddress = true;
|
||||||
dhcpRetryCnt = 1000;
|
dhcpRetryCnt = 1000;
|
||||||
Serial.print(F(" DHCP assigned IP "));
|
Log->print(F(" DHCP assigned IP "));
|
||||||
Serial.println(Ethernet.localIP());
|
Log->println(Ethernet.localIP());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,12 +102,12 @@ bool W5500Device::reconnect()
|
|||||||
|
|
||||||
void W5500Device::reconfigure()
|
void W5500Device::reconfigure()
|
||||||
{
|
{
|
||||||
Serial.println(F("Reconfigure W5500 not implemented."));
|
Log->println(F("Reconfigure W5500 not implemented."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void W5500Device::resetDevice()
|
void W5500Device::resetDevice()
|
||||||
{
|
{
|
||||||
Serial.println(F("Resetting network hardware."));
|
Log->println(F("Resetting network hardware."));
|
||||||
pinMode(ETHERNET_RESET_PIN, OUTPUT);
|
pinMode(ETHERNET_RESET_PIN, OUTPUT);
|
||||||
digitalWrite(ETHERNET_RESET_PIN, HIGH);
|
digitalWrite(ETHERNET_RESET_PIN, HIGH);
|
||||||
delay(250);
|
delay(250);
|
||||||
@@ -120,8 +120,8 @@ void W5500Device::resetDevice()
|
|||||||
|
|
||||||
void W5500Device::printError()
|
void W5500Device::printError()
|
||||||
{
|
{
|
||||||
Serial.print(F("Free Heap: "));
|
Log->print(F("Free Heap: "));
|
||||||
Serial.println(ESP.getFreeHeap());
|
Log->println(ESP.getFreeHeap());
|
||||||
}
|
}
|
||||||
|
|
||||||
PubSubClient *W5500Device::mqttClient()
|
PubSubClient *W5500Device::mqttClient()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include "WifiDevice.h"
|
#include "WifiDevice.h"
|
||||||
#include "../PreferencesKeys.h"
|
#include "../PreferencesKeys.h"
|
||||||
|
#include "../Logger.h"
|
||||||
|
|
||||||
RTC_NOINIT_ATTR char WiFiDevice_reconfdetect[17];
|
RTC_NOINIT_ATTR char WiFiDevice_reconfdetect[17];
|
||||||
|
|
||||||
@@ -38,6 +39,8 @@ WifiDevice::WifiDevice(const String& hostname, Preferences* _preferences)
|
|||||||
_wifiClient = new WiFiClient();
|
_wifiClient = new WiFiClient();
|
||||||
_mqttClient = new PubSubClient(*_wifiClient);
|
_mqttClient = new PubSubClient(*_wifiClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log = new MqttLogger(*_mqttClient, "nuki/log");
|
||||||
}
|
}
|
||||||
|
|
||||||
PubSubClient *WifiDevice::mqttClient()
|
PubSubClient *WifiDevice::mqttClient()
|
||||||
|
|||||||
Reference in New Issue
Block a user