Skip to content

Commit 71799df

Browse files
committed
feat: wokwi example app
1 parent bc63e6a commit 71799df

File tree

5 files changed

+261
-0
lines changed

5 files changed

+261
-0
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#include <time.h>
2+
#include <WiFi.h>
3+
#include <BytebeamArduino.h>
4+
#include "arduino_secrets.h"
5+
6+
// on board led pin number
7+
#define BOARD_LED 2
8+
9+
// led state variable
10+
int ledState = 0;
11+
12+
// wifi credentials
13+
const char* WIFI_SSID = SECRET_SSID;
14+
const char* WIFI_PASSWORD = SECRET_PASS;
15+
16+
// sntp credentials
17+
const long gmtOffset_sec = 19800; // GMT + 5:30h
18+
const int daylightOffset_sec = 0;
19+
const char* ntpServer = "pool.ntp.org";
20+
21+
// Replace this with your device config json in the same format
22+
char deviceConfigData[] = R"(
23+
{
24+
"project_id": "demo",
25+
"broker": "cloud.bytebeam.io",
26+
"port": 8883,
27+
"device_id": "1",
28+
"authentication": {
29+
"ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIFrDCCA5SgAwIBAgICBMwDQYJAwdzEOMAwGA1UBhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYcmUxFzAVBgNV\nBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIxMDkwMjExMDYyM1oXDTMxMDkwMjExMDYyM1owdzEOMAwG\nA1UEBhMFSW5kaWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCYW5nYWxv\ncmUxFzAVBgNVBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDAS\nBgNVBAoTC0J5dGViZWFtLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC\nAgEAr/bnOa/8AUGZmd/s+7rejuROgeLqqU9X15KKfKOBqcoMyXsSO65UEwpzadpw\nMl7GDCdHqFTymqdnAnbhgaT1PoIFhOG64y7UiNgiWmbh0XJj8G6oLrW9rQ1gug1Q\n/D7x2fUnza71aixiwEL+KsIFYIdDuzmoRD3rSer/bKOcGGs0WfB54KqIVVZ1DwsU\nk1wx5ExsKo7gAdXMAbdHRI2Szmn5MsZwGL6V0LfsKLE8ms2qlZe50oo2woLNN6XP\nRfRL4bwwkdsCqXWkkt4eUSNDq9hJsuINHdhO3GUieLsKLJGWJ0lq6si74t75rIKb\nvvsFEQ9mnAVS+iuUUsSjHPJIMnn/J64Nmgl/R/8FP5TUgUrHvHXKQkJ9h/a7+3tS\nlV2KMsFksXaFrGEByGIJ7yR4qu9hx5MXf8pf8EGEwOW/H3CdWcC2MvJ11PVpceUJ\neDVwE7B4gPM9Kx02RNwvUMH2FmYqkXX2DrrHQGQuq+6VRoN3rEdmGPqnONJEPeOw\nZzcGDVXKWZtd7UCbcZKdn0RYmVtI/OB5OW8IRoXFYgGB3IWP796dsXIwbJSqRb9m\nylICGOceQy3VR+8+BHkQLj5/ZKTe+AA3Ktk9UADvxRiWKGcejSA/LvyT8qzz0dqn\nGtcHYJuhJ/XpkHtB0PykB5WtxFjx3G/osbZfrNflcQZ9h1MCAwEAAaNCMEAwDgYD\nVR0PAQH/BAQDAgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKl/MTbLrZ0g\nurneOmAfBHO+LHz+MA0GCSqGSIb3DQEBCwUAA4ICAQAlus/uKic5sgo1d2hBJ0Ak\ns1XJsA2jz+OEdshQHmCCmzFir3IRSuVRmDBaBGlJDHCELqYxKn6dl/sKGwoqoAQ5\nOeR2sey3Nmdyw2k2JTDx58HnApZKAVir7BDxbIbbHmfhJk4ljeUBbertNXWbRHVr\ncs4XBNwXvX+noZjQzmXXK89YBsV2DCrGRAUeZ4hQEqV7XC0VKmlzEmfkr1nibDr5\nqwbI+7QWIAnkHggYi27lL2UTH7TvkwYC4TyDaoQ2ZRpG\nHY+mxXLdftoMv/ZvmyjOPYeTRQbfPqoRqcM6XOPXwSw9B6YddwmnkI7ohNOvAVfD\nwGptUc5OodgFQc3waRljX1q2lawZCTh58IUf32CRtOEL2RIz4VpUrNF/0E2vts1f\npO7V1vY2Qin998Nwqkxdsll0GLtEEE9hUyvk1F8U+fgjJ3Rjn4BxnCN4oCrdJOMa\nJCaysaHV7EEIMqrYP4jH6RzQzOXLd0m9NaL8A/Y9z2a96fwpZZU/fEEOH71t3Eo3\nV/CKlysiALMtsHfZDwHNpa6g0NQNGN5IRl/w1TS1izzjzgWhR6r8wX8OPLRzhNRz\n2HDbTXGYsem0ihC0B8uzujOhTHcBwsfxZUMpGjg8iycJlfpPDWBdw8qrGu8LeNux\na0cIevjvYAtVysoXInV0kg==\n-----END CERTIFICATE-----\n",
30+
"device_certificate": "-----BEGIN CERTIFICATE-----\nMIIEcjCCAlqgAwIBAgICB+MwhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIyMTEwMzA3NDcwMloXDTMyMTEKTEbMBkG\nA1UEChMSZXNwYnl0ZWJlYW1zZGt0ZXN0MQowCAYDVQQDEwExMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsm8CF8fKSzWFKZeO52RJRGER4z7sYrgTb9x\noIeljE8kmhR+EW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXa\nbI9manlqw0WqAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+s\nn6j5yEUnWKSIgoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY\n4X9UpdrjS5cRWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9\nplTq7I9/fDnkRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABo1YwVDAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU\nqX8xNsutnSC6ud46YB8Ec74sfP4wDAYDVR0RBAUwA4IBMTANBgkqhkiG9w0BAQsF\nAAOCAgEAcj5Ytt47AdmsXBsv/K7YkUvkNwV64luBMQtqmTKRDWnIQLaFzPjdpieu\n81ktFKklKw6pReWdUPSBy6hKq3zzGvSsShBSghbOAJvlPkK6jpLy5TzZdIj8ug7g\nMCzZvqdmznekSg4elGHJIYUfHD6ZUJaEkkGD1yQpxOIVCnodhN2246SXJK23itmz\nB5y1AHU5zydN7Ys0oY1l8RCc5Iz24IcQAi//2pIPe9ORks3QBBi+qY9m+emHCqgb\n48hNe5v7X+yF4VITlWs3Mfk0gSgbDQ4OwVf/8/D7o0hQ8EU5bzXNvf49Kd2mWTii\nQdQDdNLxZsdgWNwYdqrQhA0qN02yJxkhNm5GXmP75zmg0bPe4I+pNwuy+B32wFZn\nNcZrh4HZzS1cAyyyr3E59zsPjqcohaUcBpe6oUoQ8z1V7K9FR31TnFfvjg9mbDnX\nv2+PXsp0m7f4e1QfepZxUwyjemxOe/b+IEc7PckIrkPy46JaIvi9ONrTR8Y5wDir\nbGuzpmiyMFlyzK4ULh7kt7MU/jU/ulnqDU8JvAnhhxK3kgV4vv8LSYJSEYYP9i1S\nj/EPPQBANdtr4B2pcV1ig13dinq7rir6Q/pnkKrAFOfZcvOWW2BvPOC2dcnCYJpB\n1R5QJGXqna8Uh+ZwThs0K/Nd9dml1w/Rug8hx0VHoIe6AjXEepQ=\n-----END CERTIFICATE-----\n",
31+
"device_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAzsm8CF8fKSzWFKZeO52RJRmhR+\nEW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXabI9manlqw0Wq\nAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+sn6j5yEUnWKSI\ngoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY4X9UpdrjS5cR\nWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9plTq7I9/fDnk\nRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABAoIBAHv3A/ogzBVrA4ut\nkKA8fV6zeZFLOzfcAUuakQujReMvLsoPruPT2VUmuU1SRpNT7csmn7azmRW+4gny\nmO5meKDR382fz2DTIuKI0kByVvtNfmtBwAEdSiBpkzD7m3m1A8hg1wHw3sebolw6\njy3Zvxn5RASe3GKKsnKVLu8n5VXgyytn2I6sYOmKoLv3N9V3tziHL3Gl2AfWAd5P\nJHJdxZ50hhjzUnI0MmvUU6M9G26xagxNNibzOWv3BEuBRw5fuVpt/QoBouFhcKF7\nEdCFpiZ8LJFpux6FyLDOOAa7mj+Y6yK1qKsJbFGG8AnhPTO/bAc1m7yQcJygH9cl\nretVDcECgYEA4z+NkjqIPRiAvOsmJD6KfMeABkZc4JmART+KtrpoJmPWc2WDxu8M\ngP1eqmh/aGGORY8hcFyl+SIf5JvP13Dd/47tSK4vhyEGnnqRt+wjjuzci0rDvFdH\ntaUbjlb4kKStssQPTTmG726Zd1f32eKzBnCY8YqWdMMM1HXak20rPo8CgYEA6PN8\nYIcIrRkFzyvam8m5pCeoHylBgSNjN2j8dGC8b6SGMG6y4+rUiuxfhC/Oq7UtOvf+\njYQQgeMjB22dhcvJa6rjuuKXXpbcgNnzcemnySohUr7Nm1bXHwRfoqMAmeh3pkcL\nL+K4Mf6Gd1i2hiYd4Dd59m5/p3W+QUyKa4iaRP0CgYAf2/UZHyOijSDfW4hJZIs9\n2ypTtuGmi160Vqg33gJj/3M9UmobJcB3BQ6UjXnvRF4R2nMxsYuDVglqn32QEr7M\n6VjS67i2FSc8aKqtQmnpy8NPs/elHAdtq+wlFIRcovnHKj2K8hm8z6CsXqTc4y9+\nI6MNmgRl8kKGNs+iA5ggeQKBgBKLN25zsWQeJtE8G3XlVArWQVLhtN4z0/UYPWiC\nPt3gSfJXDZSJIAxDDsN2DsyqaoRUM4ZOagX878/qkOySsWEJxIEfAo+8EKeNMgzy\nXbHs0aRFnhZsjklgzsAim6ykzcmFxEU2lhUcvtWHUVhSdnRf1iyg1Taeb9vA3Q/8\nWtN9AoGBAN+rik+pvcdPAexngqmsUgoW8Abvv7dyBmt99KfnyRDfbt6EM68CZI90\naOlNE9P7XZyOyfQdzOlJWv8B78dwrbwMiwkhGtMjEzdW\nKFI0T+ZOXN99GcKLHeg5GfGqHcHlEhXP9BtRyTJVz914alvOIaiY\n-----END RSA PRIVATE KEY-----\n"
32+
}
33+
}
34+
)";
35+
36+
// function to setup the wifi with predefined credentials
37+
void setupWifi() {
38+
// set the wifi to station mode to connect to a access point
39+
WiFi.mode(WIFI_STA);
40+
WiFi.begin(WIFI_SSID , WIFI_PASSWORD);
41+
42+
Serial.println();
43+
Serial.print("Connecting to " + String(WIFI_SSID));
44+
45+
// wait till chip is being connected to wifi (Blocking Mode)
46+
while (WiFi.status() != WL_CONNECTED) {
47+
Serial.print(".");
48+
delay(250);
49+
}
50+
51+
// now it is connected to the access point just print the ip assigned to chip
52+
Serial.println();
53+
Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : ");
54+
Serial.println(WiFi.localIP());
55+
}
56+
57+
// function to sync time from ntp server with predefined credentials
58+
void syncTimeFromNtp() {
59+
// sync the time from ntp server
60+
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
61+
62+
struct tm timeinfo;
63+
64+
// get the current time
65+
if(!getLocalTime(&timeinfo)) {
66+
Serial.println("Failed to obtain time");
67+
return;
68+
}
69+
70+
// log the time info to serial :)
71+
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
72+
Serial.println();
73+
}
74+
75+
// function to setup the predefined led
76+
void setupLED() {
77+
pinMode(BOARD_LED, OUTPUT);
78+
digitalWrite(BOARD_LED, ledState);
79+
}
80+
81+
// function to toggle the predefined led
82+
void toggleLED() {
83+
ledState = !ledState;
84+
digitalWrite(BOARD_LED, ledState);
85+
}
86+
87+
// function to get the time
88+
unsigned long long getEpochMillis() {
89+
time_t now;
90+
struct tm timeinfo;
91+
92+
// get the current time i.e make sure the device is in sync with the ntp server
93+
if (!getLocalTime(&timeinfo)) {
94+
Serial.println("failed to obtain time");
95+
return 0;
96+
}
97+
98+
// get the epoch time
99+
time(&now);
100+
101+
// generate the epoch millis
102+
unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000);
103+
104+
return timeMillis;
105+
}
106+
107+
// function to publish payload to device shadow
108+
bool publishToDeviceShadow() {
109+
static int sequence = 0;
110+
unsigned long long milliseconds = 0;
111+
char ledStatus[200] = "";
112+
char deviceShadowStream[] = "device_shadow";
113+
114+
const char* payload = "";
115+
String deviceShadowStr = "";
116+
StaticJsonDocument<1024> doc;
117+
118+
// get the current epoch millis
119+
milliseconds = getEpochMillis();
120+
121+
// make sure you got the millis
122+
if(milliseconds == 0) {
123+
Serial.println("failed to get epoch millis");
124+
return false;
125+
}
126+
127+
// increment the sequence counter
128+
sequence++;
129+
130+
// generate the led status message string
131+
sprintf(ledStatus, "LED is %s !", ledState == true? "ON" : "OFF");
132+
133+
JsonArray deviceShadowJsonArray = doc.to<JsonArray>();
134+
JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject();
135+
136+
deviceShadowJsonObj_1["timestamp"] = milliseconds;
137+
deviceShadowJsonObj_1["sequence"] = sequence;
138+
deviceShadowJsonObj_1["Status"] = ledStatus;
139+
140+
serializeJson(deviceShadowJsonArray, deviceShadowStr);
141+
payload = deviceShadowStr.c_str();
142+
143+
Serial.printf("publishing %s to %s\n", payload, deviceShadowStream);
144+
145+
return Bytebeam.publishToStream(deviceShadowStream, payload);
146+
}
147+
148+
// handler for ToggleLED action
149+
int ToggleLED_Hanlder(char* args, char* actionId) {
150+
Serial.println("ToggleLED Action Received !");
151+
Serial.printf("<--- args : %s, actionId : %s --->\n", args, actionId);
152+
153+
// toggle the led
154+
toggleLED();
155+
156+
// publish led state to device shadow
157+
if(!publishToDeviceShadow()) {
158+
// publish action failed status
159+
if(!Bytebeam.publishActionFailed(actionId, "Publish led state to device shadow Failed")) {
160+
Serial.println("Failed to publish action failed response for Toggle LED action");
161+
}
162+
163+
Serial.println("Failed to publish led state to device shadow");
164+
return -1;
165+
}
166+
167+
// publish action completed status
168+
if(!Bytebeam.publishActionCompleted(actionId)) {
169+
Serial.println("Failed to publish action completed response for Toggle LED action");
170+
return -1;
171+
}
172+
173+
return 0;
174+
}
175+
176+
void setup() {
177+
// put your setup code here, to run once:
178+
Serial.begin(115200);
179+
Serial.println();
180+
181+
setupWifi();
182+
syncTimeFromNtp();
183+
184+
// setup the gpio led
185+
setupLED();
186+
187+
// setting up the device info i.e to be seen in the device shadow
188+
Bytebeam.status = "Device is Up!";
189+
Bytebeam.softwareType = "hello-wokwi-ino";
190+
Bytebeam.softwareVersion = "1.0.0";
191+
Bytebeam.hardwareType = "ESP32 Dev Module";
192+
Bytebeam.hardwareVersion = "rev1";
193+
194+
// begin the bytebeam client
195+
if(!Bytebeam.begin(deviceConfigData, BytebeamLogger::LOG_INFO)) {
196+
Serial.println("Bytebeam Client Initialization Failed.");
197+
} else {
198+
Serial.println("Bytebeam Client is Initialized Successfully.");
199+
}
200+
201+
// add the handler for toggle led action
202+
Bytebeam.addActionHandler(ToggleLED_Hanlder, "ToggleLED");
203+
}
204+
205+
void loop() {
206+
// put your main code here, to run repeatedly:
207+
208+
// bytebeam client loop
209+
Bytebeam.loop();
210+
211+
// hold on the execution for some time
212+
delay(5000);
213+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Bytebeam Hello Wokwi Example
2+
This example demonnstrates how to integrate Wokwi with Bytebeam IoT Platform.
3+
4+
## Hardware specification
5+
1. ESP32 Dev Board
6+
7+
## Software Specification
8+
1. Bytebeam Arduino Library
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//
2+
// Place all the sensitive data here
3+
//
4+
5+
#define SECRET_SSID "Wokwi-GUEST"
6+
#define SECRET_PASS ""
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"version": 1,
3+
"author": "Benny Meisels",
4+
"editor": "wokwi",
5+
"parts": [
6+
{ "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": 4.7, "left": -5, "attrs": {} },
7+
{
8+
"type": "wokwi-led",
9+
"id": "led-red",
10+
"top": 6,
11+
"left": 129,
12+
"attrs": { "color": "red", "flip": "1", "label": "WiFi" }
13+
},
14+
{
15+
"type": "wokwi-resistor",
16+
"id": "r1",
17+
"top": 86.2,
18+
"left": 104.4,
19+
"rotate": 90,
20+
"attrs": { "value": "1000" }
21+
}
22+
],
23+
"connections": [
24+
[ "esp:TX0", "$serialMonitor:RX", "", [] ],
25+
[ "esp:RX0", "$serialMonitor:TX", "", [] ],
26+
[ "esp:GND.1", "led-red:C", "black", [ "h66.9", "v-105.7" ] ],
27+
[ "led-red:A", "r1:1", "green", [ "h-9.6", "v19.2" ] ],
28+
[ "r1:2", "esp:D2", "green", [ "h0", "v8.4" ] ]
29+
]
30+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[wokwi]
2+
version = 1
3+
elf = "build/esp32.esp32.esp32/HelloWokwi.ino.elf"
4+
firmware = "build/esp32.esp32.esp32/HelloWokwi.ino.bin"

0 commit comments

Comments
 (0)