NewLife/NewLife.Remoting

新增IDeviceService.SetOnline,WebSocket连接和断开时调用
大石头 authored at 2024-07-09 18:44:34
79c3d08
Tree
1 Parent(s) fd76e99
Summary: 7 changed files with 89 additions and 75 deletions.
Modified +22 -3
Modified +8 -0
Modified +9 -0
Modified +1 -36
Modified +24 -0
Modified +1 -36
Modified +24 -0
Modified +22 -3
diff --git a/NewLife.Remoting.Extensions/Controllers/BaseDeviceController.cs b/NewLife.Remoting.Extensions/Controllers/BaseDeviceController.cs
index c0f0827..6a20dbf 100644
--- a/NewLife.Remoting.Extensions/Controllers/BaseDeviceController.cs
+++ b/NewLife.Remoting.Extensions/Controllers/BaseDeviceController.cs
@@ -1,6 +1,5 @@
 using System.Net;
 using System.Net.WebSockets;
-using System.Xml.Linq;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using NewLife.Caching;
@@ -8,6 +7,7 @@ using NewLife.Http;
 using NewLife.Log;
 using NewLife.Remoting.Extensions.Services;
 using NewLife.Remoting.Models;
+using NewLife.Security;
 using NewLife.Serialization;
 using WebSocket = System.Net.WebSockets.WebSocket;
 using WebSocketMessageType = System.Net.WebSockets.WebSocketMessageType;
@@ -202,14 +202,33 @@ public class BaseDeviceController : BaseController
         var device = _device ?? throw new InvalidOperationException("未登录!");
 
         var ip = UserHost;
-        WriteLog("WebSocket连接", true, socket.State + "");
+        var sid = Rand.Next();
+        WriteLog("WebSocket连接", true, $"State={socket.State} sid={sid}");
+
+        // 长连接上线
+        _deviceService.SetOnline(device, true, token, ip);
 
         var source = new CancellationTokenSource();
         var queue = _deviceService.GetQueue(device.Code);
         //_ = Task.Run(() => socket.ConsumeAndPushAsync(queue, onProcess: null, source));
         _ = Task.Run(() => ConsumeMessage(socket, device.Code, queue, ip, source));
 
-        await socket.WaitForClose(null, source);
+        //await socket.WaitForClose(null, source);
+        await socket.WaitForClose(txt =>
+        {
+            if (txt == "Ping")
+            {
+                socket.SendAsync("Pong".GetBytes(), WebSocketMessageType.Text, true, source.Token);
+
+                // 长连接上线。可能客户端心跳已经停了,WS还在,这里重新上线
+                _deviceService.SetOnline(device, true, token, ip);
+            }
+        }, source);
+
+        WriteLog("WebSocket断开", true, $"State={socket.State} CloseStatus={socket.CloseStatus} sid={sid}");
+
+        // 长连接下线
+        _deviceService.SetOnline(device, false, token, ip);
     }
 
     private async Task ConsumeMessage(WebSocket socket, String code, IProducerConsumer<String> queue, String ip, CancellationTokenSource source)
Modified +8 -0
diff --git a/NewLife.Remoting.Extensions/Services/IDeviceService.cs b/NewLife.Remoting.Extensions/Services/IDeviceService.cs
index 7fcf6cc..63ccdc3 100644
--- a/NewLife.Remoting.Extensions/Services/IDeviceService.cs
+++ b/NewLife.Remoting.Extensions/Services/IDeviceService.cs
@@ -38,6 +38,14 @@ public interface IDeviceService
     /// <returns></returns>
     IOnlineModel Ping(IDeviceModel device, IPingRequest? request, String? token, String ip);
 
+    /// <summary>设置设备的长连接上线/下线</summary>
+    /// <param name="device"></param>
+    /// <param name="online"></param>
+    /// <param name="token"></param>
+    /// <param name="ip"></param>
+    /// <returns></returns>
+    IOnlineModel SetOnline(IDeviceModel device, Boolean online, String token, String ip);
+
     /// <summary>命令响应</summary>
     /// <param name="device"></param>
     /// <param name="model"></param>
Modified +9 -0
diff --git a/Samples/IoTZero/Areas/IoT/Controllers/DeviceHistoryController.cs b/Samples/IoTZero/Areas/IoT/Controllers/DeviceHistoryController.cs
index 1da5870..05b6b01 100644
--- a/Samples/IoTZero/Areas/IoT/Controllers/DeviceHistoryController.cs
+++ b/Samples/IoTZero/Areas/IoT/Controllers/DeviceHistoryController.cs
@@ -1,5 +1,6 @@
 using IoT.Data;
 using NewLife.Cube;
+using NewLife.Cube.Extensions;
 using NewLife.Web;
 using XCode.Membership;
 
