嵌入式設備網絡的動態ID分配機制實現

文章目錄

  • 前言
  • 一、系統設計要點
  • 二、核心數據結構
    • 2.1 設備唯一標識(DeviceUID)
    • 2.2 節點信息(Node)
    • 2.3 節點管理器(NodeManager)
  • 三、核心算法實現
    • 3.1 初始化與清理
      • 3.1.1 初始化節點管理器
      • 3.1.2 清理節點管理器
    • 3.2 動態ID分配策略
      • 3.2.1 查找最小可用ID
      • 3.2.2 ID使用檢查
    • 3.3 心跳處理機制
    • 3.4 超時檢測機制
  • 四、節點查找與管理
    • 4.1 通過UID查找節點
    • 4.2 通過ID查找節點
    • 4.3 獲取活躍節點列表
  • 五、回調機制實現
    • 5.1 回調函數注冊
    • 5.2 示例回調函數
  • 六、應用示例
  • 七、總結


前言

在嵌入式設備網絡中,節點的動態加入與退出是常態,尤其是在無人機、傳感器網絡、智能家居等系統中,節點通常無法提前預設 ID,這就要求系統具備動態 ID 分配與管理能力。本篇博客將圍繞“動態 ID 管理”這一核心,介紹一個基于設備 UID 的動態 ID 分配系統,支持重復上線檢測、最小可用 ID 分配、ID 沖突檢測、ID 釋放與復用等功能,代碼完全由 C 語言實現,結構清晰,易于移植與擴展。


一、系統設計要點

該系統以節點唯一標識符 DeviceUID 為基礎,實現了以下關鍵特性:

  • ? 動態 ID 分配:無需提前為設備分配 ID,系統自動為新設備分配最小可用 ID。

  • ? UID 唯一識別機制:通過對 UID 的比較實現節點重復檢測與狀態更新。

  • ? ID 沖突檢測:避免多個設備使用相同 ID 導致狀態混亂。

  • ? ID 釋放與復用:支持節點主動釋放 ID,或超時后自動回收,以復用資源。

  • ? 回調機制:支持注冊上線、下線回調函數,便于系統業務集成。

  • ? 心跳檢測:通過心跳機制維護節點活躍狀態

  • ? 超時處理:自動檢測并清理離線節點

二、核心數據結構

2.1 設備唯一標識(DeviceUID)

typedef struct {uint8_t bytes[6];  // 6字節的唯一設備標識
} DeviceUID;

這個結構體用于存儲設備的唯一標識符,通常可以是MAC地址或其他硬件唯一ID。

2.2 節點信息(Node)

typedef struct Node {uint8_t id;          // 分配的節點IDDeviceUID uid;       // 設備唯一標識uint64_t lastSeenMs; // 最后活躍時間戳(毫秒)struct Node* next;   // 下一個節點指針
} Node;

每個節點包含分配的ID、設備唯一標識、最后活躍時間和指向下一個節點的指針。

2.3 節點管理器(NodeManager)

typedef struct {Node* head;                  // 鏈表頭指針uint8_t activeCount;         // 活躍節點計數NodeOnlineCallback onOnline; // 節點上線回調函數NodeOfflineCallback onOffline; // 節點下線回調函數
} NodeManager;

節點管理器維護所有活躍節點的鏈表,并提供回調函數接口。

三、核心算法實現

3.1 初始化與清理

3.1.1 初始化節點管理器

void NodeManager_Init(NodeManager* manager) {manager->head = NULL;manager->activeCount = 0;manager->onOnline = NULL;manager->onOffline = NULL;
}

3.1.2 清理節點管理器

