How to connect ESP32 to the smartphone using Node-RED

This project describes how to connect ESP32 to the smartphone using Node-RED running on the Raspberry Pi. In more detail, we will control, using a smartphone, a LED strip connected to the ESP32. Moreover, we will create a dashboard using Node-RED that will visualize sensor readings (temperature, humidity, and pressure). To acquire temperature and humidity, we will use the BME280 sensor connected to the ESP32.

What you will learn…

In this tutorial, you will learn:

  • How to connect the ESP32 to your smartphone through Node-RED
  • Building a UI dashboard using Node-RED
  • How to use your smartphone to interact with the ESP32

This tutorial requires a basic knowledge of Node-RED. Anyway, if you are new to it, you can simply copy and paste the code shown in this ESP32 project.

Project overview

Before diving into the details, it is useful to have an overview of this project. In order to integrate the ESP32 to the smartphone, it is necessary:

  • Create a dashboard using Node-RED so that the user can interact with ESP32 through the smartphone
  • Connect somehow the ESP32 to Node-RED so that Node-RED can receive sensor data and send commands to the ESP32 to control LEDs

There are several ways we can implement the integration between ESP32 and Node-RED and generally speaking between the ESP32 and an external system. Two of these methods are:

We have covered both methods in the previous posts (read how to implement an MQTT client to interact with an ESP32/ESP8266). In this post, we will use the Rest API approach.

The image below visualizes the project overview detailing how to connect the ESP32 to the smartphone using Node-RED as a gateway:

How to control ESP32 using smartphone with Node-RED gateay
  • Node-RED generates the UI dashboard that is visualized on the user mobile phone
  • Through the UI the user interacts with the ESP32
  • The ESP32 is connected to a BME280 sensor (temperature, humidity, pressure) and to a LED strip (i.e. WS2018B)
  • The ESP32 exposes a set of Rest JSON API that is used by Node-RED to control the ESP32

Connect the ESP32 to the Node-RED

We won’t cover again how to expose a rest interface using ESP32. To make this simple clone the Github repository:

git clone
Code language: PHP (php)

If you prefer you can download the repository zip file from the Github repository.

Next, import it in your IDE. This tutorial uses PlatformIO but you can use any IDE you like. Run the code. This code exposes several APIs. To control the ESP32 using the smartphone Node-RED will use only these two APIs:

  • /env that returns the current environment condition (such as temperature, pressure and humidity)
  • /led to control the LED strip

The first resource returns a JSON array that holds all the sensor data while to invoke the second using Node-RED we have to use the POST HTTP method with a payload that holds the three color components (red, green, blue).

If you want to more about Node-RED and Raspberry, you can read my other tutorial about how to use InfluxDB with MQTT to save sensor readings.

Raspberry Pi IoT: Sensors, InfluxDB, MQTT and Grafana
Getting started with ESP32: Build a weather station (BMP280 + SSD1306)
Implement a LoRa network using ESP32 TTGO and SX1276
How to monitor air quality with ESP32 and CCS811

Preparing Node-RED to handle the UI

In this step, we will build the UI that visualizes the data and the widget to control the RGB LED strip. To run Node-RED we are using Raspberry Pi but you can run it on your PC too. If you use RPi and Node-RED runs in a Docker container, you can use this command to run it:

sudo docker run -it -p 1880:1880 -v /home/pi/.node-red:/data nodered/node-red
Code language: JavaScript (javascript)

Connect to the Node-RED console using your browser:

Code language: JavaScript (javascript)

where raspberrypi3.local is your RPi address and 1880 is the default port. The flow is shown in the picture below:

The Node-RED flow uses:

  • A color picker so that the user can select the RGB LED color
  • a change node to map the r,g,b value to red, green and blue accepted by ESP32
  • Refresh button to refresh data
  • HTTP request node that makes the Node-RED connect to the ESP32 so that it reads the environment conditions
  • JSON node that creates a JSON object from the ESP32 API response
  • Three different set nodes that extract from the JSON response the temperature, pressure, and humidity

This is the flow:

