Skip to content

Commit 14a5906

Browse files
committed
Release v1.0.0
1 parent 8d2253a commit 14a5906

26 files changed

Lines changed: 554 additions & 217 deletions

LICENSE

Lines changed: 82 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,87 @@
1+
Apache License
2+
Version 2.0, January 2004
3+
http://www.apache.org/licenses/
14

2-
The MIT License (MIT)
5+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
36

4-
Copyright (c) Blynk Technologies Inc
7+
1. Definitions.
58

6-
Permission is hereby granted, free of charge, to any person obtaining a copy
7-
of this software and associated documentation files (the "Software"), to deal
8-
in the Software without restriction, including without limitation the rights
9-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10-
copies of the Software, and to permit persons to whom the Software is
11-
furnished to do so, subject to the following conditions:
9+
"License" shall mean the terms and conditions for use, reproduction,
10+
and distribution as defined by Sections 1 through 9 of this document.
1211

13-
The above copyright notice and this permission notice shall be included in all
14-
copies or substantial portions of the Software.
12+
"Licensor" shall mean the copyright owner or entity authorized by
13+
the copyright owner that is granting the License.
1514

16-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22-
SOFTWARE.
15+
"Legal Entity" shall mean the union of the acting entity and all
16+
other entities that control, are controlled by, or are under common
17+
control with that entity.
18+
19+
"You" (or "Your") shall mean an individual or Legal Entity exercising
20+
permissions granted by this License.
21+
22+
"Source" form shall mean the preferred form for making modifications.
23+
24+
"Object" form shall mean any form resulting from mechanical transformation.
25+
26+
"Work" shall mean the work of authorship, whether in Source or Object form.
27+
28+
"Derivative Works" shall mean any work based on the Work.
29+
30+
"Contribution" shall mean any work of authorship intentionally submitted.
31+
32+
"Contributor" shall mean Licensor and any individual or Legal Entity
33+
on behalf of whom a Contribution has been received.
34+
35+
2. Grant of Copyright License.
36+
37+
Subject to the terms and conditions of this License, each Contributor
38+
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
39+
royalty-free, irrevocable copyright license to reproduce, prepare
40+
Derivative Works of, publicly display, publicly perform, sublicense,
41+
and distribute the Work and such Derivative Works in Source or Object form.
42+
43+
3. Grant of Patent License.
44+
45+
Each Contributor hereby grants to You a perpetual, worldwide,
46+
non-exclusive, no-charge, royalty-free, irrevocable patent license
47+
to make, have made, use, offer to sell, sell, import, and otherwise
48+
transfer the Work.
49+
50+
4. Redistribution.
51+
52+
You may reproduce and distribute copies of the Work or Derivative Works
53+
thereof in any medium, with or without modifications, provided that You
54+
meet the following conditions:
55+
56+
(a) You must give any other recipients of the Work a copy of this License;
57+
58+
(b) You must cause any modified files to carry prominent notices;
59+
60+
(c) You must retain all copyright, patent, trademark, and attribution notices;
61+
62+
(d) If the Work includes a "NOTICE" file, you must include it.
63+
64+
5. Submission of Contributions.
65+
66+
Unless You explicitly state otherwise, any Contribution intentionally
67+
submitted shall be under the terms of this License.
68+
69+
6. Trademarks.
70+
71+
This License does not grant permission to use trade names, trademarks,
72+
or product names of the Licensor.
73+
74+
7. Disclaimer of Warranty.
75+
76+
Unless required by applicable law, the Work is provided "AS IS",
77+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
78+
79+
8. Limitation of Liability.
80+
81+
In no event shall any Contributor be liable for any damages.
82+
83+
9. Accepting Warranty or Additional Liability.
84+
85+
You may choose to offer support or warranty, but only on Your own behalf.
86+
87+
END OF TERMS AND CONDITIONS

README.md

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ and take advantage of all its advanced features without the need for extensive c
2424
Supported targets:
2525
```
2626
✅ ESP32, ESP32-S3, ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6
27-
⏳ ESP32-S2 - *(soon)*
27+
⏳ ESP32-S2 - soon
2828
❌ ESP32-P4, ESP32-H4
2929
```
3030