void NodeManager_Cleanup(NodeManager* manager) {Node* current = manager->head;while (current) {Node* next = current->next;// 回調通知節點離線if (manager->onOffline) {manager->onOffline(current->id, &current->uid);}free(current);current = next;}manager->head = NULL;manager->activeCount = 0;
}

3.2 動態ID分配策略

3.2.1 查找最小可用ID

static uint8_t FindMinAvailableID(NodeManager* manager) {for (uint8_t id = MIN_VALID_ID; id <= MAX_VALID_ID; id++) {if (!IsIDUsed(manager, id)) return id;}return INVALID_ID;
}

該算法從MIN_VALID_ID開始遍歷,返回第一個未被使用的ID。

3.2.2 ID使用檢查

static bool IsIDUsed(NodeManager* manager, uint8_t id) {Node* current = manager->head;while (current) {if (current->id == id) return true;current = current->next;}return false;
}

3.3 心跳處理機制

uint8_t ProcessHeartbeat(NodeManager* manager, uint8_t nodeId, const DeviceUID* uid) {// 1. 檢查是否已有相同UID的節點Node* existing = FindNodeByUID(manager, uid);if (existing) {existing->lastSeenMs = GetSysTimeMs(); // 更新活躍時間return existing->id;}// 2. 檢查請求的ID是否已被占用if (nodeId != INVALID_ID && FindNodeByID(manager, nodeId)) {nodeId = INVALID_ID; // 如果已被占用,則重置為無效ID}// 3. 分配新IDif (nodeId == INVALID_ID) {nodeId = FindMinAvailableID(manager);if (nodeId == INVALID_ID) return INVALID_ID; // 無可用ID}// 4. 添加新節點return AddNode(manager, nodeId, uid) ? nodeId : INVALID_ID;
}
  • 心跳處理流程

    1. 如果是已知節點,更新其活躍時間

    2. 如果是新節點,檢查請求ID是否可用

    3. 分配最小可用ID

    4. 添加新節點到管理器

3.4 超時檢測機制

void CheckTimeoutNodes(NodeManager* manager) {uint64_t now = GetSysTimeMs();Node** pnode = &manager->head;while (*pnode) {Node* current = *pnode;if ((now - current->lastSeenMs) > HEARTBEAT_TIMEOUT) {*pnode = current->next; // 從鏈表中移除// 回調通知節點離線if (manager->onOffline) {manager->onOffline(current->id, &current->uid);}free(current); // 釋放節點內存manager->activeCount--;} else {pnode = &(*pnode)->next;}}
}

該函數遍歷所有節點,檢查最后活躍時間是否超時,超時則移除節點并觸發下線回調。

四、節點查找與管理

4.1 通過UID查找節點

static Node* FindNodeByUID(NodeManager* manager, const DeviceUID* uid) {Node* current = manager->head;while (current) {if (CompareDeviceUID(&current->uid, uid)) return current;current = current->next;}return NULL;
}

4.2 通過ID查找節點

static Node* FindNodeByID(NodeManager* manager, uint8_t id) {Node* current = manager->head;while (current) {if (current->id == id) return current;current = current->next;}return NULL;
}

4.3 獲取活躍節點列表

uint8_t GetActiveNodeIDs(NodeManager* manager, uint8_t* outputBuffer, uint8_t bufferSize) {uint8_t count = 0;Node* current = manager->head;while (current && count < bufferSize) {outputBuffer[count++] = current->id;current = current->next;}qsort(outputBuffer, count, sizeof(uint8_t), CompareNodeIDs);return count;
}

五、回調機制實現

5.1 回調函數注冊

void NodeManager_RegisterCallbacks(NodeManager* manager, NodeOnlineCallback onOnline, NodeOfflineCallback onOffline) {manager->onOnline = onOnline;manager->onOffline = onOffline;
}

5.2 示例回調函數

void OnNodeOnline(uint8_t id, const DeviceUID* uid) {printf("[Callback] Node %d is ONLINE!\n", id);
}void OnNodeOffline(uint8_t id, const DeviceUID* uid) {printf("[Callback] Node %d is OFFLINE!\n", id);
}

六、應用示例

void TestNodeManager() {NodeManager manager;NodeManager_Init(&manager);// 注冊回調NodeManager_RegisterCallbacks(&manager, OnNodeOnline, OnNodeOffline);// 模擬設備UIDDeviceUID uid1 = {{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}};DeviceUID uid2 = {{0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB}};// 節點上線ProcessHeartbeat(&manager, 1, &uid1);  // 指定ID=1ProcessHeartbeat(&manager, INVALID_ID, &uid2);  // 自動分配ID// 打印活躍節點PrintActiveNodes(&manager);// 模擬超時printf("\nSimulating timeout...\n");GetSysTimeMs();  // 模擬時間流逝CheckTimeoutNodes(&manager);PrintActiveNodes(&manager);// 主動釋放節點printf("\nManually releasing node...\n");ReleaseNodeID(&manager, 2);PrintActiveNodes(&manager);// 清理NodeManager_Cleanup(&manager);
}

七、總結

本文詳細介紹了一個高效的動態ID管理系統的設計與實現,該系統具有以下優點:

  • 靈活性:支持動態ID分配和釋放

  • 可靠性:通過心跳機制確保節點狀態準確

  • 可擴展性:易于添加新功能如安全驗證等

  • 低開銷:內存占用小,適合嵌入式環境

  • 事件驅動:通過回調機制實現松耦合

這種動態ID管理方案非常適合物聯網設備、傳感器網絡等需要管理大量動態節點的嵌入式應用場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901966.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901966.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901966.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WebSocket 雙向通信技術詳解

引言 在現代Web應用中&#xff0c;實時通信已經成為不可或缺的一部分。想象一下聊天應用、在線游戲、股票交易平臺或協作工具&#xff0c;這些應用都需要服務器能夠即時將更新推送給客戶端&#xff0c;而不僅僅是等待客戶端請求。WebSocket技術應運而生&#xff0c;它提供了一…

kafka菜鳥教程

一、kafka原理 1、kafka是一個高性能的消息隊列系統&#xff0c;能夠處理大規模的數據流&#xff0c;并提供低延遲的數據傳輸&#xff0c;它能夠以每秒數十萬條消息的速度進行讀寫操作。 二、kafka優點 1、服務解耦 &#xff08;1&#xff09;提高系統的可維護性? 通過服務…

SQLMap工具使用

一、SQLMap介紹 SQLMap 是一款強大的開源自動化 SQL 注入工具&#xff0c;用于檢測和利用 Web 應用程序中的 SQL 注入漏洞。其工作原理是SQLMap 通過向目標 URL 發送帶有特殊構造的 SQL 語句的請求&#xff0c;觀察目標應用程序的響應&#xff0c;來判斷是否存在 SQL 注入漏洞…

virtualbox安裝xp系統卡頓的解決

安裝virtualbox的增強功能即可。 先去下載 — Oracle VirtualBox下載 VirtualBox Guest Additions iso鏡像 然后在這里導入iso鏡像 再按照這幾步操作 virtualbox按鍵 強制關閉xp-cuckoo的虛擬機 VBoxManage controlvm "xp-cuckoo" poweroff

觀察者 ? 事件總線:一路走來的碎碎念

寫給未來的自己:每次手敲事件模型都要 Google,干脆把思路和踩坑一次性記清楚。文章很長,都是嘮叨,目的是讓自己看兩眼就能把設計理由找回來。 目錄 為什么我要折騰事件模型?V0 ─ 單一事件的觀察者模式V1 ─ 多事件同步總線(類型拆分)V2 ─ 訂閱者優先級(鏈式調用可控)…

windwos腳本 | 基于scrcpy,只投聲音、只投畫面

安裝scrcpy&#xff0c;scrcpy自帶adb 寫腳本命名為 .bat 結尾 注意這里的set "PATHD:\tools\scrcpy-win64-v3.2;%PATH%" 替換成scrcpy的安裝目錄 echo off :: 設置UTF-8編碼 chcp 65001 > nul :: 設置標題 title 手機投屏工具:: 添加 scrcpy 路徑到 PATH set &q…

Android device PCO (protocol configuration options) intro

術語 英文縮寫英文全稱中文PCOprotocol configuration options協議配置選項RILradio interface layer 無線電接口層PCO介紹 PCO(Protocol Configuration Options) 是 3GPP 標準協議(TS 24.008)中定義的核心概念,用于在 LTE/5G 網絡建立 PDN 連接時傳遞動態配置參數(如 D…

Spring Boot配置文件優先級全解析:如何優雅覆蓋默認配置?

&#x1f4da; 一、為什么需要了解配置文件優先級&#xff1f; 想象一下&#xff0c;你正在玩一個游戲&#x1f3ae;&#xff0c;游戲里有默認設置&#xff0c;但你可以通過不同的方式修改這些設置&#xff1a; 游戲內置的默認設置&#xff08;就像Spring Boot的默認配置&…

汽車行駛工況特征參數:從“速度曲線”到“駕駛DNA”的硬核解碼

作為新能源汽車行業的從業者&#xff0c;你是否曾困惑于這些問題&#xff1a; 為什么同一款電動車&#xff0c;不同用戶的實際續航差異高達30%&#xff1f;如何精準量化駕駛行為對電池壽命的影響&#xff1f;車企標定的“NEDC續航”與真實路況差距的根源是什么&#xff1f; 這…

HTTP 2.0 協議特性詳解

1. 使用二進制協議&#xff0c;簡化傳輸的復雜性&#xff0c;提高了效率 2. 支持一個 TCP 鏈接發起多請求&#xff0c;移除 pipeline HTTP/2 移除了 HTTP/1.1中的管道化&#xff08;pipeline&#xff09;機制&#xff0c;轉而采用多路復用&#xff08;Multiplexing&#xff0…

完美解決瀏覽器不能復制的問題(比如賽氪網的中題庫練習題)

僅供復制題庫題目進行打印學習使用&#xff01; 最近想把賽氪網題庫中的題目打印出來做練習&#xff0c;發現題庫中的題目不能復制&#xff0c;不能在試卷上勾畫標記太難受了&#xff0c;而且不能留作材料以后復習&#xff0c;故出此策。 而且CtrlP打印出的pdf會缺少題目。(我…

std::set (C++)

std::set 1. 概述定義特點 2. 內部實現3. 性能特征4. 常用 API5. 使用示例6. 自定義比較器7. 注意事項與優化8. 使用建議 1. 概述 定義 template<class Key,class Compare std::less<Key>,class Allocator std::allocator<Key> > class std::set;特點 有…

SSM省市區三級聯動和三表聯查附帶數據庫

SSM省市區三級聯動和三表聯查 ------附帶數據庫碼云地址&#xff1a;https://gitee.com/Mr_ZKC/NO1 數據庫在項目中

曲棍球·棒球1號位

中國女子曲棍球隊曾涌現過馬弋博、李紅俠等優秀選手&#xff0c;但“李紅”這一名字可能為信息誤差。以下為您系統介紹曲棍球&#xff0c;并結合棒球進行對比分析&#xff1a; 曲棍球&#xff08;Hockey&#xff09;核心特點 運動形式 分為草地曲棍球&#xff08;夏季奧運會項…

12芯束裝光纖不同包層線顏色之間的排列順序

為什么光纖線必須按照以下顏色順序進行排序&#xff1f;這其實是為了防止光污染的問題&#xff0c;不同顏色在傳遞光時從包層表皮漏光傳感到梳妝的其它纖芯上&#xff0c;會有光污染的問題&#xff0c;而為了減少并防止光污染的現象&#xff0c;所以在光通信之中&#xff0c;需…

c++程序的打包編譯cmake+make

c打包編譯 1 在不用系統中打包介紹1.1 linux中打包c程序的2種方式1.2 windows中打包c程序1.3 cmakeNinja和cmakemake的兩種方式對比1.3.1 Ninja是什么&#xff08;可以認為是make工具的一個替代產品&#xff09;1.3.2 cmakeNinja可以用于linux和windows系統中&#xff0c;編譯效…

Spark on K8s 在 vivo 大數據平臺的混部實戰與優化

一、Spark on K8s 簡介 (一)定義與架構 Spark on K8s 是一種將 Spark 運行在 Kubernetes(K8s)集群上的架構,由 K8s 直接創建 Driver 和 Executor 的 Pod 來運行 Spark 作業。其架構如下。 Driver Pod:相當于 Spark 集群中的 Driver,負責作業的調度和管理,它會根據作業…

MDA測量數據查看器【內含工具和源碼地址】

一、工具介紹 MDA測量數據查看器用于顯示和分析以MDF格式提供的測量數據。 支持MDF3.3之前含MDF3.3的二進制格式&#xff0c;支持Vector CANape and ETAS Inca. Kvaser CAN Logger (MDF 3.2) 文件。 MDF (Measurement Data Format)是一種二進制文件&#xff0c;用來記錄、交換…

番外篇 | SEAM-YOLO:引入SEAM系列注意力機制,提升遮擋小目標的檢測性能

前言:Hello大家好,我是小哥談。SEAM(Squeeze-and-Excitation Attention Module)系列注意力機制是一種高效的特征增強方法,特別適合處理遮擋和小目標檢測問題。該機制通過建模通道間關系來自適應地重新校準通道特征響應。在遮擋小目標檢測中的應用優勢包括:1)通道注意力增強…