Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create examples for ESP-IDF #199

Merged
merged 5 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions examples/0016-espressif_esp32_rpc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Prerequisites
*.d

# Object files
*.o
*.ko
*.obj
*.elf

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

.config
*.o
*.pyc

# gtags
GTAGS
GRTAGS
GPATH

# emacs
.dir-locals.el

# emacs temp file suffixes
*~
.#*
\#*#

# eclipse setting
.settings

# MacOS directory files
.DS_Store

# cache dir
.cache/

# Components Unit Test Apps files
components/**/build/
components/**/build_*_*/
components/**/sdkconfig
components/**/sdkconfig.old

# Example project files
examples/**/build/
examples/**/build_esp*_*/
examples/**/sdkconfig
examples/**/sdkconfig.old

# Doc build artifacts
docs/_build/
docs/doxygen_sqlite3.db

# Downloaded font files
docs/_static/DejaVuSans.ttf
docs/_static/NotoSansSC-Regular.otf

# sdkconfig
sdkconfig.old
sdkconfig

# Unit test app files
tools/unit-test-app/sdkconfig
tools/unit-test-app/sdkconfig.old
tools/unit-test-app/build
tools/unit-test-app/build_*_*/
tools/unit-test-app/output
tools/unit-test-app/test_configs

# Unit Test CMake compile log folder
log_ut_cmake

# test application build files
tools/test_apps/**/build/
tools/test_apps/**/build_*_*/
tools/test_apps/**/sdkconfig
tools/test_apps/**/sdkconfig.old

TEST_LOGS

# gcov coverage reports
*.gcda
*.gcno
coverage.info
coverage_report/

test_multi_heap_host

# VS Code Settings
.vscode/

# VIM files
*.swp
*.swo

# Clion IDE CMake build & config
.idea/
cmake-build-*/

# Results for the checking of the Python coding style and static analysis
.mypy_cache
flake8_output.txt

# ESP-IDF default build directory name
build

# lock files for examples and components
dependencies.lock

# managed_components for examples
managed_components

# pytest log
pytest_embedded_log/

# Squareline Studio
SquarelineStudio/SquarelineStudio_Project/backup/
SquarelineStudio/SquarelineStudio_Project/autosave/
SquarelineStudio/SquarelineStudio_Project/cache/
SquarelineStudio/SquarelineStudio_Project/export/
9 changes: 9 additions & 0 deletions examples/0016-espressif_esp32_rpc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
cmake_minimum_required(VERSION 3.5)

# Set project version
set(PROJECT_VER "0.1.1")

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ESP32_RPC)
17 changes: 17 additions & 0 deletions examples/0016-espressif_esp32_rpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Sending telemetry / attribute data

## Devices
| Supported Devices |
|-------------------|
| ESP32 |

## Framework

Espressif IDF

## ThingsBoard API
[Server-side Remote Procedure Call](https://thingsboard.io/docs/user-guide/rpc/#server-side-rpc)

## Feature
Creating RPC methods that can be called from the cloud and will result in us receiving a message,
that then calls the corresponding callback on the device, which can optionally return a response that includes certain values
165 changes: 165 additions & 0 deletions examples/0016-espressif_esp32_rpc/main/0016-espressif_esp32_rpc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include <esp_netif.h>
#include <esp_log.h>
#include <esp_wifi.h>
#include <nvs_flash.h>
#include <string.h>

// Whether the given script is using encryption or not,
// generally recommended as it increases security (communication with the server is not in clear text anymore),
// it does come with an overhead tough as having an encrypted session requires a lot of memory,
// which might not be avaialable on lower end devices.
#define ENCRYPTED false

#include <Espressif_MQTT_Client.h>
#include <ThingsBoard.h>

// Examples using arduino used PROGMEM to save constants into flash memory,
// this is not needed when using Espressif IDF because per default
// all read only variables will be saved into DROM (flash memory).
// See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/memory-types.html#drom-data-stored-in-flash
// for more information about the aforementioned feature
constexpr char WIFI_SSID[] = "YOUR_WIFI_SSID";
constexpr char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
constexpr char TOKEN[] = "YOUR_DEVICE_ACCESS_TOKEN";

// Thingsboard we want to establish a connection to
constexpr char THINGSBOARD_SERVER[] = "demo.thingsboard.io";

// MQTT port used to communicate with the server, 1883 is the default unencrypted MQTT port,
// whereas 8883 would be the default encrypted SSL MQTT port
#if ENCRYPTED
constexpr uint16_t THINGSBOARD_PORT = 8883U;
#else
constexpr uint16_t THINGSBOARD_PORT = 1883U;
#endif

// Maximum size packets will ever be sent or received by the underlying MQTT client,
// if the size is to small messages might not be sent or received messages will be discarded
constexpr uint16_t MAX_MESSAGE_SIZE = 256U;

#if ENCRYPTED
// See https://comodosslstore.com/resources/what-is-a-root-ca-certificate-and-how-do-i-download-it/
// on how to get the root certificate of the server we want to communicate with,
// this is needed to establish a secure connection and changes depending on the website.
constexpr char ROOT_CERT[] = R"(-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)";
#endif

constexpr char RPC_TEMPERATURE_METHOD[] = "example_set_temperature";
constexpr char RPC_SWITCH_METHOD[] = "example_set_switch";
constexpr char RPC_TEMPERATURE_KEY[] = "temp";
constexpr char RPC_SWITCH_KEY[] = "switch";
constexpr char RPC_RESPONSE_KEY[] = "example_response";

// Initalize the Mqtt client instance
Espressif_MQTT_Client mqttClient;
// Initialize ThingsBoard instance with the maximum needed buffer size
ThingsBoard tb(mqttClient, MAX_MESSAGE_SIZE);

// Statuses for subscribing to rpc
bool subscribed = false;


static void on_got_ip(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {
ESP_LOGI("RPC Example", "Got IP");
}

void InitWiFi() {
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());

esp_netif_create_default_wifi_sta();

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));

