Files
ESPGadget/30_interface_mqtt.ino
Florian Overkamp 1d6201eb25 Adding to repo
2019-03-30 08:39:24 +01:00

159 lines
4.8 KiB
C++

#ifdef ENABLE_MQTT
/*
* Define a function newcmd in your module to be able to accept mqtt commands
* Syntax and parameters are like this:
*/
void newcmd(String cmd);
void module_message(const String& shorttopic, const String& message);
#include <PubSubClient.h>
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
PubSubClient mqtt(net);
String deviceprefix;
const char* fingerprint = "EA:2A:2B:80:C1:00:57:35:66:26:FF:FC:FA:27:EA:5F:3D:91:5A:F9";
long logtimerMillis = 0;
void mqtt_subscribe(const String& topic) {
mqtt.subscribe(topic.c_str());
PRINTLN_SERIAL("Subscribed to " + topic);
}
void mqtt_publish(const String& topic, const String& message) {
mqtt.publish(topic.c_str(), message.c_str());
PRINTLN_SERIAL("Published " + topic + ": " + message);
}
/*
* Callback routine is called when a topic we subscribed to got a message
*/
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
String fulltopic((char*)0);
String shorttopic((char*)0);
String message((char*)0);
fulltopic.reserve(strlen(topic));
fulltopic = String(topic);
// If deviceprefix is in topic, subtract it
// Could do a similar thing for grouptopics if we implement them
shorttopic.reserve(strlen(topic));
shorttopic = String(topic);
shorttopic.replace(deviceprefix, "");
// Decode message into string
message.reserve(length);
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
PRINT_SERIAL(F("Received MQTT "));
APPEND_SERIAL(fulltopic);
APPEND_SERIAL(F(": "));
APPENDLN_SERIAL(message);
// Deal with global topic messages
if(fulltopic.equals(MQTT_PREFIX "ping")) {
mqtt_publish(deviceprefix + "pong", "This is " + settings.name + " v" + FW_VERSION + " at " + settings.ip);
// Next quietly ignore all the things we send out ourselves
} else if(shorttopic.equals(F("pong"))) {
// Ignore quietly
//NOP; // delay 62.5ns on a 16MHz AtMega
} else if(shorttopic.equals(F("log"))) {
// Ignore quietly
//NOP; // delay 62.5ns on a 16MHz AtMega
// And now to add a catchall to hand off to other module
} else {
module_message(shorttopic, message);
}
}
void WifiMQTTconnect() {
if(WiFi.status() != WL_CONNECTED) {
PRINTLN_SERIAL("Wifi not connected, connecting...");
WiFi.mode(WIFI_STA); // Weird MQTT connection bug, https://github.com/knolleary/pubsubclient/issues/138#issuecomment-326113915
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
PRINTLN_SERIAL("Waiting for Wifi...");
delay(500);
}
settings.ip = WiFi.localIP().toString();
PRINTLN_SERIAL("Wifi connected");
}
PRINT_SERIAL("Setting time using SNTP");
configTime(-5 * 3600, 0, "pool.ntp.org", "time.nist.gov");
now = time(nullptr);
while (now < 1510592825) {
delay(500);
APPEND_SERIAL(".");
now = time(nullptr);
}
APPENDLN_SERIAL(" done!");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
PRINT_SERIAL("Current time: ");
APPENDLN_SERIAL(asctime(&timeinfo));
net.setInsecure(); // verification options set to none
mqtt.setServer(MQTT_SERVER, MQTT_SERVERPORT);
mqtt.setCallback(mqtt_callback);
if(!mqtt.connected()) {
while (!mqtt.connected()) {
PRINTLN_SERIAL("MQTT not connected, connecting...");
// Attempt to connect
// Note - the default maximum packet size is 128 bytes. If the
// combined length of clientId, username and password exceed this,
// you will need to increase the value of MQTT_MAX_PACKET_SIZE in
// PubSubClient.h
if (mqtt.connect(settings.name.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) {
PRINTLN_SERIAL("MQTT connected");
} else {
PRINTLN_SERIAL("MQTT connection failed, rc=" + String(mqtt.state()) + "...");
delay(10000); // @@@FIXME@@@ delays are not cool
}
}
// (re)subscribe to the topics we need
deviceprefix = MQTT_PREFIX;
deviceprefix = deviceprefix + settings.name + "/";
mqtt_subscribe(MQTT_PREFIX "ping"); // global topic: send a ping, and we will respond with some device info
mqtt_subscribe(deviceprefix + "#");
mqtt_publish(deviceprefix + "log", "Booting up " + settings.name + " running v" + FW_VERSION + " at " + settings.ip);
mqtt_publish(deviceprefix + "log", "Free Heap: " + String(ESP.getFreeHeap()));
}
}
void mqtt_setup() {
PRINTLN_SERIAL(devname + "initialising module MQTT");
}
void mqtt_loop() {
long currentMillis = millis();
// Check for MQTT instructions
if(!mqtt.connected()) {
WifiMQTTconnect();
} else {
mqtt.loop();
// every 5 minutes (300000 milliseconds)
if(currentMillis - logtimerMillis > 300000) {
// reset timer
logtimerMillis = currentMillis;
// log something
mqtt_publish(deviceprefix + "log", "Free Heap: " + String(ESP.getFreeHeap()));
}
}
}
#endif