- Introduction
- Create device on ThingsBoard
- Install required libraries and tools
- Connect device to ThingsBoard
- Check data on ThingsBoard
- Synchronize device state using client and shared attribute requests
- Control device using shared attributes
- Control device using RPC
- Conclusion
Introduction
The WeMos D1 board, developed by WeMos company, is based on the ESP8266 ESP-12 WiFi module.
Board programming is carried out using the standard Arduino IDE development environment.
The controller includes a processor, peripherals, RAM and input/output devices.
Most often, microcontrollers are used in computer equipment, household appliances and other electronic devices.
WeMos is distinguished by its low cost and ease of connection and programming.
In this guide, we will learn how to create device on Thingsboard, install required libraries and tools.
After this we will modify our code and upload it to the device, and check the results of our coding and check data on ThingsBoard using imported dashboard.
Our device will synchronize with ThingsBoard using client and shared attributes requests functionality.
Of course, we will control our device using provided functionality like shared attributes or RPC requests.
Prerequisites
To continue with this guide we will need the following:
- WeMos D1 R2
- ThingsBoard account
Create device on ThingsBoard
For simplicity, we will provide the device manually using the UI.
-
Login to your ThingsBoard instance and navigate to the “Entities”. Then click the “Devices” page.
-
Click on the “+” icon in the top right corner of the table and then select “Add new device”.
-
Input device name. For example, “My Device”. No other changes required at this time. Click “Add” to add the device.
-
Your device has been added.
![Login to your ThingsBoard instance and navigate to the "Entities". Then click the "Devices" page.](https://img.thingsboard.io/helloworld/getting-started-ce/hello-world-1-1-provision-device-1-ce-preview.png)
Login to your ThingsBoard instance and navigate to the “Entities”. Then click the “Devices” page.
![Click on the "+" icon in the top right corner of the table and then select "Add new device".](https://img.thingsboard.io/helloworld/getting-started-ce/hello-world-1-1-provision-device-2-ce-preview.png)
Click on the “+” icon in the top right corner of the table and then select “Add new device”.
![Input device name. For example, "My Device". No other changes required at this time. Click "Add" to add the device.](https://img.thingsboard.io/helloworld/getting-started-ce/hello-world-1-1-provision-device-3-ce-preview.png)
Input device name. For example, “My Device”. No other changes required at this time. Click “Add” to add the device.
![Your device has been added.](https://img.thingsboard.io/helloworld/getting-started-ce/hello-world-1-1-provision-device-4-ce-preview.png)
Your device has been added.
Install required libraries and tools
Install the board for Arduino IDE:
Go to File > Preferences and add the following URL to the Additional Boards Manager URLs field.
1
http://arduino.esp8266.com/stable/package_esp8266com_index.json
Next, go to Tools > Board > Board Manager and install the ESP8266 board.
-
Put ESP8266 into search field and install esp8266 by Espressif Community.
After the installation is complete, select the board by Board menu: Tools > Board > ESP8266 > LOLIN(WEMOS) D1 R2 & mini.
Connect the device to computer using USB cable and select the port for the device: Tools > Port > /dev/ttyUSB0.
Port depends on operation system and may be different:
- for Linux it will be /dev/ttyUSBX
- for MacOS it will be usb.serialX.. or usb.modemX..
- for Windows - COMX.
To install ThingsBoard Arduino SDK - we will need to do the following steps:
-
Go to “Tools” tab and click on “Manage libraries”.
-
Put “ThingsBoard” into the search box and press “INSTALL” button for the found library.
![Go to "Tools" tab and click on "Manage libraries".](https://img.thingsboard.io/devices-library/basic/arduino-ide/tools-manage-libraries-preview.png)
Go to “Tools” tab and click on “Manage libraries”.
![Put "ThingsBoard" into the search box and press "INSTALL" button for the found library.](https://img.thingsboard.io/devices-library/basic/arduino-ide/manage-libraries-thingsboard-preview.png)
Put “ThingsBoard” into the search box and press “INSTALL” button for the found library.
Also, for boards, based on ESP8266 chip we should install the “mbedtls” library.
-
Put into library search field “mbedtls” and install the library - “Seeed_Arduino_mbedtls by Peter Yang”
![Put into library search field "mbedtls" and install the library - "Seeed_Arduino_mbedtls by Peter Yang"](https://img.thingsboard.io/devices-library/basic/arduino-ide/install-mbedtls-preview.png)
Put into library search field “mbedtls” and install the library - “Seeed_Arduino_mbedtls by Peter Yang”
At this point, we have installed all required libraries and tools.
Connect device to ThingsBoard
To connect your device, you’ll first need to get its credentials. While ThingsBoard supports a variety of device credentials, for this guide, we will use the default auto-generated credentials, which is an access token.
-
Click on the device row in the table to open device details.
-
Click “Copy access token”. The token will be copied to your clipboard. Please save it in a safe place.
![Click on the device row in the table to open device details.](https://img.thingsboard.io/helloworld/getting-started-ce/hello-world-2-1-connect-device-1-ce-preview.png)
Click on the device row in the table to open device details.
![Click "Copy access token". The token will be copied to your clipboard. Please save it in a safe place.](https://img.thingsboard.io/helloworld/getting-started-ce/hello-world-2-1-connect-device-2-ce-preview.png)
Click “Copy access token”. The token will be copied to your clipboard. Please save it in a safe place.
Now it’s time to program the board to connect to ThingsBoard.
To do this, you can use the code below. It contains all required functionality for this guide.
Necessary variables for connection:
Variable name | Default value | Description |
---|---|---|
WIFI_SSID | YOUR_WIFI_SSID | Your WiFi network name. |
WIFI_PASSWORD | YOUR_WIFI_PASSWORD | Your WiFi network password. |
TOKEN | YOUR_DEVICE_ACCESS_TOKEN | Access token from device. Obtaining process described in #connect-device-to-thingsboard |
THINGSBOARD_SERVER | demo.thingsboard.io | Your ThingsBoard host or ip address. |
THINGSBOARD_PORT | 1883U | ThingsBoard server MQTT port. Can be default for this guide. |
MAX_MESSAGE_SIZE | 256U | Maximal size of MQTT messages. Can be default for this guide. |
SERIAL_DEBUG_BAUD | 1883U | Baud rate for serial port. Can be default for this guide. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
constexpr char WIFI_SSID[] = "YOUR_WIFI_SSID";
constexpr char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
constexpr char TOKEN[] = "YOUR_ACCESS_TOKEN";
constexpr char THINGSBOARD_SERVER[] = "demo.thingsboard.io";
constexpr uint16_t THINGSBOARD_PORT = 1883U;
constexpr uint32_t MAX_MESSAGE_SIZE = 256U;
constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;
...
Send data part (By default the example sends random value for temperature key and some WiFi information):
1
2
3
4
5
6
7
8
...
tb.sendTelemetryData("temperature", random(10, 20));
tb.sendAttributeData("rssi", WiFi.RSSI());
tb.sendAttributeData("bssid", WiFi.BSSIDstr().c_str());
tb.sendAttributeData("localIp", WiFi.localIP().toString().c_str());
tb.sendAttributeData("ssid", WiFi.SSID().c_str());
tb.sendAttributeData("channel", WiFi.channel());
...
Then upload the code to the device by pressing Upload button or keyboard combination Ctrl+U.
If you cannot upload the code and receive an error: Property 'upload.tool.serial' is undefined
you can do the following:
-
Go to “Tools” > “Programmer” and select “Esptool” as a programmer.
-
Go to “Sketch” > “Upload Using Programmer”.
![Go to "Tools" > "Programmer" and select "Esptool" as a programmer.](https://img.thingsboard.io/devices-library/basic/arduino-ide/select-esptool-programmer-preview.png)
Go to “Tools” > “Programmer” and select “Esptool” as a programmer.
![Go to "Sketch" > "Upload Using Programmer".](https://img.thingsboard.io/devices-library/basic/arduino-ide/upload-using-programmer-preview.png)
Go to “Sketch” > “Upload Using Programmer”.
Check data on ThingsBoard
ThingsBoard provides the ability to create and customize interactive visualizations (dashboards) for monitoring and managing data and devices.
Through ThingsBoard dashboards, you can efficiently manage and monitor your IoT devices and data. So, we will create the dashboard, for our device.
To add the dashboard to ThingsBoard, we need to import it. To import a dashboard, follow these steps:
- First download the Check and control device data dashboard file.
-
Navigate to the “Dashboards” page and click the “+” button in the upper right corner of the page and select “Import dashboard”.
-
In the dashboard import window, upload the JSON file and click “Import” button.
-
Dashboard has been imported.
![Navigate to the "Dashboards" page and click the "+" button in the upper right corner of the page and select "Import dashboard".](https://img.thingsboard.io/user-guide/dashboards/managing-dashboard/import-dashboard-1-ce-preview.png)
Navigate to the “Dashboards” page and click the “+” button in the upper right corner of the page and select “Import dashboard”.
![In the dashboard import window, upload the JSON file and click "Import" button.](https://img.thingsboard.io/user-guide/dashboards/managing-dashboard/import-dashboard-2-ce-preview.png)
In the dashboard import window, upload the JSON file and click “Import” button.
![Dashboard has been imported.](https://img.thingsboard.io/user-guide/dashboards/managing-dashboard/import-dashboard-3-ce-preview.png)
Dashboard has been imported.
The Check and control device data dashboard structure:
-
To check the data from our device we need to open the imported dashboard by clicking on it in the table.
-
The view of checking data and controlling our device dashboard.
-
Received attributes from device.
-
Device information from the ThingsBoard server.
-
Widget to see the history of LED mode changes.
-
Widget to see the history of our emulated temperature.
![To check the data from our device we need to open the imported dashboard by clicking on it in the table.](https://img.thingsboard.io/devices-library/paas/thingsboard-open-dashboard-click-on-row-preview.png)
To check the data from our device we need to open the imported dashboard by clicking on it in the table.
![The view of checking data and controlling our device dashboard.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-general-view-of-example-dashboard-preview.png)
The view of checking data and controlling our device dashboard.
![Received attributes from device.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-device-attributes-preview.png)
Received attributes from device.
![Device information from the ThingsBoard server.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-device-info-preview.png)
Device information from the ThingsBoard server.
![Widget to see the history of LED mode changes.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-led-mode-history-preview.png)
Widget to see the history of LED mode changes.
![Widget to see the history of our emulated temperature.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-temperature-history-preview.png)
Widget to see the history of our emulated temperature.
Synchronize device state using client and shared attribute requests
In order to get the state of the device from ThingsBoard during booting we have functionality to do this in the code.
Below are the relevant parts of the code example:
- Attribute callbacks:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
void processSharedAttributes(const JsonObjectConst &data) {
for (auto it = data.begin(); it != data.end(); ++it) {
if (strcmp(it->key().c_str(), BLINKING_INTERVAL_ATTR) == 0) {
const uint16_t new_interval = it->value().as<uint16_t>();
if (new_interval >= BLINKING_INTERVAL_MS_MIN && new_interval <= BLINKING_INTERVAL_MS_MAX) {
blinkingInterval = new_interval;
Serial.print("Updated blinking interval to: ");
Serial.println(new_interval);
}
} else if(strcmp(it->key().c_str(), LED_STATE_ATTR) == 0) {
ledState = it->value().as<bool>();
digitalWrite(LED_BUILTIN, ledState ? HIGH : LOW);
Serial.print("Updated state to: ");
Serial.println(ledState);
}
}
attributesChanged = true;
}
void processClientAttributes(const JsonObjectConst &data) {
for (auto it = data.begin(); it != data.end(); ++it) {
if (strcmp(it->key().c_str(), LED_MODE_ATTR) == 0) {
const uint16_t new_mode = it->value().as<uint16_t>();
ledMode = new_mode;
}
}
}
...
const Attribute_Request_Callback<MAX_ATTRIBUTES> attribute_shared_request_callback(SHARED_ATTRIBUTES_LIST.cbegin(), SHARED_ATTRIBUTES_LIST.cend(), &processSharedAttributes);
const Attribute_Request_Callback<MAX_ATTRIBUTES> attribute_client_request_callback(CLIENT_ATTRIBUTES_LIST.cbegin(), CLIENT_ATTRIBUTES_LIST.cend(), &processClientAttributes);
...
We have two callbacks:
- Shared Attributes Callback: This callback is specific to shared attributes. Its primary function is to receive a response containing the blinking interval, which determines the appropriate blinking period.;
- Client Attributes Callback: This callback is specific to client attributes. It receives information regarding the mode and state of the LED. Once this data is received, the system saves and sets these parameters.
This functionality allows us to keep the actual state after rebooting.
- Attribute requests:
1 2 3 4 5 6 7 8 9 10 11 12 13
... // Request current states of shared attributes if (!tb.Shared_Attributes_Request(attribute_shared_request_callback)) { Serial.println("Failed to request for shared attributes"); return; } // Request current states of client attributes if (!tb.Client_Attributes_Request(attribute_client_request_callback)) { Serial.println("Failed to request for client attributes"); return; } ...
In order for our callbacks to receive the data, we have to send a request to ThingsBoard.
Control device using shared attributes
Also we can change the period of the blinking using shared attribute update functionality.
-
To change period of the blinking we just need to change the value on our dashboard.
-
After applying by pressing check mark you will see a confirmation message.
![To change period of the blinking we just need to change the value on our dashboard.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-change-blinking-mode-1-preview.png)
To change period of the blinking we just need to change the value on our dashboard.
![After applying by pressing check mark you will see a confirmation message.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-blinking-interval-change-preview.png)
After applying by pressing check mark you will see a confirmation message.
In order to change state when blinking is disabled - we can use the switch in the same widget:
-
It can be done only when the blinking mode is disabled.
To reach this, we have a variable “blinkingInterval” used in the following parts of the code:
- Callback for shared attributes update:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
void processSharedAttributes(const JsonObjectConst &data) {
for (auto it = data.begin(); it != data.end(); ++it) {
if (strcmp(it->key().c_str(), BLINKING_INTERVAL_ATTR) == 0) {
const uint16_t new_interval = it->value().as<uint16_t>();
if (new_interval >= BLINKING_INTERVAL_MS_MIN && new_interval <= BLINKING_INTERVAL_MS_MAX) {
blinkingInterval = new_interval;
Serial.print("Updated blinking interval to: ");
Serial.println(new_interval);
}
} else if(strcmp(it->key().c_str(), LED_STATE_ATTR) == 0) {
ledState = it->value().as<bool>();
digitalWrite(LED_BUILTIN, ledState ? HIGH : LOW);
Serial.print("Updated state to: ");
Serial.println(ledState);
}
}
attributesChanged = true;
}
...
const Shared_Attribute_Callback<MAX_ATTRIBUTES> attributes_callback(SHARED_ATTRIBUTES_LIST.cbegin(), SHARED_ATTRIBUTES_LIST.cend(), &processSharedAttributes);
...
- Subscribing for shared attributes update:
1
2
3
4
5
6
...
if (!tb.Shared_Attributes_Request(attribute_shared_request_callback)) {
Serial.println("Failed to request for shared attributes");
return;
}
...
- Part of code to blink:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
if (ledMode == 1 && millis() - previousStateChange > blinkingInterval) {
previousStateChange = millis();
ledState = !ledState;
digitalWrite(LED_BUILTIN, ledState);
tb.sendTelemetryData(LED_STATE_ATTR, ledState);
tb.sendAttributeData(LED_STATE_ATTR, ledState);
if (LED_BUILTIN == 99) {
Serial.print("LED state changed to: ");
Serial.println(ledState);
}
}
...
You can change the logic to reach your goals and add processing for your attributes.
Control device using RPC
You can manually change state of the LED and change mode between continuous lightning and blinking. To do this, you can use the following parts of our dashboard:
-
Change LED state using switch widget to continuous lightning.
-
Change LED state using round switch widget to blinking mode.
![Change LED state using switch widget to continuous lightning.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-change-blinking-mode-0-preview.png)
Change LED state using switch widget to continuous lightning.
![Change LED state using round switch widget to blinking mode.](https://img.thingsboard.io/devices-library/basic/microcontrollers/dashboard/thingsboard-example-dashboard-change-blinking-mode-1-preview.png)
Change LED state using round switch widget to blinking mode.
Please note that you can change the LED state only if blinking mode is disabled.
In the code example we have functionality to handle RPC commands.
To get ability to control the device we have used the following parts of the code:
- Callback for RPC requests:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
void processSetLedMode(const JsonVariantConst &data, JsonDocument &response) {
Serial.println("Received the set led state RPC method");
// Process data
int new_mode = data;
Serial.print("Mode to change: ");
Serial.println(new_mode);
StaticJsonDocument<1> response_doc;
if (new_mode != 0 && new_mode != 1) {
response_doc["error"] = "Unknown mode!";
response.set(response_doc);
return;
}
ledMode = new_mode;
attributesChanged = true;
response_doc["newMode"] = (int)ledMode;
// Returning current mode
response.set(response_doc);
}
...
const std::array<RPC_Callback, 1U> callbacks = {
RPC_Callback{ "setLedMode", processSetLedMode }
};
...
- Subscribing for RPC requests:
1
2
3
4
5
6
...
if (!tb.RPC_Subscribe(callbacks.cbegin(), callbacks.cend())) {
Serial.println("Failed to subscribe for RPC");
return;
}
...
You can change the code to reach your goals and add processing for your RPC commands.
Conclusion
With the knowledge outlined in this guide, you can easily connect your WeMos D1 R2 and send data to ThingsBoard.
Explore the platform documentation to learn more about key concepts and features. For example, configure alarm rules or dashboards.