Even if we can leave our network unconnected from the rest of the world ( for a lot of good reasons ), we generally need to be connected to the Net ( for a lot of good services ).
So we need a bridge and one of these good services ( an mqtt broker )
Parts required- A working mesh ( as setup in Part 1 and Part 2 )
- ESP32 development boards ( two or more ), I used a ttgo t-display
- PlatformIO development software ( install from here)
- PainlessMesh library
- an mqtt broker, I used HiveMQ public broker ( no need to register )
- Modify the credentials to connect to your access point ( line 27-28 )
- Modify the topic's prefix ( line 50-51 ), the broker is public, anyone has access to your topics
- no need to register or setup anything on HiveMQ ( broker address: broker.hivemq.com tcp port 1883, websocket port: 8000 )
- Program a node with the MQTTBridge software
- From an mqtt client connect to the broker ( on the hivemq client simply click connect )
- subscribe to the topic "painlessMesh/from/bridge" ( you didn't change the prefix at line 50, if you did change modify accordingly )
- publish the message "getNodes" to the topic "painlessMesh/to/bridge" ( modify the prefix as defined at line 51 )
- you should receive a message ( the mesh topology in json format )
On the display you should see the ip address of the bridge ( display line 6 )
- If the bridge does not connect to your local wireless network check in the serial log:
- you should see the result of the wireless scan, is the ssid of your local wireless network reported?
- if you perform a wifi scan ( with a pc or a phone ) you should see that your painless mesh network and your local wireless network share the same wifi channel
On the display you should see the result of the connection to the mqtt broker ( display line 7 ), check the serial log
Network MapLet's take our 'new toy' apart... we want to see the topology of our network!
After programming the bridge with the MQTTBridgeWeb software you have access to a couple of web pages. By pointing your browser:
- to the_address_of_your_bridge you can brodcast messages
- to the_address_of_your_bridge/map you can visualize a graphical rapresentation of the network
- to the_address_of_your_bridge/scan you can visualize a rapresentation of the network in json format
Here how the map of a small network is displayed:
Now you can quicly see how the mesh network changes as you add/move nodes
NOTE: The map is from the bridge 'point of view'
//************************************************************
// this is a MqttBroker example that uses the painlessMesh library
//
// connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
//
// - To send a message to a mesh node, you can publish it to "painlessMesh/to/NNNN" where NNNN equals the nodeId.
// - To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
// - When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
//
// - Every message from the mesh which is sent to the gateway node will be published to "painlessMesh/from/NNNN" where NNNN
// is the nodeId from which the packet was sent.
//
//
//************************************************************
//#include <Arduino.h>
#include "painlessMesh.h"
#include "PubSubClient.h"
#include "Button2.h"
#include <TFT_eSPI.h>
// PainlessMesh credentials ( name, password and port ): You should change these
#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555
// WiFi credentials: should match your access point!
#define STATION_SSID "MyAPSSID"
#define STATION_PASSWORD "MyWirelessPass"
#define HOSTNAME "MQTT_Bridge"
Scheduler userScheduler; // to control your personal task
painlessMesh mesh;
WiFiClient wifiClient;
// Prototypes
void receivedCallback( const uint32_t &from, const String &msg );
void mqttCallback(char* topic, byte* payload, unsigned int length);
IPAddress getlocalIP();
IPAddress myIP(0,0,0,0);
// hivemq pubblic broker address and port
char mqttBroker[] = "broker.hivemq.com";
#define MQTTPORT 1883
// topic's suffix: everyone can publish/subscribe to this public broker,
// you have to change the following 2 defines
#define PUBPLISHSUFFIX "painlessMesh/from/"
#define SUBSCRIBESUFFIX "painlessMesh/to/"
#define PUBPLISHFROMGATEWAYSUFFIX PUBPLISHSUFFIX "gateway"
#define CHECKCONNDELTA 60 // check interval ( seconds ) for mqtt connection
PubSubClient mqttClient;
// TFT start
#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif
#ifndef TFT_SLPIN
#define TFT_SLPIN 0x10
#endif
#define TFT_MOSI 19
#define TFT_SCLK 18
#define TFT_CS 5
#define TFT_DC 16
#define TFT_RST 23
#define TFT_BL 4 // Display backlight control pin
#define ADC_EN 14 //ADC_EN is the ADC detection enable port
#define ADC_PIN 34
#define BUTTON_1 35
#define BUTTON_2 0
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
// TFT end
Button2 btn1(BUTTON_1);
Button2 btn2(BUTTON_2);
bool calc_delay = false;
SimpleList<uint32_t> nodes;
uint32_t nsent=0;
char buff[512];
uint32_t nexttime=0;
uint8_t initialized=0;
//Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );
// messages received from the mqtt broker
void mqttCallback(char* topic, uint8_t* payload, unsigned int length)
{
char* cleanPayload = (char*)malloc(length+1);
payload[length] = '\0';
memcpy(cleanPayload, payload, length+1);
String msg = String(cleanPayload);
free(cleanPayload);
Serial.printf("mc t:%s p:%s\n", topic, payload);
String targetStr = String(topic).substring(strlen(SUBSCRIBESUFFIX));
if(targetStr == "gateway")
{
if(msg == "getNodes")
{
auto nodes = mesh.getNodeList(true);
String str;
for (auto &&id : nodes)
str += String(id) + String(" ");
mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX, str.c_str());
}
}
else if(targetStr == "broadcast")
{
mesh.sendBroadcast(msg);
}
else
{
uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
if(mesh.isConnected(target))
{
mesh.sendSingle(target, msg);
}
else
{
mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX, "Client not connected!");
}
}
}
// Needed for painless library
// messages received from painless mesh network
void receivedCallback( const uint32_t &from, const String &msg )
{
Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
String topic = PUBPLISHSUFFIX + String(from);
mqttClient.publish(topic.c_str(), msg.c_str());
}
void newConnectionCallback(uint32_t nodeId)
{
Serial.printf("--> Start: New Connection, nodeId = %u\n", nodeId);
Serial.printf("--> Start: New Connection, %s\n", mesh.subConnectionJson(true).c_str());
}
void changedConnectionCallback()
{
Serial.printf("Changed connections\n");
nodes = mesh.getNodeList();
Serial.printf("Num nodes: %d\n", nodes.size());
Serial.printf("Connection list:");
SimpleList<uint32_t>::iterator node = nodes.begin();
while (node != nodes.end())
{
Serial.printf(" %u", *node);
node++;
}
Serial.println();
calc_delay = true;
sprintf(buff,"Nodes:%d",nodes.size());
tft.drawString(buff, 0, 32);
}
void nodeTimeAdjustedCallback(int32_t offset)
{
Serial.printf("Adjusted time %u Offset = %d\n", mesh.getNodeTime(),offset);
}
void onNodeDelayReceived(uint32_t nodeId, int32_t delay)
{
Serial.printf("Delay from node:%u delay = %d\n", nodeId,delay);
}
void reconnect()
{
//byte mac[6];
char MAC[9];
int i;
// unique string
//WiFi.macAddress(mac);
//sprintf(MAC,"%02X",mac[2],mac[3],mac[4],mac[5]);
sprintf(MAC, "%08X",(uint32_t)ESP.getEfuseMac()); // generate unique addresss.
// Loop until we're reconnected
while (!mqttClient.connected())
{
Serial.println("Attempting MQTT connection...");
// Attemp to connect
if (mqttClient.connect(/*MQTT_CLIENT_NAME*/MAC))
{
Serial.println("Connected");
mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX,"Ready!");
mqttClient.subscribe(SUBSCRIBESUFFIX "#");
tft.drawString("Mqtt connected", 0, 96);
}
else
{
Serial.print("Failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 2 seconds");
// Wait 2 seconds before retrying
delay(2000);
mesh.update();
mqttClient.loop();
}
}
}
IPAddress getlocalIP()
{
return IPAddress(mesh.getStationIP());
}
void setup()
{
Serial.begin(115200);
// TFT
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
//tft.setTextSize(4);
tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.setCursor(0, 0);
tft.setTextDatum(MC_DATUM);
tft.setTextSize(2);
if (TFT_BL > 0)
{ // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
}
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(TL_DATUM);
tft.drawString("MqttBridge 1.0.0", 0, 0);
//tft.setTextDatum(MC_DATUM);
//tft.drawString("LeftButton:", tft.width() / 2, tft.height() / 2 - 16);
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | MSG_TYPES | REMOTE ); // all types on except GENERAL
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
// Channel set to 1. Make sure to use the same channel for your mesh and for you other
// network (STATION_SSID)
mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA );
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
mesh.stationManual(STATION_SSID, STATION_PASSWORD);
mesh.setHostname(HOSTNAME);
// Bridge node, should (in most cases) be a root node. See [the wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation) for some background
mesh.setRoot(true);
// This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
mesh.setContainsRoot(true);
// if you want your node to accept OTA firmware, simply include this line
// with whatever role you want your hardware to be. For instance, a
// mesh network may have a thermometer, rain detector, and bridge. Each of
// those may require different firmware, so different roles are preferrable.
//
// MAKE SURE YOUR UPLOADED OTA FIRMWARE INCLUDES OTA SUPPORT OR YOU WILL LOSE
// THE ABILITY TO UPLOAD MORE FIRMWARE OVER OTA. YOU ALSO WANT TO MAKE SURE
// THE ROLES ARE CORRECT
mesh.initOTAReceive("bridge");
sprintf(buff,"Id:%d",mesh.getNodeId());
tft.drawString(buff, 0, 16);
mqttClient.setServer(mqttBroker, MQTTPORT);
mqttClient.setCallback(mqttCallback);
mqttClient.setClient(wifiClient);
}
void loop()
{
// it will run the user scheduler as well
mesh.update();
mqttClient.loop();
if(myIP != getlocalIP())
{
myIP = getlocalIP();
Serial.println("My IP is " + myIP.toString());
tft.drawString("Ip:" + myIP.toString(), 0, 80);
initialized = 1;
}
if ( ( millis() >= nexttime ) && ( initialized ) )
{
nexttime=millis()+CHECKCONNDELTA*1000;
if (!mqttClient.connected())
{reconnect();}
}
}
//************************************************************
// this is a MqttBroker example that uses the painlessMesh library
//
// connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
//
// - To send a message to a mesh node, you can publish it to "painlessMesh/to/NNNN" where NNNN equals the nodeId.
// - To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
// - When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
//
// - Every message from the mesh which is sent to the gateway node will be published to "painlessMesh/from/NNNN" where NNNN
// is the nodeId from which the packet was sent.
//
// - The web server has only 3 pages:
// ip_address_of_the_bridge to broadcast messages to all nodes
// ip_address_of_the_bridge/map to show the topology of the network
// ip_address_of_the_bridge/scan to get the topology of the network ( json format )
//
//************************************************************
//#include <Arduino.h>
#include "painlessMesh.h"
#include "PubSubClient.h"
#include "Button2.h"
#include <TFT_eSPI.h>
#ifdef ESP8266
#include "Hash.h"
#include <ESPAsyncTCP.h>
#else
#include <AsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
// PainlessMesh credentials ( name, password and port ): You should change these
#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555
// WiFi credentials: should match your access point!
#define STATION_SSID "MyAPSSID"
#define STATION_PASSWORD "MyWirelessPass"
#define HOSTNAME "MQTT_Bridge"
Scheduler userScheduler; // to control your personal task
painlessMesh mesh;
WiFiClient wifiClient;
AsyncWebServer server(80);
// Prototypes
void receivedCallback( const uint32_t &from, const String &msg );
void mqttCallback(char* topic, byte* payload, unsigned int length);
IPAddress getlocalIP();
IPAddress myIP(0,0,0,0);
IPAddress myAPIP(0,0,0,0);
// hivemq pubblic broker address and port
char mqttBroker[] = "broker.hivemq.com";
#define MQTTPORT 1883
// topic's suffix: everyone can publish/subscribe to this public broker,
// you have to change the following 2 defines
#define PUBPLISHSUFFIX "painlessMesh/from/"
#define SUBSCRIBESUFFIX "painlessMesh/to/"
#define PUBPLISHFROMGATEWAYSUFFIX PUBPLISHSUFFIX "gateway"
#define CHECKCONNDELTA 60 // check interval ( seconds ) for mqtt connection
PubSubClient mqttClient;
// TFT start
#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif
#ifndef TFT_SLPIN
#define TFT_SLPIN 0x10
#endif
#define TFT_MOSI 19
#define TFT_SCLK 18
#define TFT_CS 5
#define TFT_DC 16
#define TFT_RST 23
#define TFT_BL 4 // Display backlight control pin
#define ADC_EN 14 //ADC_EN is the ADC detection enable port
#define ADC_PIN 34
#define BUTTON_1 35
#define BUTTON_2 0
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
// TFT end
Button2 btn1(BUTTON_1);
Button2 btn2(BUTTON_2);
bool calc_delay = false;
SimpleList<uint32_t> nodes;
uint32_t nsent=0;
char buff[512];
uint32_t nexttime=0;
uint8_t initialized=0;
//Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );
// messages received from the mqtt broker
void mqttCallback(char* topic, uint8_t* payload, unsigned int length)
{
char* cleanPayload = (char*)malloc(length+1);
payload[length] = '\0';
memcpy(cleanPayload, payload, length+1);
String msg = String(cleanPayload);
free(cleanPayload);
Serial.printf("mc t:%s p:%s\n", topic, payload);
String targetStr = String(topic).substring(strlen(SUBSCRIBESUFFIX));
if(targetStr == "gateway")
{
if(msg == "getNodes")
{
auto nodes = mesh.getNodeList(true);
String str;
for (auto &&id : nodes)
str += String(id) + String(" ");
mqttClient.publish( PUBPLISHFROMGATEWAYSUFFIX, str.c_str() );
}
if(msg == "getrt")
{
mqttClient.publish( PUBPLISHFROMGATEWAYSUFFIX, mesh.subConnectionJson(false).c_str() );
}
if(msg == "asnodetree")
{
//mqttClient.publish( PUBPLISHFROMGATEWAYSUFFIX, mesh.asNodeTree().c_str() );
}
}
else if(targetStr == "broadcast")
{
mesh.sendBroadcast( msg );
}
else
{
uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
if(mesh.isConnected(target))
{
mesh.sendSingle(target, msg);
}
else
{
mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX, "Client not connected!");
}
}
}
// Needed for painless library
// messages received from painless mesh network
void receivedCallback( const uint32_t &from, const String &msg )
{
Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
String topic = PUBPLISHSUFFIX + String(from);
mqttClient.publish(topic.c_str(), msg.c_str());
}
void newConnectionCallback(uint32_t nodeId)
{
Serial.printf("--> Start: New Connection, nodeId = %u\n", nodeId);
Serial.printf("--> Start: New Connection, %s\n", mesh.subConnectionJson(true).c_str());
}
void changedConnectionCallback()
{
Serial.printf("Changed connections\n");
nodes = mesh.getNodeList();
Serial.printf("Num nodes: %d\n", nodes.size());
Serial.printf("Connection list:");
SimpleList<uint32_t>::iterator node = nodes.begin();
while (node != nodes.end())
{
Serial.printf(" %u", *node);
node++;
}
Serial.println();
calc_delay = true;
sprintf(buff,"Nodes:%d",nodes.size());
tft.drawString(buff, 0, 32);
}
void nodeTimeAdjustedCallback(int32_t offset)
{
Serial.printf("Adjusted time %u Offset = %d\n", mesh.getNodeTime(),offset);
}
void onNodeDelayReceived(uint32_t nodeId, int32_t delay)
{
Serial.printf("Delay from node:%u delay = %d\n", nodeId,delay);
}
void reconnect()
{
//byte mac[6];
char MAC[9];
int i;
// unique string
//WiFi.macAddress(mac);
//sprintf(MAC,"%02X",mac[2],mac[3],mac[4],mac[5]);
sprintf(MAC, "%08X",(uint32_t)ESP.getEfuseMac()); // generate unique addresss.
// Loop until we're reconnected
while (!mqttClient.connected())
{
Serial.println("Attempting MQTT connection...");
// Attemp to connect
if (mqttClient.connect(/*MQTT_CLIENT_NAME*/MAC))
{
Serial.println("Connected");
mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX,"Ready!");
mqttClient.subscribe(SUBSCRIBESUFFIX "#");
tft.drawString("Mqtt connected", 0, 96);
}
else
{
Serial.print("Failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 2 seconds");
// Wait 2 seconds before retrying
delay(2000);
mesh.update();
mqttClient.loop();
}
}
}
IPAddress getlocalIP()
{
return IPAddress(mesh.getStationIP());
}
String scanprocessor(const String& var)
{
if(var == "SCAN")
return mesh.subConnectionJson(false) ;
return String();
}
void setup()
{
Serial.begin(115200);
// TFT
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
//tft.setTextSize(4);
tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.setCursor(0, 0);
tft.setTextDatum(MC_DATUM);
tft.setTextSize(2);
if (TFT_BL > 0)
{ // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
}
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(TL_DATUM);
tft.drawString("MqttBridge 1.0.0", 0, 0);
//tft.setTextDatum(MC_DATUM);
//tft.drawString("LeftButton:", tft.width() / 2, tft.height() / 2 - 16);
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | MSG_TYPES | REMOTE ); // all types on except GENERAL
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
// Channel set to 1. Make sure to use the same channel for your mesh and for you other
// network (STATION_SSID)
mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA );
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
mesh.stationManual(STATION_SSID, STATION_PASSWORD);
mesh.setHostname(HOSTNAME);
// Bridge node, should (in most cases) be a root node. See [the wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation) for some background
mesh.setRoot(true);
// This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
mesh.setContainsRoot(true);
//Async webserver
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{
request->send(200, "text/html", "<form>Text to Broadcast<br><input type='text' name='BROADCAST'><br><br><input type='submit' value='Submit'></form>");
if (request->hasArg("BROADCAST"))
{
String msg = request->arg("BROADCAST");
mesh.sendBroadcast(msg);
}
});
server.on("/map", HTTP_GET, [](AsyncWebServerRequest *request)
{
request->send_P(200, "text/html", "<html><head><script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.js'></script><link href='https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis-network.min.css' rel='stylesheet' type='text/css' /><style type='text/css'>#mynetwork {width: 1024px;height: 768px;border: 1px solid lightgray;}</style></head><body><h1>PainlessMesh Network Map</h1><div id='mynetwork'></div><a href=https://visjs.org>Made with vis.js<img src='http://www.davidefabbri.net/files/visjs_logo.png' width=40 height=40></a><script>var txt = '%SCAN%';</script><script type='text/javascript' src='http://www.davidefabbri.net/files/painlessmeshmap.js'></script></body></html>", scanprocessor );
});
server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request)
{
request->send(200, "application/json", mesh.subConnectionJson(false) );
});
/*server.on("/asnodetree", HTTP_GET, [](AsyncWebServerRequest *request)
{
request->send(200, "text/html", mesh.asNodeTree().c_str() );
});*/
server.begin();
// if you want your node to accept OTA firmware, simply include this line
// with whatever role you want your hardware to be. For instance, a
// mesh network may have a thermometer, rain detector, and bridge. Each of
// those may require different firmware, so different roles are preferrable.
//
// MAKE SURE YOUR UPLOADED OTA FIRMWARE INCLUDES OTA SUPPORT OR YOU WILL LOSE
// THE ABILITY TO UPLOAD MORE FIRMWARE OVER OTA. YOU ALSO WANT TO MAKE SURE
// THE ROLES ARE CORRECT
mesh.initOTAReceive("bridge");
sprintf(buff,"Id:%d",mesh.getNodeId());
tft.drawString(buff, 0, 16);
mqttClient.setServer(mqttBroker, MQTTPORT);
mqttClient.setCallback(mqttCallback);
mqttClient.setClient(wifiClient);
}
void loop()
{
// it will run the user scheduler as well
mesh.update();
mqttClient.loop();
if(myIP != getlocalIP())
{
myIP = getlocalIP();
Serial.println("My IP is " + myIP.toString());
tft.drawString("Ip:" + myIP.toString(), 0, 80);
initialized = 1;
}
if ( ( millis() >= nexttime ) && ( initialized ) )
{
nexttime=millis()+CHECKCONNDELTA*1000;
if (!mqttClient.connected())
{reconnect();}
}
}
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:ttgo-t1]
platform = espressif32
board = ttgo-t1
framework = arduino
lib_deps =
TFT_eSPI
SPI
FS
SPIFFS
BUTTON2
PAINLESSMESH
PubSubClient
monitor_speed = 115200
monitor_filters = time
Comments