{"id":31783430,"url":"https://github.com/georgevio/zenoh-single-lib","last_synced_at":"2026-05-17T06:45:13.633Z","repository":{"id":318351940,"uuid":"1070921755","full_name":"georgevio/zenoh-single-lib","owner":"georgevio","description":"Self-contained, plug-and-play module for zenoh-pico implementation for ESP32 devices","archived":false,"fork":false,"pushed_at":"2025-10-06T17:10:12.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-06T18:36:07.335Z","etag":null,"topics":["esp32","esp32s3","espidf","zenoh","zenoh-pico"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/georgevio.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-06T16:05:14.000Z","updated_at":"2025-10-06T17:10:15.000Z","dependencies_parsed_at":"2025-10-06T18:36:09.933Z","dependency_job_id":null,"html_url":"https://github.com/georgevio/zenoh-single-lib","commit_stats":null,"previous_names":["georgevio/zenoh-single-lib"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/georgevio/zenoh-single-lib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgevio%2Fzenoh-single-lib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgevio%2Fzenoh-single-lib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgevio%2Fzenoh-single-lib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgevio%2Fzenoh-single-lib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/georgevio","download_url":"https://codeload.github.com/georgevio/zenoh-single-lib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/georgevio%2Fzenoh-single-lib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003536,"owners_count":26083595,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp32","esp32s3","espidf","zenoh","zenoh-pico"],"created_at":"2025-10-10T10:25:17.906Z","updated_at":"2026-05-17T06:45:13.618Z","avatar_url":"https://github.com/georgevio.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Zenoh Communication Module for ESP32\n\nThis folder contains a self-contained, plug-and-play module for handling [Zenoh](https://zenoh.io/) communication on ESP32 devices. It is designed to abstract away the complexities of the Zenoh-pico C API, providing a simple, configuration-driven interface for peer-to-peer or client-server messaging.\n\nThe module is autonomous: to use it, you just need to copy this `zenoh` directory into your project's `main` folder and configure your device's role and transport settings in a single header file.\n\n\u003cimg src=\"zenoh_lib.png\" alt=\"zenoh_lib.png\" width=\"400\"\u003e\n\n## Key Features\n\n*   **Simplified Configuration**: All settings are centralized in `zenoh_config.h`. Just define the device role and transport type.\n*   **Role-Based Architecture**: Pre-defined `ZENOH_ROLE_CLIENT` and `ZENOH_ROLE_SERVER` roles simplify application logic.\n*   **Transport Abstraction**: Easily switch between TCP (client or peer) and UDP (multicast peer) modes.\n*   **Lifecycle Management**: Automatically handles Zenoh session initialization, resource declaration (publishers, subscribers, queryables), and clean shutdown.\n*   **Helper Utilities**: Provides utilities for network interface detection and logging.\n*   **Optional Features**: Includes built-in, toggleable support for heartbeats and network scouting.\n\n## File Structure\n\n*   `zenoh_config.h`: **(User facing)** The single source of truth for all Zenoh settings.\n*   `zenoh_manager.h` / `.cpp`: The core engine that manages the Zenoh session, tasks, and API calls.\n*   `zenoh_heartbeat.h` / `.c`: An optional module for sending and receiving periodic heartbeats.\n*   `zenoh_scout.h` / `.c`: An optional module for discovering other Zenoh peers on the network.\n*   `zenoh_utils.h` / `.c`: Helper functions for network interface discovery.\n\n## How to Use\n\n### 1. Integration\n\nCopy the entire `zenoh/` directory into the `main/` folder of your ESP-IDF project.\n\n### 2. Configuration\n\nOpen `zenoh/zenoh_config.h` and modify the **User Configuration** section. This is the only file you need to edit.\n\n```c\n// zenoh/zenoh_config.h\n\n// 1. DEFINE THE ROLE OF THIS DEVICE\n//    - ZENOH_ROLE_CLIENT: The device that sends data (e.g., ESP32-CAM).\n//    - ZENOH_ROLE_SERVER: The device that receives data (e.g., ESP32-S3).\n#define ZENOH_DEVICE_ROLE ZENOH_ROLE_CLIENT\n\n// 2. DEFINE THE ZENOH TRANSPORT AND MODE\n//    - ZENOH_TRANSPORT_TCP_CLIENT: Connects to a specific server IP.\n//    - ZENOH_TRANSPORT_TCP_PEER:   Listens for incoming TCP connections.\n//    - ZENOH_TRANSPORT_UDP_PEER:   Listens on a multicast address.\n#define ZENOH_TRANSPORT ZENOH_TRANSPORT_TCP_CLIENT\n\n// 3. DEFINE NETWORK ENDPOINTS\n#define ZENOH_SERVER_IP \"192.168.1.100\" // IP of the ZENOH_ROLE_SERVER device.\n#define ZENOH_PORT \"7447\"\n\n// 4. FEATURE FLAGS (Optional)\n#define PUBLISHER_ON 1\n#define SUBSCRIBER_ON 1\n#define HEARTBEAT_ON 0\n```\n\nBased on your choices, the correct Zenoh `mode` (`client` or `peer`) and transport endpoints are automatically generated. The pre-processor directives will raise a compile-time error if you select an invalid combination (e.g., a `SERVER` role with a `TCP_CLIENT` transport).\n\n### IMPORTANT NOTE FOR TCP PEER \n\nApply the following in `idf.py menuconfig`\n```\nComponent config -LWIP\n[*] Enable SO_LINGER processing\n```\n\n**BE CAREFUL: in zenoh config.h, they have to be the same at both communicating sides!**\n```\n#define Z_FRAG_MAX_SIZE 1024\n#define Z_BATCH_UNICAST_SIZE 1024\n#define Z_BATCH_MULTICAST_SIZE 1024\n#define Z_CONFIG_SOCKET_TIMEOUT 3000\n## Main Application Example\n```\n\nHere is a complete example of how to integrate this module into your `app_main.cpp`. It demonstrates initializing WiFi, starting the Zenoh manager, and using its publish/subscribe functionality.\n\n```cpp\n// app_main.cpp\n\n#include \"freertos/FreeRTOS.h\"\n#include \"freertos/event_groups.h\"\n#include \"esp_wifi.h\"\n#include \"esp_log.h\"\n#include \"nvs_flash.h\"\n\n// 1. Include the Zenoh manager\n#include \"zenoh/zenoh_manager.h\"\n\nstatic const char* TAG = \"MAIN_APP\";\nstatic EventGroupHandle_t s_app_event_group;\n\n// Define a bit for WiFi connection status\n#define WIFI_CONNECTED_BIT (1 \u003c\u003c 0)\n\n// --- Data Handler Callback ---\n// This function will be called whenever data is received on a subscribed key expression.\nvoid data_handler_callback(z_loaned_sample_t* sample, void* arg) {\n    z_owned_string_t payload_str;\n    z_bytes_to_string(z_sample_payload(sample), \u0026payload_str);\n\n    z_view_string_t key_expr_str;\n    z_keyexpr_as_view_string(z_sample_keyexpr(sample), \u0026key_expr_str);\n\n    ESP_LOGI(TAG, \"\u003e\u003e Received data '%.*s' on key '%.*s'\",\n             (int)z_string_len(z_loan(payload_str)), z_string_data(z_loan(payload_str)),\n             (int)z_string_len(z_loan(key_expr_str)), z_string_data(z_loan(key_expr_str)));\n\n    // IMPORTANT: Free the payload string memory\n    z_drop(z_move(payload_str));\n}\n\n// --- WiFi and IP Event Handler ---\nstatic void app_event_handler(void* arg, esp_event_base_t event_base,\n            int32_t event_id, void* event_data) {\n    if (event_base == WIFI_EVENT \u0026\u0026 event_id == WIFI_EVENT_STA_DISCONNECTED) {\n        ESP_LOGI(TAG, \"Wi-Fi disconnected, trying to reconnect...\");\n        esp_wifi_connect();\n    } else if (event_base == IP_EVENT \u0026\u0026 event_id == IP_EVENT_STA_GOT_IP) {\n        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;\n        ESP_LOGI(TAG, \"Got IP address: \" IPSTR, IP2STR(\u0026event-\u003eip_info.ip));\n        xEventGroupSetBits(s_app_event_group, WIFI_CONNECTED_BIT);\n    }\n}\n\n// --- Main Application ---\nextern \"C\" void app_main() {\n    // --- Standard ESP-IDF Initialization ---\n    ESP_ERROR_CHECK(nvs_flash_init());\n    ESP_ERROR_CHECK(esp_netif_init());\n    ESP_ERROR_CHECK(esp_event_loop_create_default());\n    s_app_event_group = xEventGroupCreate();\n\n    // Register WiFi and IP event handlers\n    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, \u0026app_event_handler, NULL));\n    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, \u0026app_event_handler, NULL));\n\n    // Configure and start WiFi\n    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();\n    ESP_ERROR_CHECK(esp_wifi_init(\u0026cfg));\n    esp_netif_create_default_wifi_sta();\n    wifi_config_t wifi_config = { .sta = { .ssid = \"YOUR_WIFI_SSID\", .password = \"YOUR_WIFI_PASSWORD\" } };\n    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));\n    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, \u0026wifi_config));\n    ESP_ERROR_CHECK(esp_wifi_start());\n    ESP_ERROR_CHECK(esp_wifi_connect());\n\n    ESP_LOGI(TAG, \"Waiting for WiFi connection...\");\n    xEventGroupWaitBits(s_app_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);\n    ESP_LOGI(TAG, \"WiFi Connected!\");\n\n    // ZENOH\n    ESP_LOGI(TAG, \"Starting Zenoh Manager...\");\n    zenoh_client_init_and_start(s_app_event_group, data_handler_callback);\n\n    ESP_LOGI(TAG, \"Waiting for Zenoh session to open...\");\n    xEventGroupWaitBits(s_app_event_group, ZENOH_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);\n    ESP_LOGI(TAG, \"Zenoh Session Open!\");\n\n    xEventGroupWaitBits(s_app_event_group, ZENOH_DECLARED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);\n    ESP_LOGI(TAG, \"Zenoh Resources Declared!\");\n\n    int counter = 0;\n    while (1) {\n        char payload[32];\n        snprintf(payload, sizeof(payload), \"Hello #%d\", counter++);\n\n        // For a CLIENT, this publishes to \"faces/announcements/**\"\n        // For a SERVER, this publishes to \"faces/results/**\"\n        zenoh_publish(KEYEXPR_PUB, payload);\n\n        vTaskDelay(pdMS_TO_TICKS(5000));\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorgevio%2Fzenoh-single-lib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeorgevio%2Fzenoh-single-lib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeorgevio%2Fzenoh-single-lib/lists"}