# Module 9 - IoT Platforms, Blynk, and Red Node

# 9.1 Learning Objectives

- Understand Blynk as a cloud-dependent IoT platform for mobile control and monitoring

- Implement basic control using Blynk's virtual pin system for LED switching

- Understand Node-RED as a flow-based visual programming tool for IoT integration

- Create basic data flows using Node-RED's visual editor to connect devices and services

# 9.2 Blynk

### Introduction to Blynk
Blynk is an IoT platform designed to facilitate remote monitoring and control of microcontroller-based projects through mobile applications. The platform operates on a client-server architecture where hardware devices communicate with a cloud server, which then relays information to and from mobile applications. This setup eliminates the need for direct device-to-app communication, simplifying the development process for IoT applications.

The platform consists of three main components:

1. Blynk Cloud server that handles message routing
2. Mobile applications for creating control interfaces
3. client libraries that run on embedded devices.

Devices connect to the Blynk server using various communication protocols including Wi-Fi, Ethernet, or cellular networks, while users interact with their devices through customizable dashboards on their smartphones.

### Technical Architecture
Blynk employs a token-based authentication system where each hardware device requires a unique authentication token to establish a connection with the Blynk cloud. This token links the physical device to a specific project created within the Blynk mobile application. The communication between devices and the cloud server occurs over standard protocols like TCP, with optional SSL encryption for secure data transmission.

Data exchange in Blynk follows a virtual pin model, where hardware devices map their sensors and actuators to virtual pin numbers. The mobile application widgets interact with these virtual pins, creating an abstraction layer that separates the hardware implementation from the user interface. This virtual pin system allows for flexible project design, as hardware changes don't necessarily require modifications to the mobile interface.

### Key Concepts and Limitations
Blynk operates primarily through widget-based controls that send and receive data via virtual pins. Buttons can send digital or analog values to devices, while display widgets can show sensor readings and other device states. The platform supports real-time data visualization, push notifications for alert conditions, and basic data logging capabilities.

However, Blynk has several technical limitations. The platform relies heavily on its cloud infrastructure, meaning all device communication must pass through Blynk's servers, creating potential points of failure and privacy concerns. There are also restrictions on the rate of data transmission and the number of widgets available in the free tier. For applications requiring local network communication or complex data processing, Blynk may not provide sufficient flexibility without paid upgrades or workarounds.

# 9.3 Blynk Tutorial

### Setup Blynk

1. Go to [Blynk Official Website](https://www.blynk.io/)

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762679205212.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762679205212.png)

2. Sign Up for a new account and login

3. Once you get redirected to Blynk Console, go to Developer Zone > My Templates and click the "New Template Button"

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762679588897.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762679588897.png)

4. Give the project name and description (optional)

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762679882935.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762679882935.png)

5. After creating the project, navigate to "Datastreams" and click the "edit" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680061410.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680061410.png)

6. Click on "New Datastream" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680118329.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680118329.png)

7. Click on "Virtual Pin"

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680186143.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680186143.png)

8. You can leave everything as it is for now and click "Create".

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680296149.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680296149.png)

Note: There are different data types available (Integer, Double, and String). You may need to change this depending on your needs, but for now we are going to use integer.

9. Now go to the Web Dashboard section and drag the "Switch" to the dashboard

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680648578.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680648578.png)

Note: you can adjust the layout of the "Switch" by dragging the small arrow in the bottom right corner

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680862478.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680862478.png)

10. Hover your cursor on the "Switch" and click the setting icon

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762680930507.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762680930507.png)

11. Change the Title to "LED" (Optional) and select Integer V0 (V0) for the Datastream, then click the "Save" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762681075898.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762681075898.png)

Note: Usually after selecting the datastream, additional options will show. For this tutorial I've set the On/Off label for demonstration purpose, however keep it mind that this is **optional**.

12. Click the "Save and Apply" Button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762681917419.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762681917419.png)

12. Now select "Devices" in the Blynk Console side bar and click the "New Device" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762681356604.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762681356604.png)

13. Click "From Template"

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762681404919.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762681404919.png)

