Native ESP-IDF Blynk client

Hello Blynkers!

I’m not a big fan of Arduino and Arduino coding style, so I decided to write my own Blynk client for bare ESP-IDF (Espressif ESP32 SDK based on FreeRTOS). It’s main features are thread-safety and robust error and timeout handling.

It was tested with ESP-IDF 2.0, but it might work in other FreeRTOS+LwIP environments as well as in POSIX environment (with minimal porting).

The code is immature and may contain bugs.

Stripped down example application (full source code):

/* WiFi handling code skipped */

/* Blynk client state handler */
static void state_handler(blynk_client_t *c, const blynk_state_evt_t *ev, void *data) {
	ESP_LOGI(tag, "state: %d\n", ev->state);
}

/* Virtual write handler */
static void vw_handler(blynk_client_t *c, uint16_t id, const char *cmd, int argc, char **argv, void *data) {
	if (argc > 1 && atoi(argv[0]) == PWM_VIRTUAL_PIN) {
		uint32_t value = atoi(argv[1]);

		/* Update PWM channel */
		ledc_set_duty(PWM_MODE, PWM_CHANNEL, value);
		ledc_update_duty(PWM_MODE, PWM_CHANNEL);
	}
}

/* Virtual read handler */
static void vr_handler(blynk_client_t *c, uint16_t id, const char *cmd, int argc, char **argv, void *data) {
	if (argc > 0 && atoi(argv[0]) == ADC_VIRTUAL_PIN) {
		/* Get ADC value */
		int value = adc1_get_voltage(ADC_CHANNEL);

		/* Respond with `virtual write' command */
		blynk_send(c, BLYNK_CMD_HARDWARE, 0, "sii", "vw", ADC_VIRTUAL_PIN, value);
	}
}

static void init_adc() {
	adc1_config_width(ADC_WIDTH(ADC_BITS));
	adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN);
}

static void init_pwm() {
	ledc_timer_config_t timer = {
		.bit_num = PWM_BITS,
		.freq_hz = PWM_FREQ,
		.speed_mode = PWM_MODE,
		.timer_num = PWM_TIMER,
	};
	ledc_timer_config(&timer);

	ledc_channel_config_t channel = {
		.channel = PWM_CHANNEL,
		.duty = 0,
		.gpio_num = PWM_PIN,
		.speed_mode = PWM_MODE,
		.timer_sel = PWM_TIMER,
	};

	ledc_channel_config(&channel);
}

void app_main() {
	init_adc();
	init_pwm();

	ESP_ERROR_CHECK(nvs_flash_init());
	tcpip_adapter_init();
	ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

	/* Init WiFi */
	wifi_conn_init();

	blynk_client_t *client = malloc(sizeof(blynk_client_t));
	blynk_init(client);

	blynk_options_t opt = {
		.token = BLYNK_TOKEN,
		/* Use default server and timeouts */
	};

	blynk_set_options(client, &opt);

	/* Subscribe to state changes and errors */
	blynk_set_state_handler(client, state_handler, NULL);

	/* blynk_set_handler sets hardware (BLYNK_CMD_HARDWARE) command handler */
	blynk_set_handler(client, "vw", vw_handler, NULL);
	blynk_set_handler(client, "vr", vr_handler, NULL);

	/* Start Blynk client task */
	blynk_start(client);
}
2 Likes

@e_asphyx - Cool. I could actually help you to port the existing C++ library - which will provide developers with consistent experience and full compatibility (we can maintain it).
Just drop me a PM :wink:

@vshymanskyy Surprisingly I can’t find how to send PMs. Are you talking about implementing Blynk API wrapper on top of native client?

Click on his avatar and choose Message

I can see only badges and link to profile there. It makes me feel stupid…

I kicked you up a level… try it again and let me know.

1 Like

Hello everyone. I trying to reproduce your example, but something wrong.

> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5628
load:0x40078000,len:0
load:0x40078000,len:13716
entry 0x40078fb4
I (28) boot: ESP-IDF v3.1-dev-84-gf8bda324 2nd stage bootloader
I (29) boot: compile time 21:15:05
I (29) boot: Enabling RNG early entropy source...
I (35) boot: SPI Speed      : 40MHz
I (39) boot: SPI Mode       : DIO
I (43) boot: SPI Flash Size : 4MB
I (47) boot: Partition Table:
I (50) boot: ## Label            Usage          Type ST Offset   Length
I (58) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (73) boot:  2 factory          factory app      00 00 00010000 00100000
I (80) boot: End of partition table
I (84) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x111a4 ( 70052) map
I (118) esp_image: segment 1: paddr=0x000211cc vaddr=0x3ffb0000 size=0x03194 ( 12692) load
I (123) esp_image: segment 2: paddr=0x00024368 vaddr=0x40080000 size=0x00400 (1024) load
0x40080000: _iram_start at C:/Users/sasho/AppData/Roaming/SPB_Data/esp/esp-idf/c
omponents/freertos/xtensa_vectors.S:1685
I (125) esp_image: segment 3: paddr=0x00024770 vaddr=0x40080400 size=0x0b8a0 ( 47264) load
I (153) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x56d98 (355736) map
0x400d0018: _stext at ??:?
I (276) esp_image: segment 5: paddr=0x00086db8 vaddr=0x4008bca0 size=0x04770 ( 18288) load
0x4008bca0: bb_init at ??:?
I (284) esp_image: segment 6: paddr=0x0008b530 vaddr=0x400c0000 size=0x00000 (  0) load
I (294) boot: Loaded app from partition at offset 0x10000
I (294) boot: Disabling RNG early entropy source...
I (295) cpu_start: Pro cpu up.
I (299) cpu_start: Starting app cpu, entry point is 0x40080f1c
0x40080f1c: call_start_cpu1 at C:/Users/sasho/AppData/Roaming/SPB_Data/esp/esp-i
df/components/esp32/cpu_start.c:222
I (291) cpu_start: App cpu up.
I (309) heap_init: Initializing. RAM available for dynamic allocation:
I (316) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (322) heap_init: At 3FFB8EC8 len 00027138 (156 KiB): DRAM
I (328) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (335) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (341) heap_init: At 40090410 len 0000FBF0 (62 KiB): IRAM
I (347) cpu_start: Pro cpu start user code
I (30) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (94) wifi: wifi firmware version: f204566
I (94) wifi: config NVS flash: enabled
I (94) wifi: config nano formating: disabled
I (94) system_api: Base MAC address is not set, read default base MAC address fr
om BLK0 of EFUSE
I (104) system_api: Base MAC address is not set, read default base MAC address f
rom BLK0 of EFUSE
I (134) wifi: Init dynamic tx buffer num: 32
I (134) wifi: Init data frame dynamic rx buffer num: 32
I (134) wifi: Init management frame dynamic rx buffer num: 32
I (134) wifi: wifi driver task: 3ffc037c, prio:23, stack:4096
I (144) wifi: Init static rx buffer num: 10
I (144) wifi: Init dynamic rx buffer num: 32
I (154) wifi: wifi power manager task: 0x3ffc4fbc prio: 21 stack: 2560
ets Jun  8 2016 00:22:57

> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:5628
load:0x40078000,len:0
load:0x40078000,len:13716
entry 0x40078fb4
I (28) boot: ESP-IDF v3.1-dev-84-gf8bda324 2nd stage bootloader
I (29) boot: compile time 21:15:05
I (29) boot: Enabling RNG early entropy source...
I (35) boot: SPI Speed      : 40MHz
I (39) boot: SPI Mode       : DIO
I (43) boot: SPI Flash Size : 4MB
I (47) boot: Partition Table:
I (50) boot: ## Label            Usage          Type ST Offset   Length
I (58) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (73) boot:  2 factory          factory app      00 00 00010000 00100000
I (80) boot: End of partition table
I (84) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x111a4 ( 70052) map
I (118) esp_image: segment 1: paddr=0x000211cc vaddr=0x3ffb0000 size=0x03194 ( 12692) load
I (123) esp_image: segment 2: paddr=0x00024368 vaddr=0x40080000 size=0x00400 (1024) load
0x40080000: _iram_start at C:/Users/sasho/AppData/Roaming/SPB_Data/esp/esp-idf/c
omponents/freertos/xtensa_vectors.S:1685
I (125) esp_image: segment 3: paddr=0x00024770 vaddr=0x40080400 size=0x0b8a0 ( 47264) load
I (153) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x56d98 (355736) map
0x400d0018: _stext at ??:?
I (276) esp_image: segment 5: paddr=0x00086db8 vaddr=0x4008bca0 size=0x04770 ( 18288) load
0x4008bca0: bb_init at ??:?
I (284) esp_image: segment 6: paddr=0x0008b530 vaddr=0x400c0000 size=0x00000 (   0) load
I (294) boot: Loaded app from partition at offset 0x10000
I (294) boot: Disabling RNG early entropy source...
I (295) cpu_start: Pro cpu up.
I (299) cpu_start: Starting app cpu, entry point is 0x40080f1c
0x40080f1c: call_start_cpu1 at C:/Users/sasho/AppData/Roaming/SPB_Data/esp/esp-i
df/components/esp32/cpu_start.c:222
I (291) cpu_start: App cpu up.
I (309) heap_init: Initializing. RAM available for dynamic allocation:
I (316) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (322) heap_init: At 3FFB8EC8 len 00027138 (156 KiB): DRAM
I (328) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (335) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (341) heap_init: At 40090410 len 0000FBF0 (62 KiB): IRAM
I (347) cpu_start: Pro cpu start user code
I (30) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (94) wifi: wifi firmware version: f204566
I (94) wifi: config NVS flash: enabled
I (94) wifi: config nano formating: disabled
I (94) system_api: Base MAC address is not set, read default base MAC address fr
om BLK0 of EFUSE
I (104) system_api: Base MAC address is not set, read default base MAC address f
rom BLK0 of EFUSE
I (134) wifi: Init dynamic tx buffer num: 32
I (134) wifi: Init data frame dynamic rx buffer num: 32
I (134) wifi: Init management frame dynamic rx buffer num: 32
I (134) wifi: wifi driver task: 3ffc037c, prio:23, stack:4096
I (144) wifi: Init static rx buffer num: 10
I (144) wifi: Init dynamic rx buffer num: 32
I (154) wifi: wifi power manager task: 0x3ffc4fbc prio: 21 stack: 2560
I (184) phy: phy_version: 366.0, ba9923d, Oct 31 2017, 18:06:17, 0, 0
I (184) wifi: mode : sta (24:0a:c4:12:83:64)
I (184) blynk-example: WiFi started
I (194) blynk-example: state: 1
W (194) blynk: disconnected, reason: 8, code: 202
I (194) blynk-example: state: 1
I (2594) wifi: n:6 2, o:1 0, ap:255 255, sta:6 2, prof:1
I (3574) wifi: state: init -> auth (b0)
I (3584) wifi: state: auth -> assoc (0)
I (3584) wifi: state: assoc -> run (10)
I (3834) wifi: connected with SaShOk, channel 6
I (5514) event: sta ip: 192.168.0.38, mask: 255.255.255.0, gw: 192.168.0.1
I (6074) blynk-example: state: 2
I (6584) wifi: pm start, type:0
I (11074) blynk: auth: 65535
W (11074) blynk: disconnected, reason: 6, code: 0
I (11074) blynk-example: state: 1
I (16114) blynk-example: state: 2
I (21114) blynk: auth: 65535
W (21114) blynk: disconnected, reason: 6, code: 0
I (21114) blynk-example: state: 1
I (26154) blynk-example: state: 2
I (31154) blynk: auth: 65535
W (31154) blynk: disconnected, reason: 6, code: 0
I (31154) blynk-example: state: 1
I (36194) blynk-example: state: 2
I (41194) blynk: auth: 65535
W (41194) blynk: disconnected, reason: 6, code: 0
I (41194) blynk-example: state: 1
I (46234) blynk-example: state: 2
I (51234) blynk: auth: 65535
W (51234) blynk: disconnected, reason: 6, code: 0
I (51234) blynk-example: state: 1
I (56274) blynk-example: state: 2

In app I do not see my device(I use ESP32DevBoard). Can any help me?

Same results for me!

Hello. I found the problem, now it works on my side. I was setup ESP_IDF_V2.1 and change toolchain on xtensa-esp32-elf-win32-1.22.0-61-gab8375a-5.2.0…After that it works, but ceased work debug in eclipse via jtag, I did not understand where is problem

1 Like

But now I have the problem with adding function: pushing data from hardware( http://docs.blynk.cc/#blynk-main-operations-get-data-from-hardware-pushing-data-from-hardware). Can any help me?

Continuing the discussion from Native ESP-IDF Blynk client:

Sorry to dig up an old thread, did either of you (@e_asphyx / @vshymanskyy ) get any further with a true ESP-IDF port?

Thanks!

@vshymanskyy Could you please share the ESP-IDF portable code to use the blynk as i’ve many customised products to be make.