@@ -39,7 +39,7 @@ Supported targets:
3939
Configure the target chip, eg `idf.py set-target esp32`.
4040

4141
Configure component using `idf.py menuconfig`:
42-
```
42+
```txt
4343
(Top) → Component config → Blynk.Edgent
4444
```
4545

@@ -62,18 +62,17 @@ The device should appear `online` once the above steps complete successfully.
6262
See the device log via `idf.py monitor`:
6363

6464
```log
65-
I (326) example: app_main() started
66-
I (326) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
67-
I (326) button: IoT Button Version: 4.1.3
68-
I (346) nm_eth.c: Ethernet initialized with 0 port(s)
69-
I (346) edgent.c: Blynk.Edgent initialized (device: Blynk Blinking LED-N945)
70-
I (356) edgent.c: State transition: IDLE => CONNECTING_NET
71-
I (356) example: Received on_state_change
72-
I (1506) edgent.c: State transition: CONNECTING_NET => CONNECTING_CLOUD
73-
I (1506) example: Received on_state_change
74-
I (2626) edgent.c: State transition: CONNECTING_CLOUD => RUNNING
75-
I (2626) example: Received on_state_change
76-
I (2626) example: Received on_initial_connection
65+
I (771) edgent.c: Blynk.Edgent initialized (device: Blynk Demo-N1A9)
66+
I (771) edgent.c: State: IDLE => CONNECTING_NET
67+
I (771) example: State change event received
68+
I (851) nm_wifi.c: Connecting to SSID:wifi BSSID 2c:c8:1b:xx:xx:xx CH:11
69+
I (851) example: Awaiting Cloud connection...
70+
I (1931) edgent.c: State: CONNECTING_NET => CONNECTING_CLOUD
71+
I (1931) example: State change event received
72+
I (2981) edgent.c: State: CONNECTING_CLOUD => RUNNING
73+
I (2981) example: State change event received
74+
I (2981) example: Initial connection established
75+
I (2991) example: [main] Cloud connected event received! Continuing...
7776
```
7877

7978
</details>
@@ -95,19 +94,18 @@ The example application also handles the on-board button:
9594
idf.py add-dependency "blynk/edgent^1.0.0"
9695
```
9796