[{"id":"8a63f92f.b9b558","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"51e06ea6.93e01","type":"ui_colour_picker","z":"8a63f92f.b9b558","name":"","label":"","group":"52176d81.284134","format":"rgb","outformat":"object","showSwatch":true,"showPicker":true,"showValue":false,"showHue":false,"showAlpha":false,"showLightness":true,"square":"false","dynOutput":"false","order":1,"width":0,"height":0,"passthru":true,"topic":"","x":100,"y":80,"wires":[["4d886e4f.8967b"]]},{"id":"4d886e4f.8967b","type":"change","z":"8a63f92f.b9b558","name":"","rules":[{"t":"move","p":"payload.r","pt":"msg","to":"","tot":"msg"},{"t":"move","p":"payload.g","pt":"msg","to":"","tot":"msg"},{"t":"move","p":"payload.b","pt":"msg","to":"","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":80,"wires":[["d518d7ee.e318a8"]]},{"id":"d518d7ee.e318a8","type":"http request","z":"8a63f92f.b9b558","name":"","method":"POST","ret":"txt","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":470,"y":80,"wires":[[]]},{"id":"21496864.3245c8","type":"http request","z":"8a63f92f.b9b558","name":"","method":"GET","ret":"txt","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"","x":290,"y":160,"wires":[["f247b9d0.935798"]]},{"id":"53308fff.ae04c","type":"ui_button","z":"8a63f92f.b9b558","name":"","group":"46097c7c.c45094","order":4,"width":0,"height":0,"passthru":false,"label":"Refresh","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":90,"y":160,"wires":[["21496864.3245c8"]]},{"id":"75ed61fb.613c2","type":"ui_gauge","z":"8a63f92f.b9b558","name":"","group":"46097c7c.c45094","order":1,"width":0,"height":0,"gtype":"gage","title":"gauge","label":"units","format":"{{value}}","min":"-10","max":"40","colors":["#0096ff","#00f900","#ca3838"],"seg1":"","seg2":"","x":850,"y":240,"wires":[]},{"id":"bb71cb58.3e5ca8","type":"change","z":"8a63f92f.b9b558","name":"Temperature","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[0].value","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":240,"wires":[["75ed61fb.613c2"]]},{"id":"125bdd16.b70bd3","type":"change","z":"8a63f92f.b9b558","name":"Humidity","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[1].value","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":320,"wires":[["3e3211ee.e8ed3e"]]},{"id":"4e11c947.138178","type":"change","z":"8a63f92f.b9b558","name":"Pressure","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[2].value","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":400,"wires":[["c00acd.ae58753"]]},{"id":"c00acd.ae58753","type":"ui_gauge","z":"8a63f92f.b9b558","name":"","group":"46097c7c.c45094","order":3,"width":0,"height":0,"gtype":"donut","title":"Pressure","label":"units","format":"{{value}}","min":"600","max":"1200","colors":["#929292","#00f900","#fffb00"],"seg1":"","seg2":"","x":870,"y":400,"wires":[]},{"id":"f247b9d0.935798","type":"json","z":"8a63f92f.b9b558","name":"","property":"payload","action":"","pretty":false,"x":310,"y":260,"wires":[["4e11c947.138178","125bdd16.b70bd3","bb71cb58.3e5ca8"]]},{"id":"3e3211ee.e8ed3e","type":"ui_gauge","z":"8a63f92f.b9b558","name":"","group":"46097c7c.c45094","order":2,"width":0,"height":0,"gtype":"wave","title":"Humidity","label":"%","format":"{{value}}","min":"0","max":"100","colors":["#0096ff","#00f900","#ca3838"],"seg1":"","seg2":"","x":860,"y":320,"wires":[]},{"id":"52176d81.284134","type":"ui_group","z":"","name":"RGB Led","tab":"e562a4a.39a9e58","order":1,"disp":true,"width":6,"collapse":false},{"id":"46097c7c.c45094","type":"ui_group","z":"","name":"Environment","tab":"29a564f0.c41aac","order":2,"disp":true,"width":"6","collapse":false},{"id":"e562a4a.39a9e58","type":"ui_tab","z":"","name":"ESP32 Dashboard","icon":"dashboard","order":1,"disabled":false,"hidden":false},{"id":"29a564f0.c41aac","type":"ui_tab","z":"","name":"Environment","icon":"dashboard","order":2,"disabled":false,"hidden":false}]
Code language: JSON / JSON with Comments (json)

You can import it in your Node-RED.

Deploy the flow in the Node-RED server and opens the UI Interface:

Testing the connection between ESP32 and the smartphone

Now we can test the connection between the ESP32 and the smartphone. One thing to notice is that the smartphone, the ESP32 and the Raspberry Pi must be on the same network. Open your smartphone browser and type:

Code language: JavaScript (javascript)

Now you can control the ESP32 using your smartphone. The result is shown below:

Integrate ESP32 with a smartphone. ESP32 reads sensor data using your smartphone through Node-RED

There are several ways to use BME280 with ESP32 in different scenarios. You can learn more about how to connect ESP32 with BME280.

Wrapping up

In summary, this project showed how to interact with the ESP32 using your smartphone. The interaction is mediated by the Node-RED UI that builds the UI dashboard. The user uses the dashboard to send commands to the ESP32 and too retrieve sensor readings visualizing them in a dashboard in the smartphone.