{"id":100202,"date":"2020-11-18T13:52:04","date_gmt":"2020-11-18T13:52:04","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=100202"},"modified":"2025-01-31T15:33:47","modified_gmt":"2025-01-31T15:33:47","slug":"esp-mesh-esp32-esp8266-painlessmesh","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp-mesh-esp32-esp8266-painlessmesh\/","title":{"rendered":"ESP-MESH with ESP32 and ESP8266: Getting Started (painlessMesh library)"},"content":{"rendered":"\n<p>Learn how to use ESP-MESH networking protocol to build a mesh network with the ESP32 and ESP8266 NodeMCU boards. ESP-MESH allows multiple devices (nodes) to communicate with each other under a single wireless local area network. It is supported on the ESP32 and ESP8266 boards. In this guide, we&#8217;ll show you how to get started with ESP-MESH using the Arduino core.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-with-ESP32-ESP8266-Getting-Started-f.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-MESH with ESP32 and ESP8266: Getting Started\" class=\"wp-image-100418\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-with-ESP32-ESP8266-Getting-Started-f.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-with-ESP32-ESP8266-Getting-Started-f.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-with-ESP32-ESP8266-Getting-Started-f.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-with-ESP32-ESP8266-Getting-Started-f.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>This article covers the following topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#1\">Introducing ESP-MESH<\/a><\/li>\n\n\n\n<li><a href=\"#2\">ESP-MESH Basic Example (Broadcast messages)<\/a><\/li>\n\n\n\n<li><a href=\"#3\">Exchange Sensor Readings using ESP-MESH (broadcast)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Arduino IDE<\/h2>\n\n\n\n<p>If you want to program the&nbsp;<a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32<\/a> and <a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266 <\/a>boards using Arduino IDE, you should have the ESP32 or ESP8266 add-ons installed. Follow the next guides:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp8266-nodemcu-arduino-ide-2-0\/\" title=\"\">Installing ESP8266 Board in Arduino IDE (Windows, Mac OS X, Linux)<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you want to program the ESP32\/ESP8266 using VS Code + PlatformIO, follow the next tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266 (Windows, Mac OS X, Linux Ubuntu)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"1\">Introducing ESP-MESH<\/h2>\n\n\n\n<p>Accordingly to the Espressif documentation:<\/p>\n\n\n\n<p>&#8220;ESP-MESH is a networking protocol built atop the Wi-Fi protocol. ESP-MESH allows numerous devices (referred to as nodes) spread over a large physical area (both indoors and outdoors) to be interconnected under a single WLAN (Wireless Local-Area Network). <\/p>\n\n\n\n<p>ESP-MESH is self-organizing and self-healing meaning the network can be built and maintained autonomously.&#8221; For more information, visit the <a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-guides\/mesh.html\" target=\"_blank\" rel=\"noreferrer noopener\">ESP-MESH official documentation<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Traditional Wi-Fi Network Architecture<\/h3>\n\n\n\n<p>In a traditional Wi-Fi network architecture, a single node (access point &#8211; usually the router) is connected to all other nodes (stations). Each node can communicate with each other using the access point. However, this is limited to the access point wi-fi coverage. Every station must be in the range to connect directly to the access point. This doesn&#8217;t happen with ESP-MESH.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"900\" height=\"500\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/Traditional-Wi-Fi-Network-ESP32-ESP8266.png?resize=900%2C500&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Traditional Wi-Fi Network ESP32 ESP8266\" class=\"wp-image-100349\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/Traditional-Wi-Fi-Network-ESP32-ESP8266.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/Traditional-Wi-Fi-Network-ESP32-ESP8266.png?resize=300%2C167&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/Traditional-Wi-Fi-Network-ESP32-ESP8266.png?resize=768%2C427&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">ESP-MESH Network Architecture<\/h3>\n\n\n\n<p>With ESP-MESH, the nodes don&#8217;t need to connect to a central node. Nodes are responsible for relaying each others transmissions. This allows multiple devices to spread over a large physical area. The Nodes can self-organize and dynamically talk to each other to ensure that the packet reaches its final node destination. If any node is removed from the network, it is able to self-organize to make sure that the packets reach their destination.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"900\" height=\"500\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Network-ESP32-ESP8266i.png?resize=900%2C500&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-MESH Network ESP32 ESP8266i\" class=\"wp-image-100351\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Network-ESP32-ESP8266i.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Network-ESP32-ESP8266i.png?resize=300%2C167&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Network-ESP32-ESP8266i.png?resize=768%2C427&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">painlessMesh Library<\/h2>\n\n\n\n<p>The <a href=\"https:\/\/gitlab.com\/painlessMesh\/painlessMesh\" target=\"_blank\" rel=\"noreferrer noopener\">painlessMesh library<\/a> allows us to create a mesh network with the ESP8266 or\/and ESP32 boards in an easy way.<\/p>\n\n\n\n<p>&#8220;painlessMesh is a true ad-hoc network, meaning that no-planning, central controller, or router is required. Any system of 1 or more nodes will self-organize into fully functional mesh. The maximum size of the mesh is limited (we think) by the amount of memory in the heap that can be allocated to the sub-connections buffer and so should be really quite high.&#8221; <a href=\"https:\/\/gitlab.com\/painlessMesh\/painlessMesh\" target=\"_blank\" rel=\"noreferrer noopener\">More information about the painlessMesh library<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Installing painlessMesh Library<\/h3>\n\n\n\n<p>You can install painlessMesh through the Arduino Library manager. Go to <strong>Tools<\/strong> &gt; <strong>Manage Libraries<\/strong>. The Library Manager should open.<\/p>\n\n\n\n<p>Search for &#8220;<strong>painlessmesh<\/strong>&#8221; and install the library. We&#8217;re using Version 1.4.5<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"786\" height=\"443\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmesh-esp-library-Arduino-IDE.png?resize=786%2C443&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Install painlessMesh library Arduino IDE\" class=\"wp-image-100214\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmesh-esp-library-Arduino-IDE.png?w=786&amp;quality=100&amp;strip=all&amp;ssl=1 786w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmesh-esp-library-Arduino-IDE.png?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmesh-esp-library-Arduino-IDE.png?resize=768%2C433&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/figure><\/div>\n\n\n<p>This library needs some other library dependencies. A new window should pop up asking you to install any missing dependencies. Select &#8220;Install all&#8221;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"477\" height=\"219\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmes-library-dependencies.png?resize=477%2C219&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Install painlessmesh library dependencies Arduino IDE\" class=\"wp-image-100215\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmes-library-dependencies.png?w=477&amp;quality=100&amp;strip=all&amp;ssl=1 477w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/install-painlessmes-library-dependencies.png?resize=300%2C138&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 477px) 100vw, 477px\" \/><\/figure><\/div>\n\n\n<p>If this window doesn&#8217;t show up, you&#8217;ll need to install the following library dependencies:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/bblanchon\/ArduinoJson\" target=\"_blank\" rel=\"noreferrer noopener\">ArduinoJson<\/a> (by bblanchon)<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/arkhipenko\/TaskScheduler\" target=\"_blank\" rel=\"noreferrer noopener\">TaskScheduler<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncTCP\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncTCP<\/a> (ESP8266) <\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/ESP32Async\/AsyncTCP\/archive\/refs\/heads\/main.zip\" title=\"\">AsyncTCP <\/a>(ESP32)<\/li>\n<\/ul>\n\n\n\n<p>If you&#8217;re using <a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">PlatformIO<\/a>, add the following lines to the <span class=\"rnthl rntliteral\">platformio.ini<\/span> file to add the libraries and change the monitor speed.<\/p>\n\n\n\n<p>For the ESP32:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>monitor_speed = 115200\nlib_deps = painlessmesh\/painlessMesh @ ^1.4.5\n    ArduinoJson\n    arduinoUnity\n    TaskScheduler\n    AsyncTCP<\/code><\/pre>\n\n\n\n<p>For the ESP8266:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>monitor_speed = 115200\nlib_deps = painlessmesh\/painlessMesh @ ^1.4.5\n    ArduinoJson\n    TaskScheduler\n    ESPAsyncTCP<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2\">ESP-MESH Basic Example (Broadcast messages)<\/h2>\n\n\n\n<p>To get started with ESP-MESH, we&#8217;ll first experiment with the library&#8217;s basic example. This example creates a mesh network in which all boards broadcast messages to all the other boards. <\/p>\n\n\n\n<p>We&#8217;ve experimented this example with four boards (two <a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32<\/a> and two <a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266<\/a>). You can add or remove boards. The code is compatible with both the ESP32 and ESP8266 boards.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"500\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-painlessMesh-basic-example-ESP32-ESP8266.png?resize=900%2C500&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-MESH painlessMesh basic example ESP32 ESP8266\" class=\"wp-image-100352\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-painlessMesh-basic-example-ESP32-ESP8266.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-painlessMesh-basic-example-ESP32-ESP8266.png?resize=300%2C167&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-painlessMesh-basic-example-ESP32-ESP8266.png?resize=768%2C427&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">Code &#8211; painlessMesh Library Basic Example<\/h3>\n\n\n\n<p>Copy the following code to your Arduino IDE (code from the library examples). The code is compatible with both the ESP32 and ESP8266 boards.<\/p>\n\n\n\n<p class=\"rntbox rntcred\">If you&#8217;re using an ESP32, you need to downgrade your ESP32 boards&#8217; add-on to version 2.0.X. At the moment, the painlessMesh library is not compatible with version 3.X.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp-mesh-esp32-esp8266-painlessmesh\/\n  \n  This is a simple example that uses the painlessMesh library: https:\/\/github.com\/gmag11\/painlessMesh\/blob\/master\/examples\/basic\/basic.ino\n*\/\n\n#include &quot;painlessMesh.h&quot;\n\n#define   MESH_PREFIX     &quot;whateverYouLike&quot;\n#define   MESH_PASSWORD   &quot;somethingSneaky&quot;\n#define   MESH_PORT       5555\n\nScheduler userScheduler; \/\/ to control your personal task\npainlessMesh  mesh;\n\n\/\/ User stub\nvoid sendMessage() ; \/\/ Prototype so PlatformIO doesn't complain\n\nTask taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &amp;sendMessage );\n\nvoid sendMessage() {\n  String msg = &quot;Hi from node1&quot;;\n  msg += mesh.getNodeId();\n  mesh.sendBroadcast( msg );\n  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));\n}\n\n\/\/ Needed for painless library\nvoid receivedCallback( uint32_t from, String &amp;msg ) {\n  Serial.printf(&quot;startHere: Received from %u msg=%s\\n&quot;, from, msg.c_str());\n}\n\nvoid newConnectionCallback(uint32_t nodeId) {\n    Serial.printf(&quot;--&gt; startHere: New Connection, nodeId = %u\\n&quot;, nodeId);\n}\n\nvoid changedConnectionCallback() {\n  Serial.printf(&quot;Changed connections\\n&quot;);\n}\n\nvoid nodeTimeAdjustedCallback(int32_t offset) {\n    Serial.printf(&quot;Adjusted time %u. Offset = %d\\n&quot;, mesh.getNodeTime(),offset);\n}\n\nvoid setup() {\n  Serial.begin(115200);\n\n\/\/mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); \/\/ all types on\n  mesh.setDebugMsgTypes( ERROR | STARTUP );  \/\/ set before init() so that you can see startup messages\n\n  mesh.init( MESH_PREFIX, MESH_PASSWORD, &amp;userScheduler, MESH_PORT );\n  mesh.onReceive(&amp;receivedCallback);\n  mesh.onNewConnection(&amp;newConnectionCallback);\n  mesh.onChangedConnections(&amp;changedConnectionCallback);\n  mesh.onNodeTimeAdjusted(&amp;nodeTimeAdjustedCallback);\n\n  userScheduler.addTask( taskSendMessage );\n  taskSendMessage.enable();\n}\n\nvoid loop() {\n  \/\/ it will run the user scheduler as well\n  mesh.update();\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Mesh\/ESP_Mesh_Basic.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Before uploading the code, you can set up the <span class=\"rnthl rntliteral\">MESH_PREFIX<\/span> (it&#8217;s like the name of the MESH network) and the <span class=\"rnthl rntliteral\">MESH_PASSWORD<\/span> variables (you can set it to whatever you like).<\/p>\n\n\n\n<p>Then, we recommend that you change the following line for each board to easily identify the node that sent the message. For example, for node 1, change the message as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String msg = \"Hi from node 1 \";<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>Start by including the <span class=\"rnthl rntliteral\">painlessMesh<\/span> library.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include \"painlessMesh.h\"<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">MESH Details<\/h4>\n\n\n\n<p>Then, add the mesh details. The <span class=\"rnthl rntliteral\">MESH_PREFIX<\/span> refers to the name of the mesh. You can change it to whatever you like.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define MESH_PREFIX \"whateverYouLike\"<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">MESH_PASSWORD<\/span>, as the name suggests is the mesh password. You can change it to whatever you like. <\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define MESH_PASSWORD \"somethingSneaky\"<\/code><\/pre>\n\n\n\n<p>All nodes in the mesh should use the same <span class=\"rnthl rntliteral\">MESH_PREFIX<\/span> and <span class=\"rnthl rntliteral\">MESH_PASSWORD<\/span>.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">MESH_PORT<\/span> refers to the the TCP port that you want the mesh server to run on. The default is 5555.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define MESH_PORT 5555<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Scheduler<\/h4>\n\n\n\n<p>It is recommended to avoid using <span class=\"rnthl rntliteral\">delay()<\/span> in the mesh network code. To maintain the mesh, some tasks need to be performed in the background. Using <span class=\"rnthl rntliteral\">delay()<\/span> will stop these tasks from happening and can cause the mesh to lose stability\/fall apart. <\/p>\n\n\n\n<p>Instead, it is recommended to use <span class=\"rnthl rntliteral\">TaskScheduler<\/span> to run your tasks which is used in painlessMesh itself.<\/p>\n\n\n\n<p>The following line creates a new <span class=\"rnthl rntliteral\">Scheduler<\/span> called <span class=\"rnthl rntliteral\">userScheduler<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Scheduler userScheduler; \/\/ to control your personal task<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">painlessMesh<\/h4>\n\n\n\n<p>Create a <span class=\"rnthl rntliteral\">painlessMesh<\/span> object called <span class=\"rnthl rntliteral\">mesh<\/span> to handle the mesh network.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Create tasks<\/h4>\n\n\n\n<p>Create a task called <span class=\"rnthl rntliteral\">taskSendMessage<\/span> responsible for calling the <span class=\"rnthl rntliteral\">sendMessage()<\/span> function every second as long as the program is running.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Task taskSendMessage(TASK_SECOND * 1 , TASK_FOREVER, &amp;sendMessage);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Send a Message to the Mesh<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">sendMessage()<\/span> function sends a message to all nodes in the message network (broadcast).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void sendMessage() {\n  String msg = \"Hi from node 1\";\n  msg += mesh.getNodeId();\n  mesh.sendBroadcast( msg );\n  taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));\n}<\/code><\/pre>\n\n\n\n<p>The message contains the &#8220;<span class=\"rnthl rntliteral\">Hi from node 1<\/span>&#8221; text followed by the board chip ID.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String msg = \"Hi from node 1\";\nmsg += mesh.getNodeId();<\/code><\/pre>\n\n\n\n<p>To broadcast a message, simply use the <span class=\"rnthl rntliteral\">sendBroadcast()<\/span> method on the <span class=\"rnthl rntliteral\">mesh<\/span> object and pass as argument the message (<span class=\"rnthl rntliteral\">msg<\/span>) you want to send.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>mesh.sendBroadcast(msg);<\/code><\/pre>\n\n\n\n<p>Every time a new message is sent, the code changes the interval between messages (one to five seconds).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Mesh Callback Functions<\/h4>\n\n\n\n<p>Next, several callback functions are created that will be called when specific events happen on the mesh.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">receivedCallback()<\/span> function prints the message sender (<span class=\"rnthl rntliteral\">from<\/span>) and the content of the message (<span class=\"rnthl rntliteral\">msg.c_str()<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void receivedCallback( uint32_t from, String &amp;msg ) {\n  Serial.printf(\"startHere: Received from %u msg=%s\\n\", from, msg.c_str());\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">newConnectionCallback()<\/span> function runs whenever a new node joins the network. This function simply prints the chip ID of the new node. You can modify the function to do any other task.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void newConnectionCallback(uint32_t nodeId) {\n  Serial.printf(\"--&gt; startHere: New Connection, nodeId = %u\\n\", nodeId);\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">changedConnectionCallback()<\/span> function runs whenever a connection changes on the network (when a node joins or leaves the network).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void changedConnectionCallback() {\n  Serial.printf(\"Changed connections\\n\");\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">nodeTimeAdjustedCallback()<\/span> function runs when the network adjusts the time, so that all nodes are synchronized. It prints the offset.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void nodeTimeAdjustedCallback(int32_t offset) {\n  Serial.printf(\"Adjusted time %u. Offset = %d\\n\", mesh.getNodeTime(),offset);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the serial monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Choose the desired debug message types:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); \/\/ all types on\n\nmesh.setDebugMsgTypes( ERROR | STARTUP );  \/\/ set before init() so that you can see startup messages<\/code><\/pre>\n\n\n\n<p>Initialize the mesh with the details defined earlier.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>mesh.init(MESH_PREFIX, MESH_PASSWORD, &amp;userScheduler, MESH_PORT);<\/code><\/pre>\n\n\n\n<p>Assign all the callback functions to their corresponding events.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>mesh.onReceive(&amp;receivedCallback);\nmesh.onNewConnection(&amp;newConnectionCallback);\nmesh.onChangedConnections(&amp;changedConnectionCallback);\nmesh.onNodeTimeAdjusted(&amp;nodeTimeAdjustedCallback);<\/code><\/pre>\n\n\n\n<p>Finally, add the <span class=\"rnthl rntliteral\">taskSendMessage<\/span> function to the <span class=\"rnthl rntliteral\">userScheduler<\/span>. The scheduler is responsible for handling and running the tasks at the right time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>userScheduler.addTask(taskSendMessage);<\/code><\/pre>\n\n\n\n<p>Finally, enable the <span class=\"rnthl rntliteral\">taskSendMessage<\/span>, so that the program starts sending the messages to the mesh.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>taskSendMessage.enable();<\/code><\/pre>\n\n\n\n<p>To keep the mesh running, add <span class=\"rnthl rntliteral\">mesh.update()<\/span> to the <span class=\"rnthl rntliteral\">loop()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  \/\/ it will run the user scheduler as well\n  mesh.update();\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>Upload the code provided to all your boards. Don&#8217;t forget to modify the message to easily identify the sender node<\/p>\n\n\n\n<p>With the boards connected to your computer, open a serial connection with each board. You can use the Serial Monitor, or you can use a software like <a href=\"https:\/\/www.putty.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">PuTTY<\/a> and open multiple windows for all the boards.<\/p>\n\n\n\n<p>You should see that all boards receive each others messages. For example, these are the messages received by Node 1. It receives the messages from Node 2, 3 and 4.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"262\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-basic-example-4-boards-Serial-Monitor-ESP8266-ESP32.png?resize=760%2C262&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-MESH Basic Example 4 Boards Arduino Serial Monitor\" class=\"wp-image-100388\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-basic-example-4-boards-Serial-Monitor-ESP8266-ESP32.png?w=760&amp;quality=100&amp;strip=all&amp;ssl=1 760w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-basic-example-4-boards-Serial-Monitor-ESP8266-ESP32.png?resize=300%2C103&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 760px) 100vw, 760px\" \/><\/figure><\/div>\n\n\n<p>You should also see other messages when there are changes on the mesh: when a board leaves or joins the network.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"252\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-basic-example-Serial-Monitor-Changed-Connections.png?resize=760%2C252&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP MESH Basic Example Serial Monitor Changed Connections\" class=\"wp-image-100242\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-basic-example-Serial-Monitor-Changed-Connections.png?w=760&amp;quality=100&amp;strip=all&amp;ssl=1 760w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-basic-example-Serial-Monitor-Changed-Connections.png?resize=300%2C99&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 760px) 100vw, 760px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"3\">Exchange Sensor Readings using ESP-MESH<\/h2>\n\n\n\n<p>In this next example, we&#8217;ll exchange sensor readings between 4 boards (you can use a different number of boards). Every board receives the other boards&#8217; readings.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"540\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchnage-BME280-Sensor-Readings-ESP32-ESP8266.png?resize=900%2C540&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-MESH Exchange BME280 Sensor Readings ESP32 ESP8266\" class=\"wp-image-100350\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchnage-BME280-Sensor-Readings-ESP32-ESP8266.png?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchnage-BME280-Sensor-Readings-ESP32-ESP8266.png?resize=300%2C180&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchnage-BME280-Sensor-Readings-ESP32-ESP8266.png?resize=768%2C461&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<p>As an example, we&#8217;ll exchange sensor readings from a <a href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME280 sensor<\/a>, but you can use any other sensor.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parts Required<\/h3>\n\n\n\n<p>Here&#8217;s the parts required for this example:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>4x ESP boards (<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32<\/a> or <a href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266<\/a>)<\/li>\n\n\n\n<li>4x <a href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME280<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Arduino_JSON library<\/h3>\n\n\n\n<p>In this example, we&#8217;ll exchange the sensor readings in JSON format. To make it easier to handle JSON variables, we&#8217;ll use the <a href=\"https:\/\/github.com\/arduino-libraries\/Arduino_JSON\" target=\"_blank\" rel=\"noreferrer noopener\">Arduino_JSON library<\/a>. <\/p>\n\n\n\n<p>You can install this library in the Arduino IDE Library Manager. Just go to&nbsp;<strong>Sketch&nbsp;<\/strong>&gt;&nbsp;<strong>Include Library<\/strong>&nbsp;&gt;&nbsp;<strong>Manage Libraries<\/strong>&nbsp;and search for the library name as follows:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"786\" height=\"443\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/Install-Arduino-JSON-library-Arduino-IDE.png?resize=786%2C443&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Install Arduino JSON library Arduino IDE\" class=\"wp-image-93172\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/Install-Arduino-JSON-library-Arduino-IDE.png?w=786&amp;quality=100&amp;strip=all&amp;ssl=1 786w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/Install-Arduino-JSON-library-Arduino-IDE.png?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/01\/Install-Arduino-JSON-library-Arduino-IDE.png?resize=768%2C433&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/figure><\/div>\n\n\n<p>If you&#8217;re using VS Code with PlatformIO, include the libraries in the <span class=\"rnthl rntliteral\">platformio.ini<\/span> file as follows:<\/p>\n\n\n\n<p><strong>ESP32<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>monitor_speed = 115200\nlib_deps = painlessmesh\/painlessMesh @ ^1.4.5\n    ArduinoJson\n    arduinoUnity\n    AsyncTCP\n    TaskScheduler\n    adafruit\/Adafruit Unified Sensor @ ^1.1.4\n    adafruit\/Adafruit BME280 Library @ ^2.1.2\n    arduino-libraries\/Arduino_JSON @ ^0.1.0<\/code><\/pre>\n\n\n\n<p><strong>ESP8266<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>monitor_speed = 115200\nlib_deps = painlessmesh\/painlessMesh @ ^1.4.5\n    ArduinoJson\n    TaskScheduler\n    ESPAsyncTCP\n    adafruit\/Adafruit Unified Sensor @ ^1.1.4\n    adafruit\/Adafruit BME280 Library @ ^2.1.2\n    arduino-libraries\/Arduino_JSON @ ^0.1.0<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Circuit Diagram<\/h2>\n\n\n\n<p>Wire the BME280 sensor to the ESP32 or ESP8266 default I2C pins as shown in the following schematic diagrams.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ESP32<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"675\" height=\"670\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?resize=675%2C670&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BME280 Sensor Temperature Humidity Pressure Wiring Diagram Circuit\" class=\"wp-image-99755\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?w=675&amp;quality=100&amp;strip=all&amp;ssl=1 675w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?resize=300%2C298&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 675px) 100vw, 675px\" \/><\/figure><\/div>\n\n\n<p>Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\">ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ESP8266 NodeMCU<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"675\" height=\"531\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/07\/ESP8266-NodeMCU-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit.png?resize=675%2C531&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU BME280 Sensor Temperature Humidity Pressure Wiring Diagram Circuit\" class=\"wp-image-98049\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/07\/ESP8266-NodeMCU-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit.png?w=675&amp;quality=100&amp;strip=all&amp;ssl=1 675w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/07\/ESP8266-NodeMCU-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit.png?resize=300%2C236&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 675px) 100vw, 675px\" \/><\/figure><\/div>\n\n\n<p>Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-bme280-arduino-ide\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266 with BME280 using Arduino IDE (Pressure, Temperature, Humidity)<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code &#8211; ESP-MESH Broadcast Sensor Readings<\/h2>\n\n\n\n<p>Upload the following code to each of your boards. This code reads and broadcasts the current temperature, humidity and pressure readings to all boards on the mesh network. The readings are sent as a JSON string that also contains the node number to identify the sender board.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp-mesh-esp32-esp8266-painlessmesh\/\n  \n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files.\n  \n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.\n*\/\n\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n#include &quot;painlessMesh.h&quot;\n#include &lt;Arduino_JSON.h&gt;\n\n\/\/ MESH Details\n#define   MESH_PREFIX     &quot;RNTMESH&quot; \/\/name for your MESH\n#define   MESH_PASSWORD   &quot;MESHpassword&quot; \/\/password for your MESH\n#define   MESH_PORT       5555 \/\/default port\n\n\/\/BME object on the default I2C pins\nAdafruit_BME280 bme;\n\n\/\/Number for this node\nint nodeNumber = 2;\n\n\/\/String to send to other nodes with sensor readings\nString readings;\n\nScheduler userScheduler; \/\/ to control your personal task\npainlessMesh  mesh;\n\n\/\/ User stub\nvoid sendMessage() ; \/\/ Prototype so PlatformIO doesn't complain\nString getReadings(); \/\/ Prototype for sending sensor readings\n\n\/\/Create tasks: to send messages and get readings;\nTask taskSendMessage(TASK_SECOND * 5 , TASK_FOREVER, &amp;sendMessage);\n\nString getReadings () {\n  JSONVar jsonReadings;\n  jsonReadings[&quot;node&quot;] = nodeNumber;\n  jsonReadings[&quot;temp&quot;] = bme.readTemperature();\n  jsonReadings[&quot;hum&quot;] = bme.readHumidity();\n  jsonReadings[&quot;pres&quot;] = bme.readPressure()\/100.0F;\n  readings = JSON.stringify(jsonReadings);\n  return readings;\n}\n\nvoid sendMessage () {\n  String msg = getReadings();\n  mesh.sendBroadcast(msg);\n}\n\n\/\/Init BME280\nvoid initBME(){\n  if (!bme.begin(0x76)) {\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\n    while (1);\n  }  \n}\n\n\/\/ Needed for painless library\nvoid receivedCallback( uint32_t from, String &amp;msg ) {\n  Serial.printf(&quot;Received from %u msg=%s\\n&quot;, from, msg.c_str());\n  JSONVar myObject = JSON.parse(msg.c_str());\n  int node = myObject[&quot;node&quot;];\n  double temp = myObject[&quot;temp&quot;];\n  double hum = myObject[&quot;hum&quot;];\n  double pres = myObject[&quot;pres&quot;];\n  Serial.print(&quot;Node: &quot;);\n  Serial.println(node);\n  Serial.print(&quot;Temperature: &quot;);\n  Serial.print(temp);\n  Serial.println(&quot; C&quot;);\n  Serial.print(&quot;Humidity: &quot;);\n  Serial.print(hum);\n  Serial.println(&quot; %&quot;);\n  Serial.print(&quot;Pressure: &quot;);\n  Serial.print(pres);\n  Serial.println(&quot; hpa&quot;);\n}\n\nvoid newConnectionCallback(uint32_t nodeId) {\n  Serial.printf(&quot;New Connection, nodeId = %u\\n&quot;, nodeId);\n}\n\nvoid changedConnectionCallback() {\n  Serial.printf(&quot;Changed connections\\n&quot;);\n}\n\nvoid nodeTimeAdjustedCallback(int32_t offset) {\n  Serial.printf(&quot;Adjusted time %u. Offset = %d\\n&quot;, mesh.getNodeTime(),offset);\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  \n  initBME();\n\n  \/\/mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); \/\/ all types on\n  mesh.setDebugMsgTypes( ERROR | STARTUP );  \/\/ set before init() so that you can see startup messages\n\n  mesh.init( MESH_PREFIX, MESH_PASSWORD, &amp;userScheduler, MESH_PORT );\n  mesh.onReceive(&amp;receivedCallback);\n  mesh.onNewConnection(&amp;newConnectionCallback);\n  mesh.onChangedConnections(&amp;changedConnectionCallback);\n  mesh.onNodeTimeAdjusted(&amp;nodeTimeAdjustedCallback);\n\n  userScheduler.addTask(taskSendMessage);\n  taskSendMessage.enable();\n}\n\nvoid loop() {\n  \/\/ it will run the user scheduler as well\n  mesh.update();\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Mesh\/ESP_Mesh_Broadcast_Sensor_Readings.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>The code is compatible with both the ESP32 and ESP8266 boards.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>Continue reading this section to learn how the code works.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Libraries<\/h4>\n\n\n\n<p>Start by including the required libraries: the <span class=\"rnthl rntliteral\">Adafruit_Sensor<\/span> and <span class=\"rnthl rntliteral\">Adafruit_BME280<\/span> to interface with the BME280 sensor; the <span class=\"rnthl rntliteral\">painlessMesh<\/span> library to handle the mesh network and the <span class=\"rnthl rntliteral\">Arduino_JSON<\/span> to create and handle JSON strings easily.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n#include \"painlessMesh.h\"\n#include &lt;Arduino_JSON.h&gt;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Mesh details<\/h4>\n\n\n\n<p>Insert the mesh details in the following lines. <\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define MESH_PREFIX    \"RNTMESH\" \/\/name for your MESH\n#define MESH_PASSWORD  \"MESHpassword\" \/\/password for your MESH\n#define MESH_PORT      5555 \/\/default port<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">MESH_PREFIX<\/span> refers to the name of the mesh. You can change it to whatever you like. The <span class=\"rnthl rntliteral\">MESH_PASSWORD<\/span>, as the name suggests is the mesh password. You can change it to whatever you like. All nodes in the mesh should use the same <span class=\"rnthl rntliteral\">MESH_PREFIX<\/span> and <span class=\"rnthl rntliteral\">MESH_PASSWORD<\/span>.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">MESH_PORT<\/span> refers to the the TCP port that you want the mesh server to run on. The default is 5555.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">BME280<\/h4>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">Adafruit_BME280<\/span> object called <span class=\"rnthl rntliteral\">bme<\/span> on the default ESP32 or ESP8266 pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_BME280 bme;<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">nodeNumber<\/span> variable insert the node number for your board. It must be a different number for each board.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>int nodeNumber = 2;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">readings<\/span> variable will be used to save the readings to be sent to the other boards.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String readings;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Scheduler<\/h4>\n\n\n\n<p>The following line creates a new <span class=\"rnthl rntliteral\">Scheduler<\/span> called <span class=\"rnthl rntliteral\">userScheduler<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Scheduler userScheduler; \/\/ to control your personal task<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">painlessMesh<\/h4>\n\n\n\n<p>Create a <span class=\"rnthl rntliteral\">painlessMesh<\/span> object called <span class=\"rnthl rntliteral\">mesh<\/span> to handle the mesh network.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Create tasks<\/h4>\n\n\n\n<p>Create a task called <span class=\"rnthl rntliteral\">taskSendMessage<\/span> responsible for calling the <span class=\"rnthl rntliteral\">sendMessage()<\/span> function every five seconds as long as the program is running.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Task taskSendMessage(TASK_SECOND * 5 , TASK_FOREVER, &amp;sendMessage);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">getReadings()<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">getReadings()<\/span> function gets temperature, humidity and pressure readings from the BME280 sensor and concatenates all the information, including the node number on a JSON variable called <span class=\"rnthl rntliteral\">jsonReadings<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>JSONVar jsonReadings;\njsonReadings&#091;\"node\"] = nodeNumber;\njsonReadings&#091;\"temp\"] = bme.readTemperature();\njsonReadings&#091;\"hum\"] = bme.readHumidity();\njsonReadings&#091;\"pres\"] = bme.readPressure()\/100.0F;<\/code><\/pre>\n\n\n\n<p>The following line shows the structure of the <span class=\"rnthl rntliteral\">jsonReadings<\/span> variable with arbitrary values.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>{\n  \"node\":2,\n  \"temperature\":24.51,\n  \"humidity\":52.01,\n  \"pressure\":1005.21\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">jsonReadings<\/span> variable is then converted into a JSON string using the <span class=\"rnthl rntliteral\">stringify()<\/span> method and saved on the <span class=\"rnthl rntliteral\">readings<\/span> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>readings = JSON.stringify(jsonReadings);<\/code><\/pre>\n\n\n\n<p>This variable is then returned by the function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>return readings;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Send a Message to the Mesh<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">sendMessage()<\/span> function sends the JSON string with the readings and node number (<span class=\"rnthl rntliteral\">getReadings()<\/span>) to all nodes in the network (broadcast).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void sendMessage () {\n  String msg = getReadings();\n  mesh.sendBroadcast(msg);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Init BME280 sensor<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initBME()<\/span> function initializes the BME280 sensor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void initBME(){\n  if (!bme.begin(0x76)) {\n    Serial.println(\"Could not find a valid BME280 sensor, check wiring!\");\n    while (1);\n  }\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Mesh Callback Functions<\/h4>\n\n\n\n<p>Next, several callback functions are created that will be called when some event on the mesh happens.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">receivedCallback()<\/span> function prints the message sender (<span class=\"rnthl rntliteral\">from<\/span>) and the content of the message (<span class=\"rnthl rntliteral\">msg.c_str()<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void receivedCallback( uint32_t from, String &amp;msg ) {\n  Serial.printf(\"startHere: Received from %u msg=%s\\n\", from, msg.c_str());<\/code><\/pre>\n\n\n\n<p>The message comes in JSON format, so, we can access the variables as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>JSONVar myObject = JSON.parse(msg.c_str());\nint node = myObject&#091;\"node\"];\ndouble temp = myObject&#091;\"temp\"];\ndouble hum = myObject&#091;\"hum\"];\ndouble pres = myObject&#091;\"pres\"];<\/code><\/pre>\n\n\n\n<p>Finally, print all the information on the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.print(\"Node: \");\nSerial.println(node);\nSerial.print(\"Temperature: \");\nSerial.print(temp);\nSerial.println(\" C\");\nSerial.print(\"Humidity: \");\nSerial.print(hum);\nSerial.println(\" %\");\nSerial.print(\"Pressure: \");\nSerial.print(pres);\nSerial.println(\" hpa\");<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">newConnectionCallback()<\/span> function runs whenever a new node joins the network. This function simply prints the chip ID of the new node. You can modify the function to do any other task.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void newConnectionCallback(uint32_t nodeId) {\n  Serial.printf(\"--&gt; startHere: New Connection, nodeId = %u\\n\", nodeId);\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">changedConnectionCallback()<\/span> function runs whenever a connection changes on the network (when a node joins or leaves the network).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void changedConnectionCallback() {\n  Serial.printf(\"Changed connections\\n\");\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">nodeTimeAdjustedCallback()<\/span> function runs when the network adjusts the time, so that all nodes are synchronized. It prints the offset.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void nodeTimeAdjustedCallback(int32_t offset) {\n  Serial.printf(\"Adjusted time %u. Offset = %d\\n\", mesh.getNodeTime(),offset);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">setup()<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the serial monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void setup() {\n  Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Call the <span class=\"rnthl rntliteral\">initBME()<\/span> function to initialize the BME280 sensor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>initBME();<\/code><\/pre>\n\n\n\n<p>Choose the desired debug message types:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); \/\/ all types on\n\nmesh.setDebugMsgTypes( ERROR | STARTUP );  \/\/ set before init() so that you can see startup messages<\/code><\/pre>\n\n\n\n<p>Initialize the mesh with the details defined earlier.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>mesh.init(MESH_PREFIX, MESH_PASSWORD, &amp;userScheduler, MESH_PORT);<\/code><\/pre>\n\n\n\n<p>Assign all the callback functions to their corresponding events.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>mesh.onReceive(&amp;receivedCallback);\nmesh.onNewConnection(&amp;newConnectionCallback);\nmesh.onChangedConnections(&amp;changedConnectionCallback);\nmesh.onNodeTimeAdjusted(&amp;nodeTimeAdjustedCallback);<\/code><\/pre>\n\n\n\n<p>Finally, add the <span class=\"rnthl rntliteral\">taskSendMessage<\/span> function to the <span class=\"rnthl rntliteral\">userScheduler<\/span>. The scheduler is responsible for handling and running the tasks at the right time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>userScheduler.addTask(taskSendMessage);<\/code><\/pre>\n\n\n\n<p>Finally, enable the <span class=\"rnthl rntliteral\">taskSendMessage<\/span>, so that the program starts sending the messages to the mesh.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>taskSendMessage.enable();<\/code><\/pre>\n\n\n\n<p>To keep the mesh running, add <span class=\"rnthl rntliteral\">mesh.update()<\/span> to the <span class=\"rnthl rntliteral\">loop()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  \/\/ it will run the user scheduler as well\n  mesh.update();\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Demonstration<\/h3>\n\n\n\n<p>After uploading the code to all your boards (each board with a different node number), you should see that each board is receiving the other boards&#8217; messages.<\/p>\n\n\n\n<p>The following screenshot shows the messages received by node 1. It receives the sensor readings from node 2, 3 and 4.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1139\" height=\"659\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchange-BME280-Sensor-Readings-ESP32-ESP8266-Serial-Monitor-f.png?resize=1139%2C659&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-MESH Exchange BME280 Sensor Readings ESP32 ESP8266 Serial Monitor f\" class=\"wp-image-100510\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchange-BME280-Sensor-Readings-ESP32-ESP8266-Serial-Monitor-f.png?w=1139&amp;quality=100&amp;strip=all&amp;ssl=1 1139w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchange-BME280-Sensor-Readings-ESP32-ESP8266-Serial-Monitor-f.png?resize=300%2C174&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchange-BME280-Sensor-Readings-ESP32-ESP8266-Serial-Monitor-f.png?resize=1024%2C592&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-Exchange-BME280-Sensor-Readings-ESP32-ESP8266-Serial-Monitor-f.png?resize=768%2C444&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1139px) 100vw, 1139px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>We hope you liked this quick introduction to the ESP-MESH networking protocol. You can take a look at the <a href=\"https:\/\/gitlab.com\/painlessMesh\/painlessMesh\" target=\"_blank\" rel=\"noreferrer noopener\">painlessMesh library<\/a> for more examples.<\/p>\n\n\n\n<p>We intend to create more tutorials about this subject on a near future. So, write your suggestions on the comments&#8217; section.<\/p>\n\n\n\n<p>You may also like the following articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-now-esp32-arduino-ide\/\">Getting Started with ESP-NOW (ESP32 with Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-now-esp8266-nodemcu-arduino-ide\/\">Getting Started with ESP-NOW (ESP8266 NodeMCU with Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp-now-wi-fi-web-server\/\">ESP32: ESP-NOW Web Server Sensor Dashboard (ESP-NOW + Wi-Fi)<\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP32 and ESP8266 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\" title=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\">Home Automation using ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">More ESP32 Projects and Tutorials<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\">More ESP8266 Projects and Tutorials<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to use ESP-MESH networking protocol to build a mesh network with the ESP32 and ESP8266 NodeMCU boards. ESP-MESH allows multiple devices (nodes) to communicate with each other under &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP-MESH with ESP32 and ESP8266: Getting Started (painlessMesh library)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp-mesh-esp32-esp8266-painlessmesh\/#more-100202\" aria-label=\"Read more about ESP-MESH with ESP32 and ESP8266: Getting Started (painlessMesh library)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":100418,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,281,277,299,264],"tags":[],"class_list":["post-100202","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-esp32-project","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/11\/ESP-MESH-with-ESP32-ESP8266-Getting-Started-f.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/100202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=100202"}],"version-history":[{"count":4,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/100202\/revisions"}],"predecessor-version":[{"id":167175,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/100202\/revisions\/167175"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/100418"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=100202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=100202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=100202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}