From 74ac9cedb7a94f8f01cd55fc1316fbf6db8bcc72 Mon Sep 17 00:00:00 2001 From: BartolomeyKant Date: Mon, 16 Mar 2026 17:49:48 +0500 Subject: [PATCH 1/3] add get client uid --- aether/aether_c/aether_capi.cpp | 9 +++++++++ aether/aether_c/aether_capi.h | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/aether/aether_c/aether_capi.cpp b/aether/aether_c/aether_capi.cpp index d677f3c4..60596c0c 100644 --- a/aether/aether_c/aether_capi.cpp +++ b/aether/aether_c/aether_capi.cpp @@ -394,6 +394,15 @@ void FreeClient(AetherClient* client) { delete client; } +int GetClientUid(AetherClient* client, CUid* uid) { + if (!client->client) { + return -1; + } + auto client_uid = client->client->uid(); + *uid = CUidFromBytes(client_uid.value.data(), client_uid.value.size()); + return 0; +} + void Send(CUid destination, void const* data, size_t size, ActionStatusCb status_cb, void* user_data) { assert(default_client); diff --git a/aether/aether_c/aether_capi.h b/aether/aether_c/aether_capi.h index 606ab9c7..2b08f77c 100644 --- a/aether/aether_c/aether_capi.h +++ b/aether/aether_c/aether_capi.h @@ -90,6 +90,15 @@ AetherClient* SelectClient(ClientConfig const* config); */ void FreeClient(AetherClient* client); +/** + * \brief Read client's uid. + * This should be called on fully loaded client's only. + * \param client to read uid from. + * \param uid the pointer to read uid to. + * \return if 0, operation success, !0 something get wrong. + */ +int GetClientUid(AetherClient* client, CUid* uid); + /** * \brief Send a message from selected client to destination client. * \param client The client to send the message from. From 12af37992ffb2bd3eba127f69191b13cc579084e Mon Sep 17 00:00:00 2001 From: BartolomeyKant Date: Mon, 16 Mar 2026 17:49:55 +0500 Subject: [PATCH 2/3] fix set wifi config --- aether/aether_c/aether_capi.cpp | 47 +++++---------------------------- 1 file changed, 6 insertions(+), 41 deletions(-) diff --git a/aether/aether_c/aether_capi.cpp b/aether/aether_c/aether_capi.cpp index 60596c0c..dc612087 100644 --- a/aether/aether_c/aether_capi.cpp +++ b/aether/aether_c/aether_capi.cpp @@ -258,53 +258,18 @@ int AetherInit(AetherConfig const* config) { auto* wifi_conf = reinterpret_cast(conf); - static ae::IpV4Addr my_static_ip_v4{192, 168, 1, 100}; - static ae::IpV4Addr my_gateway_ip_v4{192, 168, 1, 1}; - static ae::IpV4Addr my_netmask_ip_v4{255, 255, 255, 0}; - static ae::IpV4Addr my_dns1_ip_v4{8, 8, 8, 8}; - static ae::IpV4Addr my_dns2_ip_v4{8, 8, 4, 4}; - static ae::IpV6Addr my_static_ip_v6{ - 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, - 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34}; - - static ae::WiFiIP wifi_ip{ - {my_static_ip_v4}, // ESP32 static IP - {my_gateway_ip_v4}, // IP Address of your network - // gateway (router) - {my_netmask_ip_v4}, // Subnet mask - {my_dns1_ip_v4}, // Primary DNS (optional) - {my_dns2_ip_v4}, // Secondary DNS (optional) - {my_static_ip_v6} // ESP32 static IP v6 - }; - - static ae::WifiCreds my_wifi{wifi_conf->ssid, - wifi_conf->password}; - - ae::WiFiAp wifi_ap{my_wifi, wifi_ip}; - - std::vector wifi_ap_vec{wifi_ap}; - - static ae::WiFiPowerSaveParam wifi_psp{ - true, - AE_WIFI_PS_MAX_MODEM, // Power save type - AE_WIFI_PROTOCOL_11B | AE_WIFI_PROTOCOL_11G | - AE_WIFI_PROTOCOL_11N, // Protocol bitmap - 3, // Listen interval - 500, // Beacon interval - 0, // Fix rate - 3, // Short retry - 3, // Long retry - 8 // Power - }; + ae::WifiCreds my_wifi{wifi_conf->ssid, wifi_conf->password}; + ae::WiFiAp wifi_ap{std::move(my_wifi), std::nullopt}; + std::vector wifi_ap_vec{std::move(wifi_ap)}; ae::WiFiInit wifi_init{ - wifi_ap_vec, // Wi-Fi access points - wifi_psp, // Power save parameters + std::move(wifi_ap_vec), // Wi-Fi access points + {}, // Power save parameters }; adapters->Add(ae::WifiAdapter::ptr::Create( context.domain(), context.aether(), context.poller(), - context.dns_resolver(), wifi_init)); + context.dns_resolver(), std::move(wifi_init))); # endif break; } From 3f45282d13ba84b6b3861f6dd9381d5aa5100e2a Mon Sep 17 00:00:00 2001 From: BartolomeyKant Date: Mon, 16 Mar 2026 17:55:20 +0500 Subject: [PATCH 3/3] enhance c-api examples Add two sides: tom's and ground control's The ground control side start aether, select client and wait for message. On message it send their message back. The major tom's side requires to know UID the ground control's side (look for it in logs >>>). It starts and send the message then waits for response. --- examples/capi/oddity/CMakeLists.txt | 35 +++-- examples/capi/oddity/aether_ground_control.c | 131 +++++++++++++++++++ examples/capi/oddity/aether_oddity.c | 52 -------- examples/capi/oddity/aether_tom.c | 108 +++++++++++++++ examples/capi/oddity/main.c | 58 -------- 5 files changed, 264 insertions(+), 120 deletions(-) create mode 100644 examples/capi/oddity/aether_ground_control.c delete mode 100644 examples/capi/oddity/aether_oddity.c create mode 100644 examples/capi/oddity/aether_tom.c delete mode 100644 examples/capi/oddity/main.c diff --git a/examples/capi/oddity/CMakeLists.txt b/examples/capi/oddity/CMakeLists.txt index 34d42565..c84aafa8 100644 --- a/examples/capi/oddity/CMakeLists.txt +++ b/examples/capi/oddity/CMakeLists.txt @@ -14,22 +14,37 @@ cmake_minimum_required(VERSION 3.16.0) -list(APPEND src_list - main.c - aether_oddity.c) - if(NOT CM_PLATFORM) project("aether-oddity" VERSION "1.0.0" LANGUAGES C) - add_executable(${PROJECT_NAME} ${src_list}) - target_link_libraries(${PROJECT_NAME} PRIVATE aether) + add_executable("aether-tom" aether_tom.c) + target_link_libraries("aether-tom" PRIVATE aether) + + add_executable("aether-ground-control" aether_ground_control.c) + target_link_libraries("aether-ground-control" PRIVATE aether) else() - idf_build_get_property(CM_PLATFORM CM_PLATFORM) if(CM_PLATFORM STREQUAL "ESP32") + set(SELECTED_ODDITY "" CACHE STRING "The selected oddity example values:[GROUND_CONTROL, TOM]") + set(WIFI_SSID "" CACHE STRING "Wifi ssid") + set(WIFI_PASSWORD "" CACHE STRING "Wifi password") + #ESP32 CMake - idf_component_register(SRCS ${src_list} - INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} - PRIV_REQUIRES aether) + if (SELECTED_ODDITY STREQUAL "GROUND_CONTROL") + idf_component_register(SRCS aether_ground_control.c + INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + PRIV_REQUIRES aether) + else() + set(DEST_UID "" CACHE STRING "Destination uid") + + idf_component_register(SRCS aether_tom.c + INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} + PRIV_REQUIRES aether) + if (NOT DEST_UID STREQUAL "") + target_compile_definitions(${COMPONENT_LIB} PRIVATE "DEST_UID=\"${DEST_UID}\"" ) + endif() + endif() + target_compile_definitions(${COMPONENT_LIB} PRIVATE ${WIFI_SSID} "WIFI_SSID=\"${WIFI_SSID}\"" ) + target_compile_definitions(${COMPONENT_LIB} PRIVATE ${WIFI_PASSWORD} "WIFI_PASSWORD=\"${WIFI_PASSWORD}\"" ) else() #Other platforms message(FATAL_ERROR "Platform ${CM_PLATFORM} is not supported") diff --git a/examples/capi/oddity/aether_ground_control.c b/examples/capi/oddity/aether_ground_control.c new file mode 100644 index 00000000..96563839 --- /dev/null +++ b/examples/capi/oddity/aether_ground_control.c @@ -0,0 +1,131 @@ +/* + * Copyright 2026 Aethernet Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifdef ESP_PLATFORM +# include +# include +# include +#endif + +extern int AetherGC(); + +#ifdef ESP_PLATFORM +void app_main() { + esp_task_wdt_config_t config_wdt = { + .timeout_ms = 60000, + .idle_core_mask = 0, // i.e. do not watch any idle task + .trigger_panic = true}; + + esp_err_t err = esp_task_wdt_reconfigure(&config_wdt); + if (err != 0) { + fprintf(stderr, "Reconfigure WDT is failed!\n"); + } + + AetherGC(); +} +#endif + +#if (defined(__linux__) || defined(__unix__) || defined(__APPLE__) || \ + defined(__FreeBSD__) || defined(_WIN64) || defined(_WIN32)) +int main(int argc, char* argv[]) { return AetherGC(); } +#endif + +#include "aether/capi.h" + +void PrintUid(CUid const* uid) { + int i = 0; + for (; i < 4; i++) { + printf("%02x", uid->value[i]); + } + printf("-"); + for (; i < 6; i++) { + printf("%02x", uid->value[i]); + } + printf("-"); + for (; i < 8; i++) { + printf("%02x", uid->value[i]); + } + printf("-"); + for (; i < 10; i++) { + printf("%02x", uid->value[i]); + } + printf("-"); + for (; i < 16; i++) { + printf("%02x", uid->value[i]); + } +} + +#define TEST_UID "3ac93165-3d37-4970-87a6-fa4ee27744e4" +char const* message = "Ground control to Major Tom"; + +void ClientSelected(AetherClient* client, void* user_data) { + CUid uid; + GetClientUid(client, &uid); + printf(">>> Loaded clieint with uid:"); + PrintUid(&uid); + printf("<<<\n"); +} + +void MessageSentCb(ActionStatus status, void* user_data) { AetherExit(0); } + +void MessageReceived(AetherClient* client, CUid sender, void const* data, + size_t size, void* user_data) { + printf(">>> Received message size: %zu test: %s\n", size, (char const*)data); + // send message and wait till it sent + SendStr(sender, message, MessageSentCb, NULL); +} + +int AetherGC() { + // This init aether library + // Send a message and wait for response + +#ifdef ESP_PLATFORM + AeWifiAdapterConf wifi_adapter_conf = { + .type = AeWifiAdapter, + .ssid = WIFI_SSID, + .password = WIFI_PASSWORD, + }; + AdapterBase* adapter_confs = (AdapterBase*)&wifi_adapter_conf; + Adapters adapters = { + .count = 1, + .adapters = &adapter_confs, + }; +#endif + + ClientConfig client_config = { + .id = "ground control", + .parent_uid = CUidFromString(TEST_UID), + .client_selected_cb = ClientSelected, + .message_received_cb = MessageReceived, + }; + + AetherConfig aether_config = { +#ifdef ESP_PLATFORM + .adapters = &adapters, +#endif + .default_client = &client_config, + }; + + AetherInit(&aether_config); + + while (AetherExcited() == AE_NOK) { + uint64_t time = AetherUpdate(); + AetherWait(time); + } + return AetherEnd(); +} diff --git a/examples/capi/oddity/aether_oddity.c b/examples/capi/oddity/aether_oddity.c deleted file mode 100644 index 39fe84a9..00000000 --- a/examples/capi/oddity/aether_oddity.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2025 Aethernet Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "aether/capi.h" - -char const* message = "Major Tom to ground control"; - -void MessageReceived(AetherClient* client, CUid sender, void const* data, - size_t size, void* user_data) { - printf("Received message size: %zu test: %s\n", size, (char const*)data); - - AetherExit(0); -} - -int AetherOddity(char const* destination_uid) { - // This init aether library - // Send a message and wait for response - - ClientConfig client_config = { - .id = "Tom", - .parent_uid = CUidFromString("3ac93165-3d37-4970-87a6-fa4ee27744e4"), - .message_received_cb = MessageReceived, - }; - - AetherConfig aether_config = { - .default_client = &client_config, - }; - - AetherInit(&aether_config); - SendStr(CUidFromString(destination_uid), message, NULL, NULL); - - while (AetherExcited() == AE_NOK) { - uint64_t time = AetherUpdate(); - AetherWait(time); - } - - return AetherEnd(); -} diff --git a/examples/capi/oddity/aether_tom.c b/examples/capi/oddity/aether_tom.c new file mode 100644 index 00000000..eebba9a4 --- /dev/null +++ b/examples/capi/oddity/aether_tom.c @@ -0,0 +1,108 @@ +/* + * Copyright 2026 Aethernet Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifdef ESP_PLATFORM +# include +# include +# include +#endif + +extern int AetherTom(char const* destination_uid); + +#ifdef ESP_PLATFORM +void app_main(void) { + esp_task_wdt_config_t config_wdt = { + .timeout_ms = 60000, + .idle_core_mask = 0, // i.e. do not watch any idle task + .trigger_panic = true}; + + esp_err_t err = esp_task_wdt_reconfigure(&config_wdt); + if (err != 0) { + fprintf(stderr, "Reconfigure WDT is failed!\n"); + } + +# ifndef DEST_UID +# error "DEST_UID should be defined for aether_tom" +# endif + + AetherTom(DEST_UID); +} +#endif + +#if (defined(__linux__) || defined(__unix__) || defined(__APPLE__) || \ + defined(__FreeBSD__) || defined(_WIN64) || defined(_WIN32)) +int main(int argc, char* argv[]) { + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + return AetherTom(argv[1]); +} +#endif + +#include "aether/capi.h" + +#define TEST_UID "3ac93165-3d37-4970-87a6-fa4ee27744e4" +char const* message = "Major Tom to ground control"; + +void MessageReceived(AetherClient* client, CUid sender, void const* data, + size_t size, void* user_data) { + printf(">>> Received message size: %zu test: %s\n", size, (char const*)data); + AetherExit(0); +} + +int AetherTom(char const* destination_uid) { + // This init aether library + // Send a message and wait for response + +#ifdef ESP_PLATFORM + AeWifiAdapterConf wifi_adapter_conf = { + .type = AeWifiAdapter, + .ssid = WIFI_SSID, + .password = WIFI_PASSWORD, + }; + AdapterBase* adapter_confs = (AdapterBase*)&wifi_adapter_conf; + Adapters adapters = { + .count = 1, + .adapters = &adapter_confs, + }; +#endif + + ClientConfig client_config = { + .id = "Tom", + .parent_uid = CUidFromString(TEST_UID), + .message_received_cb = MessageReceived, + }; + + AetherConfig aether_config = { +#ifdef ESP_PLATFORM + .adapters = &adapters, +#endif + .default_client = &client_config, + }; + + AetherInit(&aether_config); + SendStr(CUidFromString(destination_uid), message, NULL, NULL); + + while (AetherExcited() == AE_NOK) { + uint64_t time = AetherUpdate(); + AetherWait(time); + } + return AetherEnd(); +} diff --git a/examples/capi/oddity/main.c b/examples/capi/oddity/main.c deleted file mode 100644 index e1dc5b57..00000000 --- a/examples/capi/oddity/main.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2025 Aethernet Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#if (defined(CM_ESP32)) -# include -# include -# include -#endif - -// common main function for ESP and desktops -extern int AetherOddity(char const* destination_uid); - -#if (defined(ESP_PLATFORM)) -extern "C" void app_main(void) { - esp_task_wdt_config_t config_wdt = { - .timeout_ms = 60000, - .idle_core_mask = 0, // i.e. do not watch any idle task - .trigger_panic = true}; - - esp_err_t err = esp_task_wdt_reconfigure(&config_wdt); - if (err != 0) { - fprintf(stderr, "Reconfigure WDT is failed!\n"); - } - - // esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); - // esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(1)); - - AetherOddity(""); -} -#endif - -#if (defined(__linux__) || defined(__unix__) || defined(__APPLE__) || \ - defined(__FreeBSD__) || defined(_WIN64) || defined(_WIN32)) - -int main(int argc, char* argv[]) { - if (argc < 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 1; - } - - return AetherOddity(argv[1]); -} -#endif