wifi_config_t wifi_config = {};
strcpy((char*)wifi_config.sta.ssid, WIFI_SSID);
strcpy((char*)wifi_config.sta.password, WIFI_PASSWORD);

ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_connect());
}

RPC_Response processTemperatureChange(const RPC_Data &data) {
float example_temperature = data[RPC_TEMPERATURE_KEY];
ESP_LOGI("RPC Example", "Received the set temperature RPC method: %f", example_temperature);

StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
doc[RPC_RESPONSE_KEY] = 42;
return RPC_Response(doc);
}

RPC_Response processSwitchChange(const RPC_Data &data) {
bool switch_state = data[RPC_SWITCH_KEY];
ESP_LOGI("RPC Example", "Received the set switch method: %d", switch_state);

StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
doc[RPC_RESPONSE_KEY] = 22.02;
return RPC_Response(doc);
}

extern "C" void app_main(void) {
InitWiFi();

const std::array<RPC_Callback, 2U> callbacks = {
RPC_Callback{RPC_TEMPERATURE_METHOD, processTemperatureChange},
RPC_Callback{RPC_SWITCH_METHOD, processSwitchChange}
};

while (true) {
if (!tb.connected()) {
ESP_LOGI("RPC Example", "Connecting to: %s with token %s", THINGSBOARD_SERVER, TOKEN);
if (tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT)) {
ESP_LOGI("RPC Example", "Successfully connected");
if (!subscribed && tb.RPC_Subscribe(callbacks.begin(), callbacks.end())) {
ESP_LOGI("RPC Example", "Subscribed to RPC commands");
subscribed = true;
}
} else {
ESP_LOGE("RPC Example", "Failed to connect");
}
}

tb.loop();
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
29 changes: 29 additions & 0 deletions examples/0016-espressif_esp32_rpc/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Be aware this file should not be takes as inspiration on how to set up compilation with the CMake build system when using ESP-IDF, because it directly includes the implementation files.
# This has to be done because the examples are build to test if they are still working and to automatically inform the library if a pull request would break examples.
# To actually include the library in your ESP-IDF project read the documentation especially the Installation section
set(srcs
0016-espressif_esp32_rpc.cpp
../../../src/Arduino_HTTP_Client.cpp
../../../src/Arduino_MQTT_Client.cpp
../../../src/Attribute_Request_Callback.cpp
../../../src/Callback_Watchdog.cpp
../../../src/Arduino_ESP32_Updater.cpp
../../../src/Arduino_ESP8266_Updater.cpp
../../../src/Espressif_Updater.cpp
../../../src/Espressif_MQTT_Client.cpp
../../../src/HashGenerator.cpp
../../../src/Helper.cpp
../../../src/OTA_Update_Callback.cpp
../../../src/Provision_Callback.cpp
../../../src/RPC_Callback.cpp
../../../src/RPC_Request_Callback.cpp
../../../src/RPC_Response.cpp
../../../src/Shared_Attribute_Callback.cpp
../../../src/Telemetry.cpp
../../../src/ThingsBoardDefaultLogger.cpp
)

idf_component_register(
SRCS ${srcs}
INCLUDE_DIRS "../../../src"
)
5 changes: 5 additions & 0 deletions examples/0016-espressif_esp32_rpc/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Be aware this file should not be takes as inspiration on how to set up compilation with the CMake build system when using ESP-IDF, because it directly includes the needed libraries for the implementation.
# This has to be done because the examples are build to test if they are still working and to automatically inform the library if a pull request would break examples.
# To actually include the library in your ESP-IDF project read the documentation especially the Installation section
dependencies:
bblanchon/arduinojson: "^6.21.2"
Loading