14. Choose the template that we've created previously and click the "Create" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762681465273.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762681465273.png)

15. Copy all the information in the notification

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762681952834.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762681952834.png)

16. This will be your main web dashboard. If you want to edit it, you can refer back to step 9

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762682081761.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762682081761.png)

### Setup Wokwi

1. Go to [Wokwi Official Website](https://wokwi.com/) and create a new ESP32 project (you should've known how by now)

2. Copy this code and paste it into the wokwi project that you have created

```cpp
#define BLYNK_TEMPLATE_ID ""
#define BLYNK_TEMPLATE_NAME ""
#define BLYNK_AUTH_TOKEN ""

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

// Your WiFi credentials
char ssid[] = "Wokwi-GUEST";
char pass[] = "";

// LED pin
const int ledPin = 2;

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  
  // Initialize LED pin as output
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);  // Start with LED off
  
  // Connect to Blynk
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  
  Serial.println("Connecting to Blynk...");
}

// Blynk function that runs when Virtual Pin V0 changes
BLYNK_WRITE(V0) {
  int buttonState = param.asInt(); // Get button state (0 or 1)
  
  if (buttonState == 1) {
    digitalWrite(ledPin, HIGH);  // Turn LED ON
    Serial.println("LED turned ON");
  } else {
    digitalWrite(ledPin, LOW);   // Turn LED OFF
    Serial.println("LED turned OFF");
  }
}

void loop() {
  Blynk.run(); // Keep Blynk connection alive
}
```

Note: This code is used to connect to out Blynk Project that we've created. Notice how there is an led pin with number 2 — we'll try to toggle it using our switch in the Blynk dashboard.

3. Replace this code section with the information that you've just copied in step 15 of the Blynk Setup tutorial

```cpp
#define BLYNK_TEMPLATE_ID ""
#define BLYNK_TEMPLATE_NAME ""
#define BLYNK_AUTH_TOKEN ""
```

4. Create this sketch in your wokwi project

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762682625923.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762682625923.png)

5. Go to the Library Manager section in your wokwi and add "Blynk"

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762682692630.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762682692630.png)

Note: For reference, you can look up to this [Wokwi Project](https://wokwi.com/projects/447133612142700545)

6. Start the Simulation

7. Wait until the Serial Monitor shows "Connecting to Blynk.."

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762683017061.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762683017061.png)

8. Click the LED Switch in the Blynk Dashboard

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762683048819.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762683048819.png)

# 9.4 Node Red

### Introduction to Node-RED
Node-RED is a flow-based programming tool built on Node.js that enables visual development of IoT applications and automation systems. Originally created by IBM for wiring together hardware devices, APIs, and online services, it provides a browser-based editor where developers create applications by connecting nodes together to form processing flows. Unlike Blynk's mobile-focused approach, Node-RED operates as a local server that can be deployed on various devices from single-board computers to cloud instances.

The platform uses a modular architecture where each node represents a specific function, such as reading sensors, processing data, or triggering actions. These nodes are connected together in sequences called flows, which define how data moves through the system and gets transformed along the way. This visual programming approach makes complex IoT logic more accessible to developers who may not have extensive coding experience.

### Architecture and Deployment
Node-RED runs as a Node.js application, typically operating as a local web server on a designated port (default 1880). The runtime engine executes the flows, while the built-in web server provides both the visual editor and HTTP endpoints for external access. This architecture allows Node-RED to function as both a development environment and a runtime engine simultaneously.

A key advantage of Node-RED is its flexible deployment options. It can run directly on edge devices like Raspberry Pi for local processing, on servers for centralized control, or in cloud environments. The platform includes a built-in flow repository for saving and sharing configurations, and projects can be easily backed up through simple JSON file exports. This flexibility makes it suitable for everything from simple home automation to complex industrial IoT systems.

### Core Concepts and Data Handling
The fundamental building blocks in Node-RED are nodes, which are categorized into three types: input nodes that inject data or receive external messages, processing nodes that transform or route data, and output nodes that send data to external systems or devices. Nodes are connected by wires that carry message objects containing payload data and optional properties.

