Advertisement
eshafik

MESH

Apr 9th, 2021
1,939
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //************************************************************
  2. // this is a MqttBroker example that uses the painlessMesh library
  3. //
  4. // connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
  5. //
  6. // - To send a message to a mesh node, you can publish it to "painlessMesh/to/NNNN" where NNNN equals the nodeId.
  7. // - To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
  8. // - When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
  9. //
  10. // - Every message from the mesh which is sent to the gateway node will be published to "painlessMesh/from/NNNN" where NNNN
  11. //   is the nodeId from which the packet was sent.
  12. //
  13. //
  14. //************************************************************
  15. //#include <Arduino.h>
  16. #include "painlessMesh.h"
  17. #include "PubSubClient.h"
  18. #include "Button2.h"
  19. #include <TFT_eSPI.h>
  20.  
  21. // PainlessMesh credentials ( name, password and port ): You should change these
  22. #define   MESH_PREFIX     "whateverYouLike"
  23. #define   MESH_PASSWORD   "somethingSneaky"
  24. #define   MESH_PORT       5555
  25.  
  26. // WiFi credentials: should match your access point!
  27. #define   STATION_SSID     "MyAPSSID"
  28. #define   STATION_PASSWORD "MyWirelessPass"
  29.  
  30. #define   HOSTNAME         "MQTT_Bridge"
  31.  
  32. Scheduler userScheduler;   // to control your personal task
  33.  
  34. painlessMesh  mesh;
  35. WiFiClient wifiClient;
  36.  
  37. // Prototypes
  38. void receivedCallback( const uint32_t &from, const String &msg );
  39. void mqttCallback(char* topic, byte* payload, unsigned int length);
  40.  
  41. IPAddress getlocalIP();
  42. IPAddress myIP(0,0,0,0);
  43.  
  44. // hivemq pubblic broker address and port
  45. char mqttBroker[]  = "broker.hivemq.com";
  46. #define MQTTPORT 1883
  47.  
  48. // topic's suffix: everyone can publish/subscribe to this public broker,
  49. // you have to change the following 2 defines
  50. #define PUBPLISHSUFFIX             "painlessMesh/from/"
  51. #define SUBSCRIBESUFFIX            "painlessMesh/to/"
  52.  
  53. #define PUBPLISHFROMGATEWAYSUFFIX  PUBPLISHSUFFIX "gateway"
  54.  
  55. #define CHECKCONNDELTA 60     // check interval ( seconds ) for mqtt connection
  56.  
  57. PubSubClient mqttClient;
  58.  
  59. // TFT start
  60. #ifndef TFT_DISPOFF
  61. #define TFT_DISPOFF 0x28
  62. #endif
  63.  
  64. #ifndef TFT_SLPIN
  65. #define TFT_SLPIN   0x10
  66. #endif
  67.  
  68. #define TFT_MOSI        19
  69. #define TFT_SCLK        18
  70. #define TFT_CS          5
  71. #define TFT_DC          16
  72. #define TFT_RST         23
  73.  
  74. #define TFT_BL          4   // Display backlight control pin
  75. #define ADC_EN          14  //ADC_EN is the ADC detection enable port
  76. #define ADC_PIN         34
  77. #define BUTTON_1        35
  78. #define BUTTON_2        0
  79.  
  80. TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
  81. // TFT end
  82. Button2 btn1(BUTTON_1);
  83. Button2 btn2(BUTTON_2);
  84.  
  85. bool calc_delay = false;
  86. SimpleList<uint32_t> nodes;
  87. uint32_t nsent=0;
  88. char buff[512];
  89. uint32_t nexttime=0;
  90. uint8_t  initialized=0;
  91.  
  92.  
  93. //Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );
  94.  
  95.  
  96.  
  97. // messages received from the mqtt broker
  98. void mqttCallback(char* topic, uint8_t* payload, unsigned int length)
  99.   {
  100.   char* cleanPayload = (char*)malloc(length+1);
  101.   payload[length] = '\0';
  102.   memcpy(cleanPayload, payload, length+1);
  103.   String msg = String(cleanPayload);
  104.   free(cleanPayload);
  105.  
  106.   Serial.printf("mc t:%s  p:%s\n", topic, payload);
  107.  
  108.   String targetStr = String(topic).substring(strlen(SUBSCRIBESUFFIX));
  109.   if(targetStr == "gateway")
  110.     {
  111.     if(msg == "getNodes")
  112.       {
  113.       auto nodes = mesh.getNodeList(true);
  114.       String str;
  115.       for (auto &&id : nodes)
  116.         str += String(id) + String(" ");
  117.       mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX, str.c_str());
  118.       }
  119.     }
  120.   else if(targetStr == "broadcast")
  121.     {
  122.     mesh.sendBroadcast(msg);
  123.     }
  124.   else
  125.     {
  126.     uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
  127.     if(mesh.isConnected(target))
  128.       {
  129.       mesh.sendSingle(target, msg);
  130.       }
  131.     else
  132.       {
  133.       mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX, "Client not connected!");
  134.       }
  135.     }
  136.   }
  137.  
  138.  
  139.  
  140.  
  141.  
  142. // Needed for painless library
  143.  
  144. // messages received from painless mesh network
  145. void receivedCallback( const uint32_t &from, const String &msg )
  146.   {
  147.   Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
  148.   String topic = PUBPLISHSUFFIX + String(from);
  149.   mqttClient.publish(topic.c_str(), msg.c_str());
  150.   }
  151.  
  152.  
  153.  
  154.  
  155. void newConnectionCallback(uint32_t nodeId)
  156.   {
  157.   Serial.printf("--> Start: New Connection, nodeId = %u\n", nodeId);
  158.   Serial.printf("--> Start: New Connection, %s\n", mesh.subConnectionJson(true).c_str());
  159.   }
  160.  
  161.  
  162.  
  163.  
  164. void changedConnectionCallback()
  165.   {
  166.   Serial.printf("Changed connections\n");
  167.  
  168.   nodes = mesh.getNodeList();
  169.   Serial.printf("Num nodes: %d\n", nodes.size());
  170.   Serial.printf("Connection list:");
  171.   SimpleList<uint32_t>::iterator node = nodes.begin();
  172.   while (node != nodes.end())
  173.     {
  174.     Serial.printf(" %u", *node);
  175.     node++;
  176.     }
  177.   Serial.println();
  178.   calc_delay = true;
  179.  
  180.   sprintf(buff,"Nodes:%d",nodes.size());
  181.   tft.drawString(buff, 0, 32);
  182.   }
  183.  
  184.  
  185.  
  186.  
  187. void nodeTimeAdjustedCallback(int32_t offset)
  188.   {
  189.   Serial.printf("Adjusted time %u Offset = %d\n", mesh.getNodeTime(),offset);
  190.   }
  191.  
  192.  
  193.  
  194.  
  195. void onNodeDelayReceived(uint32_t nodeId, int32_t delay)
  196.   {
  197.   Serial.printf("Delay from node:%u delay = %d\n", nodeId,delay);
  198.   }
  199.  
  200.  
  201.  
  202.  
  203. void reconnect()
  204. {
  205.   //byte mac[6];
  206.   char MAC[9];
  207.   int i;
  208.  
  209.   // unique string
  210.   //WiFi.macAddress(mac);
  211.   //sprintf(MAC,"%02X",mac[2],mac[3],mac[4],mac[5]);
  212.   sprintf(MAC, "%08X",(uint32_t)ESP.getEfuseMac());  // generate unique addresss.
  213.   // Loop until we're reconnected
  214.   while (!mqttClient.connected())
  215.     {
  216.     Serial.println("Attempting MQTT connection...");    
  217.     // Attemp to connect
  218.     if (mqttClient.connect(/*MQTT_CLIENT_NAME*/MAC))
  219.       {
  220.       Serial.println("Connected");  
  221.       mqttClient.publish(PUBPLISHFROMGATEWAYSUFFIX,"Ready!");
  222.       mqttClient.subscribe(SUBSCRIBESUFFIX "#");
  223.       tft.drawString("Mqtt connected", 0, 96);
  224.       }
  225.     else
  226.       {
  227.       Serial.print("Failed, rc=");
  228.       Serial.print(mqttClient.state());
  229.       Serial.println(" try again in 2 seconds");
  230.       // Wait 2 seconds before retrying
  231.       delay(2000);
  232.       mesh.update();
  233.       mqttClient.loop();
  234.       }
  235.     }
  236. }
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243. IPAddress getlocalIP()
  244.   {
  245.   return IPAddress(mesh.getStationIP());
  246.   }
  247.  
  248.  
  249.  
  250.  
  251.  
  252. void setup()
  253.   {
  254.   Serial.begin(115200);
  255.  
  256.   // TFT
  257.   tft.init();
  258.   tft.setRotation(1);
  259.   tft.fillScreen(TFT_BLACK);
  260.   //tft.setTextSize(4);
  261.   tft.setTextColor(TFT_GREEN,TFT_BLACK);
  262.   tft.setCursor(0, 0);
  263.   tft.setTextDatum(MC_DATUM);
  264.   tft.setTextSize(2);
  265.  
  266.   if (TFT_BL > 0)
  267.     { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
  268.     pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
  269.     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
  270.     }
  271.   tft.fillScreen(TFT_BLACK);
  272.   tft.setTextDatum(TL_DATUM);
  273.   tft.drawString("MqttBridge 1.0.0", 0, 0);
  274.   //tft.setTextDatum(MC_DATUM);
  275.   //tft.drawString("LeftButton:", tft.width() / 2, tft.height() / 2 - 16);
  276.  
  277.   //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | MSG_TYPES | REMOTE ); // all types on except GENERAL
  278.   //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  279.   mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION );  // set before init() so that you can see startup messages
  280.  
  281.   // Channel set to 1. Make sure to use the same channel for your mesh and for you other
  282.   // network (STATION_SSID)
  283.   mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA );
  284.   mesh.onReceive(&receivedCallback);
  285.   mesh.onNewConnection(&newConnectionCallback);
  286.   mesh.onChangedConnections(&changedConnectionCallback);
  287.   mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
  288.  
  289.   mesh.stationManual(STATION_SSID, STATION_PASSWORD);
  290.   mesh.setHostname(HOSTNAME);
  291.  
  292.   // 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
  293.   mesh.setRoot(true);
  294.   // This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
  295.   mesh.setContainsRoot(true);
  296.  
  297.   // if you want your node to accept OTA firmware, simply include this line
  298.   // with whatever role you want your hardware to be. For instance, a
  299.   // mesh network may have a thermometer, rain detector, and bridge. Each of
  300.   // those may require different firmware, so different roles are preferrable.
  301.   //
  302.   // MAKE SURE YOUR UPLOADED OTA FIRMWARE INCLUDES OTA SUPPORT OR YOU WILL LOSE
  303.   // THE ABILITY TO UPLOAD MORE FIRMWARE OVER OTA. YOU ALSO WANT TO MAKE SURE
  304.   // THE ROLES ARE CORRECT
  305.   mesh.initOTAReceive("bridge");
  306.  
  307.   sprintf(buff,"Id:%d",mesh.getNodeId());
  308.   tft.drawString(buff, 0, 16);
  309.  
  310.   mqttClient.setServer(mqttBroker, MQTTPORT);
  311.   mqttClient.setCallback(mqttCallback);  
  312.   mqttClient.setClient(wifiClient);
  313.   }
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320. void loop()
  321.   {
  322.   // it will run the user scheduler as well
  323.   mesh.update();
  324.   mqttClient.loop();
  325.  
  326.   if(myIP != getlocalIP())
  327.     {
  328.     myIP = getlocalIP();
  329.     Serial.println("My IP is " + myIP.toString());
  330.     tft.drawString("Ip:" + myIP.toString(), 0, 80);
  331.     initialized = 1;
  332.     }
  333.   if ( ( millis() >= nexttime ) && ( initialized ) )
  334.     {
  335.     nexttime=millis()+CHECKCONNDELTA*1000;
  336.     if (!mqttClient.connected())
  337.       {reconnect();}
  338.     }
  339.   }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement