Book A Demo Now

Virtual IoT Development: Simulating ESP32 with WokWi and Bytebeam

Virtual IoT Development: Simulating ESP32 with WokWi and Bytebeam

In the realm of IoT development, where innovation knows no bounds, the ability to experiment and learn at one's own pace is paramount. However, the constraints of physical hardware often pose a significant hurdle. But fear not, for there exists an amazing web-based ESP32 simulator called WokWi, where you can simulate your IoT projects developed on ESP32.

In this blog, we will guide you through the steps to simulate ESP32 on WokWi and Bytebeam. We will create an IoT project involving Bytebeam and WokWi integration. This can be accomplished using the following easy steps

  1. Setting up the Bytebeam cloud console: We will be setting up a new project on the Bytebeam cloud console.
  2. Setting up WokWi VS-Code extension: We will be installing WokWi extension in VS-Code.
  3. Configuring WokWi for ESP32: In this step, we will configure ESP32 in WokWi.
  4. Going through code: In this step we will go through the example project.
  5. Data visualization on the Bytebeam cloud console: We will explore the data visualization tools by Bytebeam and learn how to view and analyze data from the connected Arduino device in real-time.

No more worries about hardware limitations! Whether you're an experienced developer or just getting started with IoT, this integration lets you dive into virtual prototyping and explore complex IoT ideas. Bytebeam and Wokwi are your partners in this journey, allowing your concepts to take off without physical hardware restrictions.

Software Requirements

  • ESP-IDF
  • Bytebeam ESP-IDF SDK
  • WokWi VS Code Extension

Getting Started with ByteBeam Cloud

Firstly, you need to create an account on Bytebeam Cloud (cloud.bytebeam.io). In case you already have an account with Bytebeam Cloud then you can proceed further with this guide or else follow Getting Started with Bytebeam Cloud.

Creating a new project

Login to your Bytebeam account to access the cloud console. Now, create a New Project and give it a name. I have given it the name “esp32wokwi”. In the next screen, you will be asked to select the project. Select the newly created project and proceed further

Provisioning a new device

Click on Create Device button to provision a new device to Bytebeam cloud. And hit Submit.

  • As you hit submit in the prompt. A new JSON file will be downloaded which contains the authentication certificate, broker, device_id, and project id. You need to save this file in the ESP file system. We will talk about this in a later section. The JSON will look like this.

{
"project_id": "****",
"broker": "******",
"port": 8883,
"device_id": "**",
"authentication": {
      "ca_certificate":*"*********",
      "device_certificate": "**********",
      "device_private_key": "***********"
      }
}

Setting up ByteBeam SDK for ESP-IDF

ByteBeam provides an SDK, built on top of the ESP-IDF framework to connect to the ByteBeam cloud platform.  This guide assumes that you have a fair understanding of ESP-IDF and that you have already set up ESP-IDF on your machine. In case you haven’t done this you should follow ESP-IDF Getting Started Guide before going further.

Next, you can follow Getting started with Bytebeam Part 1 to configure the Bytebeam ESP-IDF SDK.

Setting up WokWi VS-Code extension

To get started, you'll need to install the WokWi extension for Visual Studio Code (VSCode). We're using VSCode in this tutorial for coding. Wokwi is a handy tool for tech folks, especially those working on embedded systems and IoT. This extension easily fits into your coding setup, letting you run project simulations right from your code editor. For step-by-step instructions on setting up the WokWi extension in VSCode, refer to the WokWi Getting Started guide.


WokWi Simulator provides a virtual WiFi access point called Wokwi-GUEST. To configure this access point in ESP32 follow these steps

  • To change wifi configuration enter following command

Idf.py menuconfig

  • Next on the configuration page navigate to ExampleConnectionConfiguration
  • Then in WiFi SSID type Wokwi-Guest
  • Save the configuration

Configuring WokWi for ESP32

To simulate your project on Wokwi, you need to create two files in your project's root directory:

  • wokwi.toml - This file tells Wokwi how to handle your project's settings and run the project.
  • diagram.json - This file describes your circuit using a diagram.

We need to create these two files inside our project directory. A basic wokwi.toml file looks like this.

[wokwi]
version = 1
firmware = 'path-to-your-firmware.bin
elf = 'path-to-your-firmware.elf'

To know more about wokwi.toml visit WokWi to configure your project page

Now, let's discuss the "diagram.json" file. This file is essential because it outlines the detailed circuit setup you want to simulate. To gain a deeper understanding of how to work with "diagram.json", you can refer to the dedicated "Configure Your diagram.json" page on WokWi's platform.

To give you a glimpse, here's the basic structure of a "diagram.json" file.


 "version": 1,
 "author": "author_name",
 "editor": "wokwi",
 "parts": [],
 "connections": []
}
  • The "parts" section defines the list of components in the simulation. It's an array of objects.
Name Type Description
id string the unique identifier of the part (e.g. "led1")
type string the type of the part (e.g. "wokwi-led")
left number x screen coordinate (in pixels)
top number y screen coordinate (in pixels)
attrs object part attributes (e.g. "color" for wokwi-led)
rotate number rotation in degress (e.g. 90)
hide boolean if true, the part won't be visible
  • Combining these keywords, the parts object of the diagram.json will look like this
"parts": [
          {
       "type": "wokwi-led",
       "id": "led-red",
       "top": 6,
       "left": 129,
       "attrs": { "color": "red", "flip": "1", "label": "WiFi" }
     }
   ]
  • The "connections" section is like the master plan, The "connections" section defines how the parts are connected. Each connection is an array with four items:
    • The source component's ID and its pin name, separated by a colon (like "partId:pinName").
    • The target component's ID and its corresponding pin name, establishing the connection.
    • A color code for the wire, or empty string at all if you want to hide it.
    • Optionally, a set of instructions in the form of a string array, guiding you on precisely where to place the wire in the circuit. These instructions are like your blueprint for creating connections.
  • For example, the following definition will connect TX0 pin of ESP32 to RX of serial monitor
 [ "esp:TX0", "$serialMonitor:RX", "", [] ]

Configuring Actions

  • Navigate to examples -> hello_wokwi
  • Then open the project directory in VS-code
code .
  • The project structure looks like this
* Main
|----	App_main.c
|---- CMakeLists.txt
|---- Idf_component.yml
* CMakeLists.txt
* Diagram.json
* Wokwi.toml
* partitions_example.csv
  • Now navigate to app_main.c
  • Inside app_main.c, First include the bytebeam sdk header and declare the bytebeam_client_t variable. It is a structure containing host, port, certificates, project ID and device ID information.
#include "bytebeam_sdk.h"
static bytebeam_client_t bytebeam_client;
  • Next, we will do device provisioning in the same code. To do that declare your device config data like this
static const char* project_id = "your project id here";
static const char* device_id  = "your device id here";
static const char* broker_uri = "your broker end point here";
static const char* ca_cert     = "-----BEGIN CERTIFICATE-----**Your ca certificate here**-----END CERTIFICATE-----\n";
static const char* client_cert = "-----BEGIN CERTIFICATE-----**Your client certificate here**-----END CERTIFICATE-----\n";
static const char* client_key  = "-----BEGIN RSA PRIVATE KEY-----**Your client key here**-----END RSA PRIVATE KEY-----\n";
  • In app_main(), call syncTimeFromNtp() to sync time with NTP.
static void sync_time_from_ntp(void)
{
    time_t now = 0;
    struct tm timeinfo = {0};
    int retry = 0;
    const int retry_count = 10;

    initialize_sntp();

    // wait for time to be set
    while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) 
    {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }

    time(&now);
    localtime_r(&now, &timeinfo);
}
static void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");

    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);

#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
    sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
#endif

    sntp_init();
}
  • Next, fill your bytebeam_client structure with device config data
bytebeam_client.device_cfg.ca_cert_pem     = ca_cert;
bytebeam_client.device_cfg.client_cert_pem = client_cert;
bytebeam_client.device_cfg.client_key_pem  = client_key;
strcpy(bytebeam_client.device_cfg.project_id, project_id);
strcpy(bytebeam_client.device_cfg.broker_uri, broker_uri);
strcpy(bytebeam_client.device_cfg.device_id, device_id);
  • call bytebeam_init to initialise bytebeam_client. Then add an action handler to toggle led and then bytebeam_start to start the Bytebeam client.
// initialize the bytebeam client
bytebeam_init(&bytebeam_client);
// add the handler for toggle led action
bytebeam_add_action_handler(&bytebeam_client, handle_toggle_led, "toggle_led");
// start the bytebeam client
bytebeam_start(&bytebeam_client);
  • Add an action handler using the bytebeam_add_action_handler function. It contains the following arguments
    • bytebeam_client: reference to bytebeam client. this is a structure containing host, port, certificates and device id information
    • handle_toggle_led: handler function to update configurations
    • toggle_led: action name.

Creating an action handler to toggle led

In this section, we will create an action handler to parse action arguments and toggle the LED.

  • In the last section, we added a handle_toggle_led action handler function using bytebeam_add_action_handler.
  • handle_update_config contains the following arguments
    • bytebeam_client: reference to bytebeam client. this is a structure containing host, port, certificates and device id information
    • args: configuration JSON received for bytebeam cloud.
    • action_id: id of led_toggle action.
int handle_led_toggle(bytebeam_client_t *bytebeam_client, char *args, char *action_id) 
  • After this build your example to get the binary file
Idf.py build
  • Next press F1 in VS Code IDE to open Command Palette.
  • In the command palette type Wokwi: Start Simulator to open Wokwi simulator
>Wokwi:Start Simulator
  • Using this command you can access WokWi simulator

Adding action on bytebeam cloud

Next we will add an action button on bytebeam cloud console to toggle the led. We have already covered this part in our handling action guide. Refer to this Getting Started with Bytebeam- handling action [link] guide to proceed with adding action

Triggering an Action

We need to follow these easy steps to trigger an action:

  • Navigate to the Devices tab under Device Management
  • Click on the checkboxes to select the list of devices you want to trigger the Action
  • Click on the Action button you want to trigger. In our case, we have selected a device with #id 1 and triggered 'Toggle Led' Action.
  • In the Last Action column, you can see the Action status as Initiated and you can monitor the progress of the action from the progress bar
  • The Action will be sent to the selected Devices now. If the device is offline when the Action is triggered, the system will retry sending Actions to the device every 5s.
  • After successful execution of the action, the Action status will be charged to Completed.


Conclusion

Actions can be very handy in many use cases. Check out our other guides on Data visualization, OTA, Handling actions and Remote Debugging as well. I hope you find this guide useful.

We will come up with more interesting tutorials and maker content. Stay tuned.