Node-RED handles data as JSON message objects that flow between connected nodes. Each message contains a payload property that holds the primary data, along with optional topic and metadata properties. The platform includes numerous built-in nodes for common IoT protocols including MQTT, HTTP, WebSockets, and serial communication. Additional functionality can be added through the extensive package manager, which provides thousands of community-contributed nodes for specialized hardware and services.

### Integration Capabilities and Use Cases
Node-RED excels at integrating diverse systems and protocols within a single visual environment. It can connect to databases, web services, messaging systems, and hardware devices simultaneously, making it effective for building complex IoT gateways. The platform includes built-in support for function nodes where developers can write custom JavaScript code for specialized processing logic that isn't available in pre-built nodes.

Common IoT applications for Node-RED include data aggregation from multiple sources, protocol translation between different IoT devices, automation rule execution, and data visualization through dashboard nodes. The platform's ability to handle both real-time processing and scheduled tasks makes it suitable for monitoring systems, smart home automation, industrial control systems, and data processing pipelines. Unlike cloud-dependent platforms, Node-RED can operate completely locally, providing greater control over data privacy and system reliability.

# 9.5 Node Red Tutorial

### Node Red Setup

1. In this tutorial, I am using a Linux terminal in Windows (WSL) for simplicity, if you're using other environment, that is fine too but some steps might be a little bit different, so be ready to adapt.

2. Install Node and NPM

```shell
sudo apt update
sudo apt install nodejs npm
```

3. Install Node Red

```shell
sudo npm install -g --unsafe-perm node-red
```

4. Run Node Red

```shell
node-red
```

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762684419132.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762684419132.png)

5. Access the Node Red server [http://127.0.0.1:1880/](http://127.0.0.1:1880/) in the web browser

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688581191.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688581191.png)

### Node Red Debug

1. Drag Inject Node in to the editor

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688652702.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688652702.png)

2. Double click the node and set the payload type to String

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688699606.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688699606.png)

3. Set the Payload and Topic to whatever you want, then click the "Done" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688777355.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688777355.png)

4. Drag the Debug Node in to the editor

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688823185.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688823185.png)

5. Connect both nodes

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688863642.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688863642.png)

6. Click the "Deploy" button in the top right corner

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688911321.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688911321.png)

7. Click the button in the inject node

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762688997300.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762688997300.png)

Node, ehem I mean Note: you can see the debug messages in the right section.

### Node Red Dashboard

1. Click the 3 stripes button in the top-right corner, then click "Manage Palette"

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762691282573.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762691282573.png)

2. Go to the "Install" section, search for `dashboard` in the search bar, then install the dashboard palette from `@flowfuse`. Click the "Done" button once it is finished.

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762691472306.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762691472306.png)

3. You should now see the "Dashboard 2" node section if you scroll down enough. If you don't, then try to refresh the web or try to restart Node Red. Once you found it, drag the "button" node to the editor

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762691758315.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762691758315.png)

4. Double click the button node, then set the name to "LED", group to default (look at the screenshot below for reference), Label to "Toggle LED" and click the "Done" button once it is all finished

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762691801156.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762691801156.png)

5. Now scroll above in the node section till you found the `Function` node section. Drag the "function" node to the editor and connect it with the "button" node that you've setup previously.

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762691905967.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762691905967.png)

6. Double click the "function" node and insert this code below, then click the "Done" button.

```python
// Store LED state
context.ledState = context.ledState || false;

// Toggle LED state when button pressed
context.ledState = !context.ledState;

// Create message
msg.payload = {
    led_state: context.ledState,
    timestamp: new Date().toISOString(),
    message: context.ledState ? "LED ON" : "LED OFF"
};

return msg;
```
[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762691986709.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762691986709.png)

Note: The code here is to simulate an LED, since we haven't integrate to Wokwi yet in this Tutorial.

7. Go back to the `Dashboard 2` section and drag the "Text Output" node in to the editor and connect it with the "function" node

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692202990.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692202990.png)

