新增IDeviceService.SetOnline,WebSocket连接和断开时调用大石头 authored at 2024-07-09 18:44:34
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)
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>
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);
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 设备通道
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>
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
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>