esp-idfzenoh

zenoh implementation over minimal esp-idf example (idf.py)


All CMakeLists.txt files are fine, the code compiles fine after a lot of tries, but keeps on failing to connect to zenoh public server "demo.zenoh.io" which resolves to 212.71.244.198. the wifi connects ok with appropriate messages...

that is a minimal example:

#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "zenoh-pico.h"
#include "utils/config.h"
#include "utils/secret.h"
#include "utils/wifi.h"

#define ZENOH_CONNECT_IP "212.71.244.198"

void data_handler(z_loaned_sample_t *sample, void *arg) {
    z_view_string_t keystr;
    z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr);
    
    z_owned_string_t value;
    z_bytes_to_string(z_sample_payload(sample), &value);
    
    ESP_LOGI(TAG, "--> [Subscriber] Received ('%.*s': '%.*s')", 
             (int)z_string_len(z_view_string_loan(&keystr)), z_string_data(z_view_string_loan(&keystr)),
             (int)z_string_len(z_string_loan(&value)), z_string_data(z_string_loan(&value)));
    
    z_drop(z_move(value));
}

void app_main(void) {
    configure_system_logging();
    ESP_LOGI(TAG, "--- ZENOH - ESP-IDF PUB/SUB ----");

    // Initialize NVS Flash
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_LOGI(TAG, "Wi-Fi init...");
    wifi_init_sta();

    ESP_LOGI(TAG, "Starting Zenoh app in CLIENT mode...");
    z_owned_session_t session;
    z_owned_config_t config;

    while(1) {
        z_config_default(&config);
        zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, "client");

        char connect_endpoint[128];
        snprintf(connect_endpoint, sizeof(connect_endpoint), "tcp/%s:7447", ZENOH_CONNECT_IP);
        zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, connect_endpoint);
        
        ESP_LOGI(TAG, "Opening Zenoh session: %s", connect_endpoint);

        if (z_open(&session, z_move(config), NULL) == Z_OK) {
            ESP_LOGI(TAG, "Zenoh session opened successfully!");
            break; 
        } else {
            ESP_LOGE(TAG, "Zenoh session failed. Retry in 27 sec...");
            vTaskDelay(27000 / portTICK_PERIOD_MS);
        }
    }

    zp_start_read_task(z_loan_mut(session), NULL);
    zp_start_lease_task(z_loan_mut(session), NULL);

    // Publisher
    const char *pub_key_expr = "demo/esp32/ping";
    ESP_LOGI(TAG, "Declare PUBlisher '%s'...", pub_key_expr);
    z_owned_keyexpr_t pub_key;
    z_keyexpr_from_str(&pub_key, pub_key_expr);
    z_owned_publisher_t pub;
    z_declare_publisher(z_loan(session), &pub, z_loan(pub_key), NULL);
    z_drop(z_move(pub_key));
    
    // Subscriber
    const char *sub_key_expr = "demo/esp32/ping";
    ESP_LOGI(TAG, "Declare SUBscriber '%s'...", sub_key_expr);
    z_owned_keyexpr_t sub_key;
    z_keyexpr_from_str(&sub_key, sub_key_expr);
    z_owned_closure_sample_t callback;
    z_closure(&callback, data_handler, NULL, NULL);
    z_owned_subscriber_t sub;
    z_declare_subscriber(z_loan(session), &sub, z_loan(sub_key), z_move(callback), NULL);
    z_drop(z_move(sub_key));
    
    int count = 0;
    char payload_buffer[128];
    while (1) {
        snprintf(payload_buffer, sizeof(payload_buffer), "ESP32 Message #%d", count++);
        ESP_LOGI(TAG, "[Publisher] Sending: '%s'", payload_buffer);
        z_owned_bytes_t payload;
        z_bytes_copy_from_str(&payload, payload_buffer);
        z_publisher_put(z_loan(pub), z_move(payload), NULL);
        
        // Wait for 23 seconds before sending the next message
        vTaskDelay(23000 / portTICK_PERIOD_MS);
    }
}

No matter what I change and try, it does not connect to zenoh with the same message below. I tried all alterations, connected the esp32s3 to a different mobile data network. I tried the pub/sub for the tcp/212.71.244.198:7447 and it works just fine. So, there is no firewall issue on my wifi router. It looks such a firewall-like problem, but I tried all those options.

I (2569) WIFI: got ip:192.168.1.101
I (2569) WIFI: connected to SSID:XXXXXXXXX
I (2569) ZENOH_APP: Starting Zenoh application in CLIENT mode...
I (2579) ZENOH_APP: Opening Zenoh session: tcp/212.71.244.198:7447
E (2579) ZENOH_APP: Zenoh session failed. Retry in 27 sec...

I add here the detailed logs of the ESP

 OK!
Opening Zenoh Session...D (4345) lwip: udp_bind(ipaddr =
D (4345) lwip: 0.0.0.0
D (4345) lwip: , port = 16452)
D (4345) lwip: udp_bind: bound to
D (4355) lwip: 0.0.0.0
D (4355) lwip: , port 16452)
D (4355) lwip: udp_send
D (4355) lwip: udp_send: added header in given pbuf 0x3fcb46ec
D (4365) lwip: udp_send: sending datagram of length 39
D (4375) lwip: udp_send: UDP packet length 39
D (4375) lwip: udp_send: UDP checksum 0x6c21
D (4375) lwip: udp_send: ip_output_if (,,,,0x11,)
D (4395) wifi:eb is dhcp or dns sport = 16452, dport = 53
D (4435) lwip: udp_input: received datagram of length 55
D (4435) lwip: UDP header:
D (4435) lwip: +-------------------------------+
D (4435) lwip: |        53     |     16452     | (src port, dest port)
D (4435) lwip: +-------------------------------+
D (4445) lwip: |        55     |     0x5c38    | (len, chksum)
D (4455) lwip: +-------------------------------+
D (4455) lwip: udp (
D (4455) lwip: 192.168.1.100
D (4455) lwip: , 16452) <-- (
D (4465) lwip: 192.168.1.1
D (4465) lwip: , 53)
D (4465) lwip: pcb (
D (4465) lwip: 0.0.0.0
D (4475) lwip: , 16452) <-- (
D (4475) lwip: 0.0.0.0
D (4475) lwip: , 0)
D (4475) lwip: pcb (
D (4475) lwip: 0.0.0.0
D (4485) lwip: , 68) <-- (
D (4485) lwip: 0.0.0.0
D (4485) lwip: , 67)
D (4485) lwip: udp_input: calculating checksum
D (4495) lwip: tcp_close: closing in
D (4495) lwip: State: CLOSED
Unable to open session!

Solution

  • EUREKA!
    file /components/zenoh-pico/include/zenoh-pico/config.h

    **MUST ALTER**

    ```

    #define Z_FRAG_MAX_SIZE 4096

    #define Z_BATCH_UNICAST_SIZE 2048

    #define Z_BATCH_MULTICAST_SIZE 2048

    #define Z_CONFIG_SOCKET_TIMEOUT 5000

    ```

    *MOST IMPORTANT* seems to be the line `Z_CONFIG_SOCKET_TIMEOUT 100`from 100 to 5000. Feel free to experiment with lower values (it seems to work with 1000).

    Project is uploaded in github: https://github.com/georgevio/ESP32-Zenoh.git