8. Double click the "Text Output" node then apply these configurations. Set name to "LED Status", set the group to default (see the screenshot below for reference), set the label to "LED Status:", make sure the value type is `msg` and its value is "payload.message", and set the Layout the same as seen in the screenshot below. Click the "Done" button once eveything is finished.

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692278980.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692278980.png)

9, Drag the "debug" node to the editor and connect it to the "function" node

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692457531.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692457531.png)

10. Click the dropdown icon in the top-right corner, then click on "Dashboard 2.0"

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692501213.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692501213.png)

11. Click on the setting of your default group

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692562936.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692562936.png)

12. Set the size to `3 x 1`. You can change the value later on to experiment on the dashboard layout, but for now we keep it on `3 x 1` for simplicity. Click the "Update" button, once it is finished.

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692629381.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692629381.png)

13. Click the "Deploy" button so that the changes are reflected

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692766146.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692766146.png)

14. To check on the dashboard, click the "open dashboard" button

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692811449.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692811449.png)

15. You should be directed to a page similar to this. Try clicking on the "Toggle LED" button and see what happens.

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692863136.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692863136.png)

16. You can also see the log history in the debug section since you use the "debug" node

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762692911406.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762692911406.png)

### Node Red x Wokwi

1. Drag the "Button Group" Node to the editor

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762696840921.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762696840921.png)

2. Double click the "Button Group" Node and apply this configuration

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697327183.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697327183.png)

3. Drag the "MQTT Out" Node to the editor

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697367733.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697367733.png)

4. Double click the "MQTT Out" node and add a MQTT server

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697414244.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697414244.png)

5. Apply this configuration and save the server

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697453418.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697453418.png)

6. Copy the remaining configuration for the "MQTT Out" node

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697742198.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697742198.png)

Note: After this I added a "Debug" node that connects with the "Button Group" Node, but this is fully optional for you

7. Drag the "MQTT In" node to the editor

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697851109.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697851109.png)

8. Double click the "MQTT IN" node and apply this configuration

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697894757.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697894757.png)

9. Drag the "Text Output" Node from the "Dashboard 2" Section and apply this configuration

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762697968748.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762697968748.png)

10. Create a new WOKWI ESP32 project and copy paste this code

```cpp
#include <WiFi.h>
#include <PubSubClient.h>

// Wokwi WiFi - works in simulation
const char* ssid = "Wokwi-GUEST";
const char* password = "";

const char* mqtt_server = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient client(espClient);

const int ledPin = 2;
bool ledState = false;

void setup_wifi() {
  delay(10);
  Serial.println("Connecting to WiFi...");
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  
  String messageTemp;
  for (int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  Serial.println(messageTemp);

  // Check if message is for LED control
  if (String(topic) == "wokwi/led/control") {
    Serial.print("Changing LED to ");
    if(messageTemp == "ON"){
      digitalWrite(ledPin, HIGH);
      ledState = true;
      Serial.println("ON");
      client.publish("wokwi/led/status", "ON");
    }
    else if(messageTemp == "OFF"){
      digitalWrite(ledPin, LOW);
      ledState = false;
      Serial.println("OFF");
      client.publish("wokwi/led/status", "OFF");
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "WokwiClient-";
    clientId += String(random(0xffff), HEX);
    
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Subscribe to control topic
      client.subscribe("wokwi/led/control");
      // Publish connected message
      client.publish("wokwi/led/status", "connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  
  Serial.begin(115200);
  setup_wifi();
  
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // Add a small delay
  delay(100);
}
```

11. Create the sketch where an LED is connected to PIN. The result should be similar to the following screenshot

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762698153192.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762698153192.png)

12. Add the `PubSubClient` library in the library manager

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762698188090.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762698188090.png)

13. Run the Wokwi simulation

Note: if you're having difficulties, you can follow [this](https://wokwi.com/projects/447150309147845633) as a reference

14. Deploy the Node Red project and go to the dashboard. You should be able to control the LED using the button there.

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762698319776.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762698319776.png)

[![](https://learn.digilabdte.com/uploads/images/gallery/2025-11/scaled-1680-/image-1762698344916.png)](https://learn.digilabdte.com/uploads/images/gallery/2025-11/image-1762698344916.png)