Skip to content

Commit

Permalink
Merge pull request #199 from hayschan/add-esp-idf-examples
Browse files Browse the repository at this point in the history
Create examples for ESP-IDF
  • Loading branch information
imbeacon committed Jun 7, 2024
2 parents 3647e80 + f760506 commit e159f13
Show file tree
Hide file tree
Showing 20 changed files with 1,330 additions and 0 deletions.
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

0 comments on commit e159f13

Please sign in to comment.