159 lines
4.8 KiB
C++
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
|