98-
If your project uses **Minimal Build**, consider disabling it, or add build dependencies explicitly:
97+
If your project uses [`MINIMAL_BUILD`](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/build-system.html#cmake-build-properties), consider disabling it, or add build dependencies explicitly:
9998
```
10099
esp_event esp_netif esp_wifi esp_https_ota
101-
esp_partition efuse nvs_flash mqtt json bt
102-
esp_eth
100+
esp_partition efuse nvs_flash mqtt json bt esp_eth
103101
```
104102

105103
## OTA configuration
106104

107105
Minimum flash size requirement for OTA updates is `4MB`.
108106

109107
You should select a dual-bank partition table, for example:
110-
```
108+
```txt
111109
(Top) → Partition Table → Partition Table → Two large size OTA partitions
112110
```
113111

@@ -128,6 +126,7 @@ To enable Ethernet:
128126
<!--
129127
- [Cookbook](_extra/Cookbook.md)
130128
-->
129+
131130
- [Blynk.Edgent](https://docs.blynk.io/en/blynk.edgent/overview)
132131
- [Blynk IoT Apps][blynk-apps]
133132
- [Deploying Products With Dynamic AuthTokens](https://docs.blynk.io/en/commercial-use/deploying-products-with-dynamic-authtokens)

examples/basic/main/main.cpp

Lines changed: 84 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@
99
#include <string.h>
1010
#include <esp_log.h>
1111
#include <esp_system.h>
12-
#include "nvs_flash.h"
13-
#include "iot_button.h"
14-
#include "button_gpio.h"
15-
#include "freertos/FreeRTOS.h"
16-
#include "freertos/task.h"
12+
#include <esp_random.h>
13+
#include <nvs_flash.h>
14+
#include <freertos/FreeRTOS.h>
15+
#include <freertos/task.h>
16+
#include <iot_button.h>
17+
#include <button_gpio.h>
1718
#include "blynk_edgent.h"
1819

1920
static const char* TAG = "example";
2021

22+
static EventGroupHandle_t evt_group;
23+
#define EVT_CONNECTED BIT0
24+
2125
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
2226
# define BOOT_BUTTON_NUM 0
23-
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || \
24-
CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C5
27+
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C5
2528
# define BOOT_BUTTON_NUM 9
2629
#endif
2730
#define BUTTON_ACTIVE_LEVEL 0
@@ -30,20 +33,18 @@ static void button_event_cb(void* arg, void* data) {
3033
iot_button_print_event((button_handle_t)arg);
3134
button_event_t event = iot_button_get_event((button_handle_t)arg);
3235
if (BUTTON_LONG_PRESS_START == event) {
33-
edgent_reset_config();
36+
edgent_config_reset();
3437
} else if (BUTTON_DOUBLE_CLICK == event) {
35-
edgent_start_config();
38+
edgent_config_start();
3639
}
3740
}
3841

3942
static void button_init(uint32_t button_num) {
4043
button_config_t btn_cfg = {.long_press_time = 5000, .short_press_time = 200};
41-
button_gpio_config_t gpio_cfg = {
42-
.gpio_num = (int32_t)button_num,
43-
.active_level = BUTTON_ACTIVE_LEVEL,
44-
.enable_power_save = true,
45-
.disable_pull = true
46-
};
44+
button_gpio_config_t gpio_cfg = {.gpio_num = (int32_t)button_num,
45+
.active_level = BUTTON_ACTIVE_LEVEL,
46+
.enable_power_save = true,
47+
.disable_pull = true};
4748

4849
button_handle_t btn;
4950
esp_err_t ret = iot_button_new_gpio_device(&btn_cfg, &gpio_cfg, &btn);
@@ -56,11 +57,6 @@ static void button_init(uint32_t button_num) {
5657
ESP_ERROR_CHECK(ret);
5758
}
5859

59-
void edgent_on_reboot_request(void) {
60-
ESP_LOGI(TAG, "Blynk.Edgent initiated reboot");
61-
esp_restart();
62-
}
63-
6460
static void on_downlink_datastream_callback(const char* topic, int topic_len, const char* data, int data_len) {
6561
ESP_LOGI(TAG, "Datastream received — topic: %s, data: %s", topic, data);
6662
}
@@ -75,20 +71,28 @@ static void on_state_change(void) {
7571

7672
static void on_initial_connection(void) {
7773
ESP_LOGI(TAG, "Initial connection established");
74+
edgent_get_ds_all();
75+
edgent_get_utc();
76+
edgent_get_location();
7877
}
7978

8079
static void on_config_change(void) {
8180
ESP_LOGI(TAG, "Configuration change detected");
8281
}
8382

83+
void on_reboot_request(void) {
84+
ESP_LOGI(TAG, "Blynk.Edgent initiated reboot");
85+
esp_restart();
86+
}
87+
8488
// Event handler
8589
static void blynk_edgent_event_handler(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data) {
8690
if (id == EDGENT_EVENT_STATE_CHANGED && event_data) {
8791
edgent_state_evt_t* evt = (edgent_state_evt_t*)event_data;
88-
ESP_LOGI(TAG, "Blynk Edgent state changed: %d -> %d", evt->prev, evt->curr);
92+
ESP_LOGD(TAG, "Blynk.Edgent state changed: %d -> %d", evt->prev, evt->curr);
8993
switch (evt->curr) {
9094
case EDGENT_STATE_CONNECTED:
91-
ESP_LOGI(TAG, "Device is now connected to cloud.");
95+
xEventGroupSetBits(evt_group, EVT_CONNECTED);
9296
break;
9397
case EDGENT_STATE_ERROR:
9498
ESP_LOGW(TAG, "Device entered ERROR state, take action!");
@@ -99,6 +103,20 @@ static void blynk_edgent_event_handler(void* handler_arg, esp_event_base_t base,
99103
}
100104
}
101105

106+
void other_task(void* arg) {
107+
EventBits_t bits = xEventGroupWaitBits(evt_group, EVT_CONNECTED, pdFALSE, pdFALSE, portMAX_DELAY);
108+
if (bits & EVT_CONNECTED) {
109+
ESP_LOGI(TAG, "[%s] Cloud connected event received! Continuing...", pcTaskGetName(NULL));
110+
}
111+
112+
while (true) {
113+
double rnd = 10.0 + (esp_random() % 2501) / 100.0;
114+
edgent_publish_ds_float("Set Temperature", rnd, 2);
115+
edgent_publish_ds_int("Status", rand() % 5);
116+
vTaskDelay(pdMS_TO_TICKS(10000));
117+
}
118+
}
119+
102120
extern "C" void app_main(void) {
103121
ESP_LOGI(TAG, "app_main() entered");
104122

@@ -126,29 +144,59 @@ extern "C" void app_main(void) {
126144
ESP_ERROR_CHECK(esp_event_handler_instance_register(
127145
EDGENT_EVENT_BASE, EDGENT_EVENT_STATE_CHANGED, blynk_edgent_event_handler, NULL, NULL));
128146

147+
// Create the event group
148+
evt_group = xEventGroupCreate();
149+
assert(evt_group);
150+
129151
// initialize button
130152
button_init(BOOT_BUTTON_NUM);
131153

132154
// initialize Edgent
133-
edgent_init();
134-
135-
// setup Edgent callbacks
136-
edgent_set_downlink_callback(on_downlink_callback);
137-
edgent_set_downlink_datastream_callback(on_downlink_datastream_callback);
138-
edgent_set_on_state_change(on_state_change);
139-
edgent_set_on_initial_connection(on_initial_connection);
140-
edgent_set_on_config_change(on_config_change);
155+
edgent_config_t config = {};
156+
config.downlink_ds_callback = on_downlink_datastream_callback;
157+
config.downlink_callback = on_downlink_callback;
158+
config.state_change_callback = on_state_change;
159+
config.config_change_callback = on_config_change;
160+
config.initial_connection_callback = on_initial_connection;
161+
config.reboot_request_callback = on_reboot_request;
162+
edgent_init(&config);
141163

142164
// start Edgent
143165
edgent_start();
144166

145-
bool bON = false;
146-
char data[32];
167+
// create parallel task
168+
xTaskCreate(other_task,
169+
"other_task",
170+
2048,
171+
NULL,
172+
tskIDLE_PRIORITY + 1, // default normal priority
173+
NULL);
174+
175+
ESP_LOGI(TAG, "Awaiting Cloud connection...");
176+
EventBits_t bits = xEventGroupWaitBits(evt_group, EVT_CONNECTED, pdFALSE, pdFALSE, portMAX_DELAY);
177+
if (bits & EVT_CONNECTED) {
178+
ESP_LOGI(TAG, "[%s] Cloud connected event received! Continuing...", pcTaskGetName(NULL));
179+
}
180+
181+
static bool bON = false;
147182
while (true) {
148-
int count = snprintf(data, sizeof(data) - 1, "%d", bON);
149-
// https://docs.blynk.io/en/blynk.cloud-mqtt-api/device-mqtt-api/datastreams#send-data-to-blynk
150-
edgent_publish("ds/Power", data, count, 0);
151-
edgent_publish("get/meta", "Serial,Time Zone", 16, 0);
183+
// Publish Power state
184+
edgent_publish_ds_int("Power", (int64_t)bON);
185+
186+
// Publish random Current Temperature
187+
double rnd = 10.0 + (esp_random() % 2501) / 100.0;
188+
edgent_publish_ds_float("Current Temperature", rnd, 2);
189+
190+
// Publish uptime
191+
uint32_t uptime_sec = xTaskGetTickCount();
192+
edgent_publish_ds_int("uptime", uptime_sec);
193+
194+
// Request metadata
195+
edgent_get_metadata("Device Name");
196+
197+
// Toggle widget state
198+
edgent_set_property("uptime", "isDisabled", bON ? "false" : "true");
199+
152200
bON = !bON;
153201
vTaskDelay(pdMS_TO_TICKS(15000));
154202
}

idf_component.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
version: "0.9.0-beta.4"
1+
version: "1.0.0"
22
description: "Blynk Edgent for ESP-IDF"
33
url: "https://www.blynk.io"
4-
license: "MIT"
4+
license: "Apache-2.0"
55
dependencies:
66
idf:
77
version: ">=5.4,<=5.5.2"

0 commit comments

Comments
 (0)