@@ -9,6 +10,14 @@ namespace IoTZero.Areas.IoT.Controllers;
 [Menu(60, true)]
 public class DeviceHistoryController : ReadOnlyEntityController<DeviceHistory>
 {
+    static DeviceHistoryController()
+    {
+        ListFields.RemoveField("Id");
+        ListFields.AddListField("Remark", null, "Success");
+
+        ListFields.TraceUrl();
+    }
+
     protected override IEnumerable<DeviceHistory> Search(Pager p)
     {
         var deviceId = p["deviceId"].ToInt(-1);
Modified +1 -36
diff --git a/Samples/IoTZero/Controllers/DeviceController.cs b/Samples/IoTZero/Controllers/DeviceController.cs
index c358f9b..cd9d5ea 100644
--- a/Samples/IoTZero/Controllers/DeviceController.cs
+++ b/Samples/IoTZero/Controllers/DeviceController.cs
@@ -1,5 +1,4 @@
-using System.Net.WebSockets;
-using IoT.Data;
+using IoT.Data;
 using IoTZero.Services;
 using Microsoft.AspNetCore.Mvc;
 using NewLife.IoT.Drivers;
@@ -66,40 +65,6 @@ public class DeviceController : BaseDeviceController
 
         return rs;
     }
-
-    /// <summary>长连接处理</summary>
-    /// <param name="socket"></param>
-    /// <param name="token"></param>
-    /// <returns></returns>
-    protected override async Task HandleNotify(WebSocket socket, String token)
-    {
-        DeviceOnline online = null;
-        var device = Device;
-        if (device != null)
-        {
-            // 上线打标记
-            online = _deviceService.GetOnline(device, UserHost);
-            if (online != null)
-            {
-                online.WebSocket = true;
-                online.Update();
-            }
-        }
-
-        try
-        {
-            await base.HandleNotify(socket, token);
-        }
-        finally
-        {
-            // 下线清除标记
-            if (online != null)
-            {
-                online.WebSocket = false;
-                online.Update();
-            }
-        }
-    }
     #endregion
 
     #region 设备通道
Modified +24 -0
diff --git a/Samples/IoTZero/Services/MyDeviceService.cs b/Samples/IoTZero/Services/MyDeviceService.cs
index e94eb4f..805ff2a 100644
--- a/Samples/IoTZero/Services/MyDeviceService.cs
+++ b/Samples/IoTZero/Services/MyDeviceService.cs
@@ -244,6 +244,30 @@ public class MyDeviceService : IDeviceService
         return olt;
     }
 
+    /// <summary>设置设备的长连接上线/下线</summary>
+    /// <param name="device"></param>
+    /// <param name="online"></param>
+    /// <param name="token"></param>
+    /// <param name="ip"></param>
+    /// <returns></returns>
+    public IOnlineModel SetOnline(IDeviceModel device, Boolean online, String token, String ip)
+    {
+        if (device is Device dv)
+        {
+            // 上线打标记
+            var olt = GetOnline(dv, ip);
+            if (olt != null)
+            {
+                olt.WebSocket = online;
+                olt.Update();
+            }
+
+            return olt;
+        }
+
+        return null;
+    }
+
     /// <summary></summary>
     /// <param name="device"></param>
     /// <param name="ip"></param>
Modified +1 -36
diff --git a/Samples/ZeroServer/Controllers/NodeController.cs b/Samples/ZeroServer/Controllers/NodeController.cs
index 37915ff..d86fb21 100644
--- a/Samples/ZeroServer/Controllers/NodeController.cs
+++ b/Samples/ZeroServer/Controllers/NodeController.cs
@@ -1,5 +1,4 @@
-using System.Net.WebSockets;
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc;
 using NewLife.Log;
 using NewLife.Remoting;
 using NewLife.Remoting.Extensions;
@@ -65,38 +64,4 @@ public class NodeController : BaseDeviceController
 
         return rs;
     }
-
-    /// <summary>长连接处理</summary>
-    /// <param name="socket"></param>
-    /// <param name="token"></param>
-    /// <returns></returns>
-    protected override async Task HandleNotify(WebSocket socket, String token)
-    {
-        NodeOnline online = null;
-        var node = Node;
-        if (node != null)
-        {
-            // 上线打标记
-            online = _nodeService.GetOnline(node, UserHost);
-            if (online != null)
-            {
-                online.WebSocket = true;
-                online.Update();
-            }
-        }
-
-        try
-        {
-            await base.HandleNotify(socket, token);
-        }
-        finally
-        {
-            // 下线清除标记
-            if (online != null)
-            {
-                online.WebSocket = false;
-                online.Update();
-            }
-        }
-    }
 }
\ No newline at end of file
Modified +24 -0
diff --git a/Samples/ZeroServer/Services/NodeService.cs b/Samples/ZeroServer/Services/NodeService.cs
index 535e7a7..69d7d3a 100644
--- a/Samples/ZeroServer/Services/NodeService.cs
+++ b/Samples/ZeroServer/Services/NodeService.cs
@@ -208,6 +208,30 @@ public class NodeService : IDeviceService
         return online;
     }
 
+    /// <summary>设置设备的长连接上线/下线</summary>
+    /// <param name="device"></param>
+    /// <param name="online"></param>
+    /// <param name="token"></param>
+    /// <param name="ip"></param>
+    /// <returns></returns>
+    public IOnlineModel SetOnline(IDeviceModel device, Boolean online, String token, String ip)
+    {
+        if (device is Node node)
+        {
+            // 上线打标记
+            var olt = GetOnline(node, ip);
+            if (olt != null)
+            {
+                olt.WebSocket = online;
+                olt.Update();
+            }
+
+            return olt;
+        }
+
+        return null;
+    }
+
     /// <summary></summary>
     /// <param name="node"></param>
     /// <param name="ip"></param>