PowerTGS440

ESP8266 Mesh Bridge v0.03

Apr 10th, 2021 (edited)
400
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 20.05 KB | None | 0 0
  1. // ------------------------------------------------------------------------------------------------------------ //
  2. // --- M E S H   B R I D G E   B Y   T O M A S Z   M A J C H E R ---------------------------------------------- //
  3. // --- T L G   ( T R A N S   L I N E   G R O U P ) ------------------------------------------------------------ //
  4. // ------------------------------------------------------------------------------------------------------------ //
  5. //
  6. // MESH-SERVER Wi-Fi BRIDGE v0.03 dla ESP8266
  7. //
  8. // LICENCJA : Open Source (FREE)
  9. //
  10. // ------------------------------------------------------------------------------------------------------------ //
  11. // --- DOŁĄCZONE NAGŁÓWKI BIBLIOTEK --------------------------------------------------------------------------- //
  12. // ------------------------------------------------------------------------------------------------------------ //
  13.  
  14. #include <Arduino.h>
  15. #include <painlessMesh.h>
  16. #include <PubSubClient.h>
  17. #include <WiFiClient.h>
  18. #include <NTPClient.h>                                           // NTP klient (czas)
  19. #include <TimeLib.h>                                             // parser
  20. #include <WiFiUdp.h>                                             // UDP Wi-Fi
  21. #include <ESP8266HTTPClient.h>                                                            
  22. #include <WiFiClient.h>
  23. #include <ArduinoJson.h>
  24.  
  25. // ------------------------------------------------------------------------------------------------------------ //
  26. // --- D E F I N I C J E -------------------------------------------------------------------------------------- //
  27. // ------------------------------------------------------------------------------------------------------------ //
  28.  
  29. #define   MESH_PREFIX         "ESP_Root"                  // nazwa sieci MESH
  30. #define   MESH_PASSWORD       "ESP_Root"                  // hasło sieci MESH
  31. #define   MESH_PORT           5555                        // port  sieci MESH
  32.  
  33. #define   STATION_SSID        "DIABLO"                    // nazwa sieci Wi-Fi (router podłączony do sieci)
  34. #define   STATION_PASSWORD    "xxxxxxxxxxx"               // hasło sieci Wi-Fi (router podłączony do sieci)
  35.  
  36. #define   HOSTNAME            "ESP_Bridge"                // nazwa hosta (bridge) most sieci MESH i INTERNET
  37.  
  38. const String s_geo = "51.40";                             // szerokosc geograficzna Twojego Miasta
  39. const String d_geo = "16.20";                             // dlugosc geograficzna Twojego Miasta
  40.  
  41. String serverPath = "http://fcc-pogoda-api.glitch.me/api/current";       // darmowy serwer pogody
  42.  
  43. #define   TRUE      true
  44. #define   FALSE     false
  45.  
  46. #define   SERIAL  TRUE                                // włącz terminal
  47. #define   SPEED   115200                              // prędkość terminala
  48.  
  49. // ------------------------------------------------------------------------------------------------------------ //
  50. // --- P R O T O T Y P Y -------------------------------------------------------------------------------------- //
  51. // ------------------------------------------------------------------------------------------------------------ //
  52.  
  53. void receivedCallback( const uint32_t &from, const String &msg );
  54. void mqttCallback(char* topic, byte* payload, unsigned int length);
  55. void TimeDateUpdate();                                                      // aktualizuj czas z Serwera NTP
  56. void pogodaUpdate();                                                        // aktualizuj pogodę z Serwera FCC
  57.  
  58. // ------------------------------------------------------------------------------------------------------------ //
  59. // --- O B I E K T Y ------------------------------------------------------------------------------------------ //
  60. // ------------------------------------------------------------------------------------------------------------ //
  61.  
  62. WiFiUDP ntpUDP;                                                 // dla NTP (pobieranie czasu z internetu)
  63. NTPClient timeClient(ntpUDP, "pool.ntp.org", 3600);             // dla NTP (pobieranie czasu z internetu)
  64.  
  65. IPAddress getlocalIP();                                         // pobierz adres lokalny IP
  66. IPAddress myIP(0,0,0,0);                                        // mój adres IP
  67. IPAddress mqttBroker(192, 168, 1, 1);                           // mój adres IP
  68.  
  69. painlessMesh  mesh;                                             // obiekt mesh
  70.                                                                
  71. WiFiClient wifiClient;                                          // obiekt WiFi
  72. HTTPClient http;                                                // obiket HTTP
  73.  
  74. PubSubClient mqttClient(mqttBroker, 1883, mqttCallback, wifiClient);
  75.  
  76. // ------------------------------------------------------------------------------------------------------------ //
  77. // --- Z M I E N N E   G L O B A L N E ------------------------------------------------------------------------ //
  78. // ------------------------------------------------------------------------------------------------------------ //
  79.  
  80. struct NTP
  81. {
  82.     int8_t    Godzina;
  83.     int8_t    Minuta;
  84.     int8_t    Sekunda;
  85.     int8_t    Dzien;
  86.     int8_t    Miesiac;
  87.     int16_t   Rok;    
  88.     String    SformatowanyCzas;
  89.     String    SformatowanaData;
  90.     String    SformatowanyNTP;
  91. } ntp;
  92.  
  93. struct POGODA_SERVER
  94. {  
  95.     float           szerokosc_geograficzna  =  0;
  96.     float           dlugosc_geograficzna    =  0;
  97.     int             pogoda_0_id;
  98.     const char*     pogoda_0_main;
  99.     const char*     pogoda_0_description;
  100.     const char*     pogoda_0_icon;
  101.     const char*     baza;
  102.     float           temperatura;
  103.     float           cisnienie;
  104.     float           wilgotnosc;
  105.     float           temperatura_min;
  106.     float           temperatura_max;
  107.     float           poziom_wody;
  108.     float           wysokoc_npm;
  109.     float           wiatr_speed;
  110.     float           wiatr_deg;
  111.     int             zachmurzenie;
  112.     long            dt;
  113.     float           system_wiadomosc;
  114.     const char*     kraj;
  115.     long            wschod;
  116.     long            zachod;
  117.     long            id;
  118.     const char*     lokacja;
  119.     int             kod;
  120. }
  121. pogodaS;                                                            // dane pogodowe z Serwera
  122.  
  123. struct POGODA_NA_ZEWNATRZ
  124. {
  125.     float temperatura;
  126.     float cisnienie;  
  127. }
  128. pododaOUT;                                                           // dane pogodowe zewnętrzne z czujników
  129.  
  130. struct POGODA_W_WEWNATRZ
  131. {
  132.     float temperatura;
  133.     float cisnienie;  
  134. }
  135. pododaIN;                                                           // dane pogodowe wewnętrzne z czujników
  136.  
  137.  
  138.  
  139. unsigned long time_ZERO = 0;    
  140. unsigned long time_01S = 0;    
  141. unsigned long time_60S = 0;
  142. unsigned long time_out_01S = 0;
  143. unsigned long time_out_60S = 0;
  144.  
  145.  
  146. // ------------------------------------------------------------------------------------------------------------ //
  147. // --- o d b i o r n i k   b r o a d c a s t ------------------------------------------------------------------ //
  148. // ------------------------------------------------------------------------------------------------------------ //
  149.  
  150. void receivedCallback( const uint32_t &from, const String &msg )
  151. {
  152.     Serial.printf("ESP Bridge: Odebralem wiadomosc od wezla: %u o tresci: %s\n", from, msg.c_str());  
  153.    
  154.     mesh.sendSingle(from, ntp.SformatowanyNTP.c_str());          // wysyłam do nadawcy (tylko do nadawcy) !!!      
  155.  
  156.     #if SERIAL
  157.         Serial.printf("\n *** wysłałem do nadawcy - aktualny czas i datę ***\n");
  158.     #endif
  159. }
  160.  
  161. // ------------------------------------------------------------------------------------------------------------ //
  162. // --- m q t t   C a l l b a c k  ----------------------------------------------------------------------------- //
  163. // ------------------------------------------------------------------------------------------------------------ //
  164.  
  165. void mqttCallback(char* topic, uint8_t* payload, unsigned int length)
  166. {
  167.     char* cleanPayload = (char*)malloc(length+1);
  168.     memcpy(cleanPayload, payload, length);
  169.     cleanPayload[length] = '\0';
  170.     String msg = String(cleanPayload);
  171.     free(cleanPayload);
  172.  
  173.     String targetStr = String(topic).substring(16);
  174.  
  175.     if(targetStr == "gateway")
  176.     {
  177.         if(msg == "getNodes")
  178.         {
  179.             auto nodes = mesh.getNodeList(true);
  180.             String str;
  181.             for (auto &&id : nodes)
  182.                 str += String(id) + String(" ");
  183.                 mqttClient.publish("painlessMesh/from/gateway", str.c_str());
  184.         }
  185.     }
  186.     else
  187.     if(targetStr == "broadcast")
  188.     {
  189.         mesh.sendBroadcast(msg);
  190.     }
  191.     else
  192.     {
  193.         uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
  194.         if(mesh.isConnected(target))
  195.         {
  196.           mesh.sendSingle(target, msg);
  197.         }
  198.         else
  199.         {
  200.           mqttClient.publish("painlessMesh/from/gateway", "Klient nie podłaczony!");
  201.         }
  202.     }
  203. }
  204.  
  205. // ------------------------------------------------------------------------------------------------------------ //
  206. // --- p o b i e r z   a d r e s   I P  ----------------------------------------------------------------------- //
  207. // ------------------------------------------------------------------------------------------------------------ //
  208.  
  209. IPAddress getlocalIP()
  210. {
  211.     return IPAddress(mesh.getStationIP());
  212. }
  213.  
  214. // ------------------------------------------------------------------------------------------------------------ //
  215. // --- Aktualizacja Czasu i Daty  ----------------------------------------------------------------------------- //
  216. // ------------------------------------------------------------------------------------------------------------ //
  217.  
  218. void TimeDateUpdate()                                                                  
  219. {                            
  220.     timeClient.update();                                    // pobierz aktualny czas i datę z serwera NTP
  221.  
  222.     unsigned long epochTime = timeClient.getEpochTime();    // zapisz EpochTime                                            
  223.     struct tm *ptm = gmtime ((time_t *)&epochTime);         // struktura daty EpochTime                        
  224.  
  225.     ntp.Godzina    =   timeClient.getHours();               // zapisz godzinę z serwera NTP do struktury
  226.     ntp.Minuta     =   timeClient.getMinutes();             // zapisz minutę z serwera NTP do struktury
  227.     ntp.Sekunda    =   timeClient.getSeconds();             // zapisz sekundę z serwera NTP do stuktury
  228.  
  229.     ntp.Dzien     =   ptm->tm_mday;                         // dzień miesiąca                                                  
  230.     ntp.Miesiac   =   ptm->tm_mon+1;                        // aktualny miesiąc (musimy dodać +1)                
  231.     ntp.Rok       =   ptm->tm_year+1900;                    // aktualny rok (musimy dodać +1900)
  232.  
  233.     ntp.SformatowanyCzas  =   timeClient.getFormattedTime();
  234.     ntp.SformatowanaData  =   String(ntp.Dzien) + "." + String(ntp.Miesiac) + "." + String(ntp.Rok);
  235.    
  236.     ntp.SformatowanyNTP = ntp.SformatowanaData + " " + ntp.SformatowanyCzas;
  237. }    
  238.  
  239. // ------------------------------------------------------------------------------------------------------------ //
  240. // --- Aktualizacja Pogody z Serwera  ------------------------------------------------------------------------- //
  241. // ------------------------------------------------------------------------------------------------------------ //
  242.  
  243. void pogodaUpdate()
  244. {
  245.     String path = serverPath + "?lat=" + s_geo + "&lon=" + d_geo;       // ścieżka do serwera pogody
  246.  
  247.     String jsonBuffer = httpGETRequest(path.c_str());                   // pobierz i zapisz dane z serwera
  248.      
  249.     #if SERIAL
  250.         Serial.println(jsonBuffer);            
  251.     #endif
  252.  
  253.     int str_len = jsonBuffer.length() + 1;                              // ustal wielkość bufora    
  254.     char json[str_len];                                                 // przygotuj tablicę znaków (bufor)    
  255.     jsonBuffer.toCharArray(json, str_len);                              // kopiuj długość do tablicy  
  256.     StaticJsonDocument<1000> doc;                                       // odnieś się do obliczenia rozmiaru
  257.  
  258.     deserializeJson(doc, json);                                         // de-serializacja
  259.  
  260.     pogodaS.szerokosc_geograficzna = doc["coord"]["lon"];               // szerokosc geograficzna
  261.     pogodaS.dlugosc_geograficzna   = doc["coord"]["lat"];               // dlugosc geograficzna
  262.    
  263.     JsonObject pogoda_0 = doc["pogoda"][0];                          
  264.     pogodaS.pogoda_0_id = pogoda_0["id"];
  265.     pogodaS.pogoda_0_main = pogoda_0["main"];
  266.     pogodaS.pogoda_0_description = pogoda_0["description"];
  267.     pogodaS.pogoda_0_icon = pogoda_0["icon"];  
  268.     pogodaS.baza = doc["base"];
  269.  
  270.     JsonObject main = doc["main"];
  271.     pogodaS.temperatura = main["temp"];
  272.     pogodaS.cisnienie = main["pressure"];
  273.     pogodaS.wilgotnosc = main["humidity"];
  274.     pogodaS.temperatura_min = main["temp_min"];
  275.     pogodaS.temperatura_max = main["temp_max"];
  276.     pogodaS.poziom_wody = main["sea_level"];
  277.     pogodaS.wysokoc_npm = main["grnd_level"];
  278.     pogodaS.wiatr_speed = doc["wind"]["speed"];
  279.     pogodaS.wiatr_deg = doc["wind"]["deg"];
  280.     pogodaS.zachmurzenie = doc["clouds"]["all"];
  281.     pogodaS.dt = doc["dt"];
  282.  
  283.     JsonObject sys = doc["sys"];
  284.     pogodaS.system_wiadomosc = sys["message"];
  285.     pogodaS.kraj = sys["country"];
  286.     pogodaS.wschod = sys["sunrise"];
  287.     pogodaS.zachod = sys["sunset"];
  288.     pogodaS.id = doc["id"];
  289.     pogodaS.lokacja = doc["name"];
  290.     pogodaS.kod = doc["cod"];
  291. }
  292.  
  293. // ------------------------------------------------------------------------------------------------------------ //
  294. // --- Aktualizacja Pogody z Serwera  ------------------------------------------------------------------------- //
  295. // ------------------------------------------------------------------------------------------------------------ //
  296.  
  297. String httpGETRequest(const char* serverName)                                                        
  298. {                                                                                                    
  299.     HTTPClient http;                                                                                  
  300.     http.begin(serverName);                                                                          
  301.     int httpResponseCode = http.GET();                                                                
  302.     String bufor = "{}";                                                                              
  303.                                                                                                      
  304.     if ( httpResponseCode > 0 )                                                                      
  305.     {                                                                                                
  306.         #if SERIAL
  307.             //Serial.print("\nHTTP Response code: ");                                                  
  308.             //Serial.print(httpResponseCode);                                                      
  309.         #endif          
  310.                                                                                      
  311.         bufor = http.getString();                                                                    
  312.     }                                                                                                
  313.     else                                                                                              
  314.     {                                                                                                
  315.         #if SERIAL                                                                                  
  316.             //Serial.print("Error code: ");                                                          
  317.             //Serial.println(httpResponseCode);                                                      
  318.         #endif                                                                                        
  319.     }                                                                                                
  320.     http.end();                                                                                      
  321.     return bufor;                                                                                    
  322. }      
  323.  
  324. // ------------------------------------------------------------------------------------------------------------ //
  325. // --- MY TASK ------------------------------------------------------------------------------------------------ //
  326. // ------------------------------------------------------------------------------------------------------------ //
  327.  
  328. void my_task()
  329. {
  330.     time_ZERO =  millis();
  331.     time_01S  =  time_ZERO - time_out_01S;
  332.     time_60S  =  time_ZERO - time_out_60S;
  333.  
  334.     if(time_01S >= 1000UL)                          
  335.     {                  
  336.         TimeDateUpdate();                                           // aktualizuj czas z serwera co 1 sekundę
  337.         time_out_01S = time_ZERO;                        
  338.     }  
  339.  
  340.     if(time_60S >= 60000UL)                          
  341.     {                  
  342.         pogodaUpdate();                                            // aktualizuj pogodę z serwera co 1 minutę
  343.         time_out_60S = time_ZERO;                        
  344.     }
  345. }
  346.  
  347. // ------------------------------------------------------------------------------------------------------------ //
  348. // --- S E T U P ---------------------------------------------------------------------------------------------- //
  349. // ------------------------------------------------------------------------------------------------------------ //
  350.  
  351. void setup()
  352. {
  353.    
  354.     #if SERIAL
  355.         Serial.begin(SPEED);                // ustaw prędkość terminala SERIAL
  356.     #endif
  357.          
  358.     mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION );  // ustaw przed init (), abyś mógł zobaczyć komunikaty startowe
  359.  
  360.     mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
  361.     mesh.onReceive(&receivedCallback);
  362.     mesh.stationManual(STATION_SSID, STATION_PASSWORD);
  363.     mesh.setHostname(HOSTNAME);
  364.  
  365.     mesh.setRoot(true);                           // sieć MESH na tym urządzeniu jako ROOT  
  366.     mesh.setContainsRoot(true);                   // sieć MESH na tym urządzeniu jako ROOT
  367.  
  368.     timeClient.begin();                           // włącz klienta NTP (pobieranie czasu z internetu)
  369.  
  370. }
  371.  
  372. // ------------------------------------------------------------------------------------------------------------ //
  373. // --- L O O P ------------------------------------------------------------------------------------------------ //
  374. // ------------------------------------------------------------------------------------------------------------ //
  375.  
  376. void loop()
  377. {
  378.     mesh.update();                                                                // aktulizuj MESH
  379.     mqttClient.loop();                                                            // pętla dla klienta mqtt
  380.  
  381.     if(myIP != getlocalIP())                                                      // jeśli moje IP różne od lokalnego IP
  382.     {                                                                          
  383.         myIP = getlocalIP();                                                      // zapisz lokalne IP
  384.  
  385.         #if SERIAL
  386.             Serial.println("Adres lokalny IP: " + myIP.toString());
  387.         #endif
  388.  
  389.         if (mqttClient.connect("painlessMeshClient"))                             // jeśli client
  390.         {
  391.             mqttClient.publish("painlessMesh/from/gateway","Gotowe!");
  392.             mqttClient.subscribe("painlessMesh/to/#");
  393.         }
  394.     }  
  395.  
  396.     my_task();                                                                   // wywołaj moje zadania wg. harmonogramu
  397. }
  398.  
  399.  
  400. // ------------------------------------------------------------------------------------------------------------ //
  401. // --- E N D  ------------------------------------------------------------------------------------------------- //
  402. // ------------------------------------------------------------------------------------------------------------ //
  403.  
Advertisement
Add Comment
Please, Sign In to add comment