Skip to content

Commit 30726c7

Browse files
Reymerclaude
andcommitted
[新增] EdgeLinkManager 加入設備 timeout 偵測機制與範例更新
- OnDeviceTimeout:超過 deviceTimeoutSeconds 沒收到訊息觸發(TCP/UDP 通用) - OnDeviceReconnected:超時設備重新送資料時觸發 - Inspector 可設定 deviceIdKey 和 deviceTimeoutSeconds - Example.cs 示範三種事件的完整用法 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 610bc3b commit 30726c7

2 files changed

Lines changed: 73 additions & 4 deletions

File tree

SDK/Unity/Package/Runtime/EdgeLinkManager.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,32 @@ public enum Protocol { TCP, TCPListener, UDP }
2323
[HideInInspector] public string kvSeparator = ":";
2424
[HideInInspector] public string outputTemplate = "{raw}";
2525

26+
[Tooltip("訊息中代表設備 ID 的欄位名稱,留空則不追蹤 timeout")]
27+
public string deviceIdKey = "id";
28+
[Tooltip("超過幾秒沒收到訊息視為設備離線(0 = 停用)")]
29+
public float deviceTimeoutSeconds = 20f;
30+
2631
private EdgeLinkClient tcp;
2732
private EdgeLinkTcpListener tcpListener;
2833
private EdgeLinkUdpClient udp;
2934

30-
private readonly Dictionary<string, string> latest = new();
35+
private readonly Dictionary<string, string> latest = new();
36+
private readonly Dictionary<string, float> lastSeenTime = new();
37+
private readonly HashSet<string> timedOut = new();
3138
private readonly System.Collections.Concurrent.ConcurrentQueue<(bool, string)> deviceStatusQueue = new();
3239

3340
public string Raw { get; private set; }
3441

35-
/// <summary>Fired on Unity main thread when an upstream device connects/disconnects.
36-
/// bool = isConnected, string = endpoint (e.g. "TCPServer@192.168.1.50:9001")</summary>
42+
/// <summary>Fired on Unity main thread when an upstream device connects/disconnects (TCP only).
43+
/// bool = isConnected, string = endpoint (e.g. "TCPServer@192.168.1.50")</summary>
3744
public event Action<bool, string> OnDeviceStatus;
3845

46+
/// <summary>Fired on Unity main thread when a device ID stops sending data beyond deviceTimeoutSeconds.</summary>
47+
public event Action<string> OnDeviceTimeout;
48+
49+
/// <summary>Fired on Unity main thread when a previously timed-out device sends data again.</summary>
50+
public event Action<string> OnDeviceReconnected;
51+
3952
public string Get(string key) =>
4053
latest.TryGetValue(key, out string val) ? val : null;
4154

@@ -130,13 +143,37 @@ private void Update()
130143

131144
while (deviceStatusQueue.TryDequeue(out var ds))
132145
OnDeviceStatus?.Invoke(ds.Item1, ds.Item2);
146+
147+
CheckDeviceTimeouts();
148+
}
149+
150+
private void CheckDeviceTimeouts()
151+
{
152+
if (deviceTimeoutSeconds <= 0 || string.IsNullOrEmpty(deviceIdKey)) return;
153+
154+
foreach (var kv in lastSeenTime)
155+
{
156+
bool isTimedOut = Time.time - kv.Value > deviceTimeoutSeconds;
157+
if (isTimedOut && !timedOut.Contains(kv.Key))
158+
{
159+
timedOut.Add(kv.Key);
160+
OnDeviceTimeout?.Invoke(kv.Key);
161+
}
162+
}
133163
}
134164

135165
private void Handle(string msg)
136166
{
137167
Raw = msg;
138168
var parsed = Parse(msg);
139169
foreach (var kv in parsed) latest[kv.Key] = kv.Value;
170+
171+
if (!string.IsNullOrEmpty(deviceIdKey) && parsed.TryGetValue(deviceIdKey, out string deviceId))
172+
{
173+
lastSeenTime[deviceId] = Time.time;
174+
if (timedOut.Remove(deviceId))
175+
OnDeviceReconnected?.Invoke(deviceId);
176+
}
140177
}
141178

142179
private void OnDestroy()

SDK/Unity/Package/Samples~/Basic/Example.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
using UnityEngine;
22

3+
/// <summary>
4+
/// EdgeLink 基本範例 — 多設備資料讀取、斷線偵測
5+
///
6+
/// Inspector 設定:
7+
/// edgeLinkObject → 掛有 EdgeLinkManager 的 GameObject
8+
/// deviceIdKey → 訊息中代表設備 ID 的欄位(預設 "id")
9+
/// deviceTimeout → 超過幾秒沒收到資料視為斷線(預設 20 秒)
10+
/// </summary>
311
public class Example : MonoBehaviour
412
{
513
public GameObject edgeLinkObject;
@@ -10,17 +18,41 @@ public class Example : MonoBehaviour
1018
void Start()
1119
{
1220
edgeLink = edgeLinkObject.GetComponent<EdgeLinkManager>();
21+
22+
// TCP 正常斷線 / 拔電後 ~15 秒偵測到(EdgeLink PING/PONG 超時)
23+
edgeLink.OnDeviceStatus += (connected, endpoint) =>
24+
{
25+
string ip = endpoint.Contains("@") ? endpoint.Split('@')[1] : endpoint;
26+
if (connected)
27+
Debug.Log($"[EdgeLink] 設備上線 IP: {ip}");
28+
else
29+
Debug.LogWarning($"[EdgeLink] 設備斷線 IP: {ip}");
30+
};
31+
32+
// Timeout 偵測:超過 deviceTimeoutSeconds 沒收到訊息(TCP / UDP 通用)
33+
edgeLink.OnDeviceTimeout += deviceId =>
34+
{
35+
Debug.LogWarning($"[EdgeLink] 設備 {deviceId} 超時,可能已離線");
36+
};
37+
38+
// 超時設備重新送資料
39+
edgeLink.OnDeviceReconnected += deviceId =>
40+
{
41+
Debug.Log($"[EdgeLink] 設備 {deviceId} 重新上線");
42+
};
1343
}
1444

1545
void Update()
1646
{
47+
// 只在新訊息到達時處理
1748
if (edgeLink.Raw == lastRaw) return;
1849
lastRaw = edgeLink.Raw;
1950

51+
string id = edgeLink.Get("id");
2052
string temp = edgeLink.Get("temp");
2153
string humid = edgeLink.Get("humid");
2254
string status = edgeLink.Get("status");
2355

24-
Debug.Log($"溫度:{temp} 濕度:{humid} 狀態:{status}");
56+
Debug.Log($"[{id}] 溫度:{temp} 濕度:{humid} 狀態:{status}");
2557
}
2658
}

0 commit comments

Comments
 (0)