#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 // 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", "Connected " + 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