diff --git a/DeviceAdapter/DeviceAdapter.cs b/DeviceAdapter/DeviceAdapter.cs
index a4a0bde..35e05dd 100644
--- a/DeviceAdapter/DeviceAdapter.cs
+++ b/DeviceAdapter/DeviceAdapter.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
@@ -228,6 +230,7 @@ namespace Mesnac.DeviceAdapter
/// 1成功,2为通讯成功,设备未返回,3为发送失败
byte Device_SendHeartPack();
+ Task Device_SendHeartPackAsync(CancellationToken cancellationToken = default);
///
/// 获取自报数据
///
diff --git a/HighWayAssemble/App.config b/HighWayAssemble/App.config
index 2ff0ef7..906dfec 100644
--- a/HighWayAssemble/App.config
+++ b/HighWayAssemble/App.config
@@ -9,7 +9,7 @@
-
+
diff --git a/HighWayAssemble/HighWayAssemble.csproj b/HighWayAssemble/HighWayAssemble.csproj
index 86c8731..167ef6d 100644
--- a/HighWayAssemble/HighWayAssemble.csproj
+++ b/HighWayAssemble/HighWayAssemble.csproj
@@ -38,6 +38,9 @@
cloud_computing_128px_1222169_easyicon.net.ico
+
+
+
dll\CatLib.Core.dll
diff --git a/HighWayAssemble/Main/EventSystem.cs b/HighWayAssemble/Main/EventSystem.cs
index f1d1b2c..f9a0aaf 100644
--- a/HighWayAssemble/Main/EventSystem.cs
+++ b/HighWayAssemble/Main/EventSystem.cs
@@ -11,6 +11,7 @@
// public static string GetMesEquipList = "GetMesEquipList";
public static string UpdateMesListInfo = "UpdateMesListInfo";
+ public static string updateEquipListInfoasyc = "updateEquipListInfoasyc";
public static string updateEquipListInfo = "updateEquipListInfo";
public static string updateSensorListInfo = "updateSensorListInfo";
diff --git a/HighWayAssemble/Main/FrmDisplayControl.cs b/HighWayAssemble/Main/FrmDisplayControl.cs
index 54c1667..f6eb447 100644
--- a/HighWayAssemble/Main/FrmDisplayControl.cs
+++ b/HighWayAssemble/Main/FrmDisplayControl.cs
@@ -137,6 +137,7 @@ namespace HighWayAssemble
App.TriggerHalt(EventSystem.AppClosed);
App.Off(EventSystem.UpdateViewList);
App.Off(EventSystem.UpdateMesListInfo);
+ App.Off(EventSystem.updateEquipListInfoasyc);
App.Off(EventSystem.updateEquipListInfo);
App.Off(EventSystem.updateSensorListInfo);
App.Off(EventSystem.MessageBox);
@@ -161,6 +162,11 @@ namespace HighWayAssemble
{
view.UpdateMesListView(mesinfo);
});
+ App.On(EventSystem.updateEquipListInfoasyc, (DeviceInfo state) =>
+ {
+ view.equipState(state.m_iDeviceId.ToString(), state.m_ConnectState);
+
+ });
App.On(EventSystem.updateEquipListInfo, (List state) =>
{
for (int i = 0; i < state.Count; i++)
diff --git a/HighWayAssemble/Main/FrmDisplayModel.cs b/HighWayAssemble/Main/FrmDisplayModel.cs
index 1f67499..298b60f 100644
--- a/HighWayAssemble/Main/FrmDisplayModel.cs
+++ b/HighWayAssemble/Main/FrmDisplayModel.cs
@@ -329,8 +329,14 @@ namespace HighWayAssemble
//发送传感器
m_EquipClient.SensorInfo(SoftInfo.SensorList);
m_EquipClient.Init();
- //设备状态回调
- m_EquipClient.RecEquipState(async (state) =>
+ m_EquipClient.RecEquipStateasyc(async (state) =>
+ {
+ App.TriggerHalt(EventSystem.updateEquipListInfoasyc, state);
+
+
+ });
+ //设备状态回调
+ m_EquipClient.RecEquipState(async (state) =>
{
App.TriggerHalt(EventSystem.updateEquipListInfo, state);
for (int i = 0; i < state.Count; i++)
diff --git a/HighWayAssemble/Protocol/MesHttpClient.cs b/HighWayAssemble/Protocol/MesHttpClient.cs
index 2d8f52a..486c0df 100644
--- a/HighWayAssemble/Protocol/MesHttpClient.cs
+++ b/HighWayAssemble/Protocol/MesHttpClient.cs
@@ -45,7 +45,7 @@ namespace HighWayAssemble.Protocol
}
catch (Exception ex)
{
- FrmDisplayView.LogInfo.Error("ERROR: " + ex.Message);
+ FrmDisplayView.LogInfo.Fatal("MES接口连接异常: " + ex.Message);
}
}
@@ -63,7 +63,7 @@ namespace HighWayAssemble.Protocol
}
catch (Exception ex)
{
- FrmDisplayView.LogInfo.Error("ERROR: " + ex.Message);
+ FrmDisplayView.LogInfo.Fatal("MES接口调用异常: " + ex.Message);
return null;
}
}
diff --git a/Highway.Assemble.EquipClient/ConcurrentDeviceHeartbeatManager.cs b/Highway.Assemble.EquipClient/ConcurrentDeviceHeartbeatManager.cs
new file mode 100644
index 0000000..8c10fa3
--- /dev/null
+++ b/Highway.Assemble.EquipClient/ConcurrentDeviceHeartbeatManager.cs
@@ -0,0 +1,238 @@
+using log4net.Core;
+using Mesnac.DeviceAdapter.RFly_I160;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Highway.Assemble.EquipClient
+{
+ using Highway.Assemble.common;
+ using Mesnac.DeviceAdapterNet;
+ using System;
+ using System.Collections.Concurrent;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ public class DeviceHeartbeatManager : IDisposable
+ {
+ private readonly ConcurrentDictionary _deviceTokens =
+ new ConcurrentDictionary();
+
+ private List _deviceIds;
+ private readonly SemaphoreSlim _concurrencySemaphore;
+ private readonly int _heartbeatIntervalMs;
+ private readonly int _timeoutMs;
+ private readonly ILogger _logger;
+ private readonly Func _createHeartbeatMessage;
+ private readonly Func> _sendMessageAsync;
+ private readonly Action _handleResult;
+ private Timer _heartbeatTimer;
+ private bool _isDisposed;
+
+ public DeviceHeartbeatManager(
+ int maxConcurrentDevices = 10,
+ int heartbeatIntervalMs = 2000,
+ int timeoutMs = 2000,
+ ILogger logger = null,
+ Func createHeartbeatMessage = null,
+ Func> sendMessageAsync = null,
+ Action handleResult = null)
+ {
+ _concurrencySemaphore = new SemaphoreSlim(maxConcurrentDevices);
+ _heartbeatIntervalMs = heartbeatIntervalMs;
+ _timeoutMs = timeoutMs;
+ _logger = logger ?? new NullLogger();
+ _createHeartbeatMessage = createHeartbeatMessage ?? CreateDefaultHeartbeatMessage;
+ _sendMessageAsync = sendMessageAsync ?? ((id, msg) => Task.FromResult(false));
+ _handleResult = handleResult ?? ((id, result) => { });
+ }
+
+ public void StartMonitoring(List deviceIds)
+ {
+ if (_heartbeatTimer != null)
+ throw new InvalidOperationException("Heartbeat manager is already running.");
+
+ _deviceIds = deviceIds;
+
+ // 创建定时器,使用固定间隔触发心跳周期
+ _heartbeatTimer = new Timer(
+ callback: ExecuteHeartbeatCycle,
+ state: null,
+ dueTime: 0,
+ period: _heartbeatIntervalMs);
+ }
+
+ public void StopMonitoring()
+ {
+ if (_heartbeatTimer == null)
+ return;
+
+ _heartbeatTimer.Dispose();
+ _heartbeatTimer = null;
+
+ // 取消所有正在执行的设备任务
+ foreach (var cts in _deviceTokens.Values)
+ {
+ cts.Cancel();
+ cts.Dispose();
+ }
+ _deviceTokens.Clear();
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_isDisposed)
+ return;
+
+ if (disposing)
+ {
+ StopMonitoring();
+ _concurrencySemaphore.Dispose();
+ }
+
+ _isDisposed = true;
+ }
+
+ private async void ExecuteHeartbeatCycle(object state)
+ {
+ try
+ {
+ var cycleStartTime = DateTime.UtcNow;
+ _logger.Debug($"Starting heartbeat cycle at {cycleStartTime:O}");
+
+ // 为每个设备创建独立的取消令牌
+ var deviceTasks = new List();
+ foreach (var deviceId in _deviceIds)
+ {
+ var cts = new CancellationTokenSource();
+ _deviceTokens.AddOrUpdate(deviceId.m_iDeviceId.ToString(), cts, (key, oldValue) => { oldValue.Dispose(); return cts; });
+
+ deviceTasks.Add(SendHeartbeatAsync(deviceId.m_iDeviceId.ToString(), cts.Token));
+ }
+
+ // 并发执行所有设备的心跳任务
+ await Task.WhenAll(deviceTasks);
+
+ var cycleDuration = (DateTime.UtcNow - cycleStartTime).TotalMilliseconds;
+ _logger.Debug($"Heartbeat cycle completed in {cycleDuration:F2}ms");
+ }
+ catch (OperationCanceledException)
+ {
+ _logger.Info("Heartbeat cycle was canceled.");
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"Exception in heartbeat cycle: {ex.Message}");
+ }
+ }
+
+ private async Task SendHeartbeatAsync(string deviceId, CancellationToken cancellationToken)
+ {
+ await _concurrencySemaphore.WaitAsync(cancellationToken);
+
+ try
+ {
+ var startTime = DateTime.UtcNow;
+ _logger.Debug($"Sending heartbeat to device {deviceId} at {startTime:O}");
+
+ var message = _createHeartbeatMessage(deviceId);
+ var result = await SendWithTimeoutAsync(deviceId, message, cancellationToken);
+
+ _handleResult(deviceId, result);
+
+ var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
+ _logger.Debug($"Heartbeat to device {deviceId} processed in {elapsed:F2}ms");
+ }
+ catch (OperationCanceledException)
+ {
+ _handleResult(deviceId, 2); // 操作取消
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"Exception sending heartbeat to device {deviceId}: {ex.Message}");
+ _handleResult(deviceId, 2); // 发生异常
+ }
+ finally
+ {
+ _concurrencySemaphore.Release();
+
+ // 清理完成的任务令牌
+ if (_deviceTokens.TryGetValue(deviceId, out var cts) && !cts.IsCancellationRequested)
+ {
+ cts.Dispose();
+ _deviceTokens.TryRemove(deviceId, out _);
+ }
+ }
+ }
+
+ private async Task SendWithTimeoutAsync(string deviceId, MessagePack message, CancellationToken cancellationToken)
+ {
+ using (var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
+ {
+ timeoutCts.CancelAfter(_timeoutMs);
+
+ try
+ {
+ var sendTask = _sendMessageAsync(deviceId, message);
+ var completedTask = await Task.WhenAny(sendTask, Task.Delay(Timeout.Infinite, timeoutCts.Token));
+
+ if (completedTask == sendTask)
+ {
+ return await sendTask ? (byte)1 : (byte)2;
+ }
+
+ _logger.Warn($"Heartbeat to device {deviceId} timed out after {_timeoutMs}ms");
+ return 0; // 超时
+ }
+ catch (OperationCanceledException) when (timeoutCts.IsCancellationRequested)
+ {
+ _logger.Warn($"Heartbeat to device {deviceId} timed out after {_timeoutMs}ms");
+ return 0; // 超时
+ }
+ }
+ }
+
+ private MessagePack CreateDefaultHeartbeatMessage(string deviceId)
+ {
+ return new MessagePack
+ {
+ m_pData = new byte[9] { 0xAA, 0x55, 0x00, 0x90, 0x90, 0x0D, 0x00, 0x00, 0x0D }
+ };
+ }
+ }
+
+ // 简单的日志接口实现
+ public interface ILogger
+ {
+ void Debug(string message);
+ void Info(string message);
+ void Warn(string message);
+ void Error(string message);
+ }
+
+ public class NullLogger : ILogger
+ {
+ public void Debug(string message) { }
+ public void Info(string message) { }
+ public void Warn(string message) { }
+ public void Error(string message) { }
+ }
+
+ // 消息包结构
+ public class MessagePack
+ {
+ public byte[] m_pData { get; set; }
+ }
+}
diff --git a/Highway.Assemble.EquipClient/EquipClient.cs b/Highway.Assemble.EquipClient/EquipClient.cs
index 527d369..ae9db79 100644
--- a/Highway.Assemble.EquipClient/EquipClient.cs
+++ b/Highway.Assemble.EquipClient/EquipClient.cs
@@ -19,6 +19,9 @@ namespace Highway.Assemble.EquipClient
public Action> EquipStateAction;
+ public Action EquipStateActionasyc;
+
+
public Action> ReadDataAction;
public Action> RecSendDataAction;
@@ -129,15 +132,242 @@ namespace Highway.Assemble.EquipClient
LogInfo.Info("设备信息表为空!");
return;
}
+
m_bgwDeviceDetect.DoWork += bgwDeviceDetect_DoWork;
m_bgwDeviceDetect.RunWorkerAsync(this);
}
+ //private void test()
+ //{
+ // // 创建心跳管理器实例
+ // var manager = new DeviceHeartbeatManager(
+ // maxConcurrentDevices: 10, // 最大并发设备数
+ // heartbeatIntervalMs: 2000, // 心跳间隔(毫秒)
+ // timeoutMs: 2000, // 超时时间(毫秒)
+ // sendMessageAsync: async (deviceId, message) =>
+ // {
+ // // 实际发送心跳包的逻辑
+ // try
+ // {
+ // // 这里调用你的通信服务发送消息
+ // return await YourCommunicationService.SendAsync(deviceId, message);
+ // }
+ // catch
+ // {
+ // return false;
+ // }
+ // },
+ // handleResult: (deviceId, result) =>
+ // {
+ // // 处理心跳结果
+ // switch (result)
+ // {
+ // case 0: Console.WriteLine($"Device {deviceId} timed out"); break;
+ // case 1: Console.WriteLine($"Device {deviceId} is online"); break;
+ // case 2: Console.WriteLine($"Device {deviceId} communication error"); break;
+ // }
+ // }
+ // );
+
+ // // 添加设备进行监控
+
+ // manager.StartMonitoring(m_DeviceInfoList);
+
+ // // 稍后停止监控
+ // // manager.StopMonitoring();
+ //}
+
+ private async void bgwDeviceDetect_DoWork(object sender, DoWorkEventArgs e)
+ {
+ BackgroundWorker backgroundworker = sender as BackgroundWorker;
+ CancellationTokenSource cts = new CancellationTokenSource();
+ const int DETECTION_INTERVAL_MS = 30000; // 检测间隔1分钟
+
+ try
+ {
+ // 记录下一次检测的时间点
+ DateTime nextDetectionTime = DateTime.Now.AddMilliseconds(DETECTION_INTERVAL_MS);
+
+ while (!ExitEvent.WaitOne(0, exitContext: false))
+ {
+ try
+ {
+ Console.WriteLine(DateTime.Now+"开始执行设备检测");
+ // 执行设备检测
+ await PerformDeviceDetection(cts.Token);
+
+
+ }
+ catch (OperationCanceledException)
+ {
+ // 任务被取消,退出循环
+ break;
+ }
+ catch (Exception ex)
+ {
+ LogInfo.Error("设备检测过程中发生异常: " + ex.Message);
+ }
+
+ // 计算距离下一次检测的剩余时间
+ TimeSpan timeToNextDetection = nextDetectionTime - DateTime.Now;
+
+ // 如果剩余时间为正,则等待
+ if (timeToNextDetection > TimeSpan.Zero)
+ {
+ await Task.Delay(timeToNextDetection, cts.Token);
+ }
+
+ // 设置下一次检测时间点
+ nextDetectionTime = DateTime.Now.AddMilliseconds(DETECTION_INTERVAL_MS);
+ }
+
+ LogInfo.Info("设备检测线程正常退出");
+ ExitEvent.Reset();
+ e.Cancel = true;
+ }
+ catch (OperationCanceledException)
+ {
+ LogInfo.Info("设备检测线程被取消");
+ }
+ catch (Exception ex)
+ {
+ LogInfo.Error("设备检测线程异常:" + ex.Message);
+ // 异常发生后等待一段时间再继续
+ await Task.Delay(30000);
+ }
+ finally
+ {
+ cts.Cancel();
+ cts.Dispose();
+ }
+ }
+
+ // 执行所有设备的检测
+ private async Task PerformDeviceDetection(CancellationToken cancellationToken)
+ {
+ var tasks = new List();
+ SemaphoreSlim semaphore = new SemaphoreSlim(m_DeviceInfoList.Count); // 限制最多5个并发任务
+
+ foreach (var item in m_DeviceInfoList)
+ {
+ await semaphore.WaitAsync(cancellationToken);
+
+ tasks.Add(Task.Factory.StartNew(async () =>
+ {
+ try
+ {
+ await HandleDeviceConnection(item);
+ // 更新设备状态
+
+ EquipStateActionasyc?.Invoke(item);
+ }
+ catch (OperationCanceledException)
+ {
+ // 任务被取消
+ }
+ catch (Exception ex)
+ {
+ LogInfo.Error($"处理设备 {item.m_strConnectStr} 时出错: {ex.Message}");
+ }
+ finally
+ {
+ semaphore.Release();
+ }
+ }, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap());
+ }
+
+ // 等待所有任务完成
+ await Task.WhenAll(tasks);
+ }
+
+ // 其余方法保持不变...
+
+ // 将设备连接处理逻辑提取为单独的方法
+ private async Task HandleDeviceConnection(DeviceInfo item)
+ {
+ IDeviceAdapter pDeviceAdapter = item.m_IDeviceAdapter;
+
+ if (pDeviceAdapter == null)
+ {
+ item.m_ConnectState = 0;
+ return;
+ }
+ if (item.m_iDeviceId == 10001)
+ {
+
+ }
+ switch (item.m_ConnectState)
+ {
+ case 0: // 未连接状态
+ if (await RunOnThreadPool(() => pDeviceAdapter.Device_Init_Id((CommType)item.m_iConnectMode, item.m_strConnectStr, item.m_iDeviceId)))
+ {
+ if (await RunOnThreadPool(() => pDeviceAdapter.Device_Connect()))
+ {
+ // 管理事件订阅,避免重复订阅
+ pDeviceAdapter.RecvIdentifyDataEvent -= RecvIdentifyData_Instance;
+ pDeviceAdapter.RecvIdentifyDataEvent += RecvIdentifyData_Instance;
+
+ item.m_ConnectState = await GetConnectionStateFromHeartbeat(pDeviceAdapter);
+ }
+ else
+ {
+ item.m_ConnectState = 0;
+ }
+ }
+ else
+ {
+ item.m_ConnectState = 0;
+ }
+ break;
+
+ case 1: // 已连接状态
+ item.m_ConnectState = await GetConnectionStateFromHeartbeat(pDeviceAdapter);
+ break;
+
+ case 2: // 连接异常状态
+ int heartbeatResult = await GetConnectionStateFromHeartbeat(pDeviceAdapter);
+ if (heartbeatResult == 2)
+ {
+ item.m_ConnectState = 0;
+ await RunOnThreadPool(() => item.m_IDeviceAdapter.Device_Destroy());
+ }
+ else if (heartbeatResult == 1)
+ {
+ item.m_ConnectState = 1;
+ }
+ else
+ {
+ item.m_ConnectState = 0;
+ await RunOnThreadPool(() => item.m_IDeviceAdapter.Device_Destroy());
+ }
+ break;
+ }
+ }
+
+ // 将心跳检测逻辑提取为单独的方法
+ private async Task GetConnectionStateFromHeartbeat(IDeviceAdapter adapter)
+ {
+ return await adapter.Device_SendHeartPackAsync();
+ }
+
+ // 替代 Task.Run 的辅助方法,兼容 .NET Framework 4.6.1
+ private Task RunOnThreadPool(Func func)
+ {
+ return Task.Factory.StartNew(func, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ // 替代 Task.Run 的辅助方法,兼容 .NET Framework 4.6.1
+ private Task RunOnThreadPool(Action action)
+ {
+ return Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+
///
/// 监听设备数据事件
///
///
///
- private void bgwDeviceDetect_DoWork(object sender, DoWorkEventArgs e)
+ private void bgwDeviceDetect_DoWork(object sender, DoWorkEventArgs e ,string test)
{
BackgroundWorker backgroundworker = sender as BackgroundWorker;
while (true)
@@ -229,7 +459,7 @@ namespace Highway.Assemble.EquipClient
});
}
DetectEvent.Reset();
- DetectEvent.WaitOne(120000, exitContext: false);
+ DetectEvent.WaitOne(60000, exitContext: false);
}
catch (Exception ex)
{
@@ -722,6 +952,11 @@ namespace Highway.Assemble.EquipClient
EquipStateAction = action;
}
+ public void RecEquipStateasyc(Action action)
+ {
+ EquipStateActionasyc = action;
+ }
+
public void RecGetData(Action action)
{
RecGetDataAction = action;
diff --git a/Highway.Assemble.EquipClient/Highway.Assemble.EquipClient.csproj b/Highway.Assemble.EquipClient/Highway.Assemble.EquipClient.csproj
index b9a473b..13be077 100644
--- a/Highway.Assemble.EquipClient/Highway.Assemble.EquipClient.csproj
+++ b/Highway.Assemble.EquipClient/Highway.Assemble.EquipClient.csproj
@@ -49,6 +49,7 @@
+
@@ -63,6 +64,10 @@
{514b888f-4d0d-4406-9396-5235a7bed7bf}
Highway.Assemble.Common
+
+ {786B9D51-D67A-4235-B082-78E9CF4FCFB6}
+ Mesnac.DeviceAdapter.RFly_I160
+
\ No newline at end of file
diff --git a/Highway.Assemble.EquipClient/IEquipClient.cs b/Highway.Assemble.EquipClient/IEquipClient.cs
index 2322d7c..753ddae 100644
--- a/Highway.Assemble.EquipClient/IEquipClient.cs
+++ b/Highway.Assemble.EquipClient/IEquipClient.cs
@@ -27,6 +27,8 @@ namespace Highway.Assemble.EquipClient
void RecEquipState(Action> action);
+ void RecEquipStateasyc(Action action);
+
void ReadData(int num, byte filterMembank, ushort filterWordPtr, ushort filterWordCnt, byte[] filterData, byte Membank, ushort WordPtr, ushort WordCnt);
void RetReadData(Action> action);
diff --git a/Mesnac.DeviceAdapter.Fuchs/FuchsDevice.cs b/Mesnac.DeviceAdapter.Fuchs/FuchsDevice.cs
index 6f41768..ca33439 100644
--- a/Mesnac.DeviceAdapter.Fuchs/FuchsDevice.cs
+++ b/Mesnac.DeviceAdapter.Fuchs/FuchsDevice.cs
@@ -4,6 +4,7 @@ using System.ComponentModel;
//using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
+using System.Threading.Tasks;
namespace Mesnac.DeviceAdapter.Fuchs
{
@@ -1508,6 +1509,11 @@ namespace Mesnac.DeviceAdapter.Fuchs
throw new NotImplementedException();
}
+ public Task Device_SendHeartPackAsync(CancellationToken cancellationToken = default)
+ {
+ throw new NotImplementedException();
+ }
+
//public List TagInventoryTimePeriod(byte Antenna, int time)
//{
// List t = new List { };
diff --git a/Mesnac.DeviceAdapter.HWKC_81600/HWKC_81600Device.cs b/Mesnac.DeviceAdapter.HWKC_81600/HWKC_81600Device.cs
index fc267d4..352a232 100644
--- a/Mesnac.DeviceAdapter.HWKC_81600/HWKC_81600Device.cs
+++ b/Mesnac.DeviceAdapter.HWKC_81600/HWKC_81600Device.cs
@@ -4,6 +4,7 @@ using System.Configuration;
//using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
+using System.Threading.Tasks;
namespace Mesnac.DeviceAdapter.HWKC_81600
{
@@ -784,6 +785,11 @@ namespace Mesnac.DeviceAdapter.HWKC_81600
{
throw new NotImplementedException();
}
+
+ public Task Device_SendHeartPackAsync(CancellationToken cancellationToken = default)
+ {
+ throw new NotImplementedException();
+ }
#endregion
}
}
diff --git a/Mesnac.DeviceAdapter.RFly_I160/BgTcpClient.cs b/Mesnac.DeviceAdapter.RFly_I160/BgTcpClient.cs
index 59f3ddc..34017c2 100644
--- a/Mesnac.DeviceAdapter.RFly_I160/BgTcpClient.cs
+++ b/Mesnac.DeviceAdapter.RFly_I160/BgTcpClient.cs
@@ -284,7 +284,7 @@ namespace Mesnac.DeviceAdapter.RFly_I160
m_ClientSock.Blocking = false;
m_ClientSock.Send(tmp, 0, 0);
bResult = true;
- Console.WriteLine("Connected!");
+ //Console.WriteLine("Connected!");
}
else
{
@@ -297,12 +297,12 @@ namespace Mesnac.DeviceAdapter.RFly_I160
if (e.NativeErrorCode.Equals(10035))
{
bResult = true;
- Console.WriteLine("Still Connected, but the Send would block");
+ //Console.WriteLine("Still Connected, but the Send would block");
}
else
{
bResult = false;
- Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
+ //Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
diff --git a/Mesnac.DeviceAdapter.RFly_I160/Properties/_system~.ini b/Mesnac.DeviceAdapter.RFly_I160/Properties/_system~.ini
deleted file mode 100644
index e69de29..0000000
diff --git a/Mesnac.DeviceAdapter.RFly_I160/RFly_I160Device.cs b/Mesnac.DeviceAdapter.RFly_I160/RFly_I160Device.cs
index ea9af36..a1f5236 100644
--- a/Mesnac.DeviceAdapter.RFly_I160/RFly_I160Device.cs
+++ b/Mesnac.DeviceAdapter.RFly_I160/RFly_I160Device.cs
@@ -1,12 +1,13 @@
using System;
+using System.Collections;
using System.Collections.Generic;
+using System.Configuration;
using System.Linq;
-using System.Text;
//using System.Threading.Tasks;
using System.Runtime.InteropServices;
+using System.Text;
using System.Threading;
-using System.Configuration;
-using System.Collections;
+using System.Threading.Tasks;
namespace Mesnac.DeviceAdapter.RFly_I160
{
@@ -34,7 +35,10 @@ namespace Mesnac.DeviceAdapter.RFly_I160
private Semaphore m_GlobalSem = new Semaphore(1, 1);
private bool m_GetHeartSuccessful = false;
- private Semaphore m_GetHeartSem = new Semaphore(0, 100000);
+ private Semaphore m_GetHeartSem = new Semaphore(0, 100000);
+
+ //private ManualResetEvent m_GetHeartSem = new ManualResetEvent(false);
+
private Semaphore m_MulEpcSem = new Semaphore(0, 100000);
private Semaphore m_StopSem = new Semaphore(0, 100000);
@@ -272,6 +276,94 @@ namespace Mesnac.DeviceAdapter.RFly_I160
return true;
}
+
+ public async Task Device_SendHeartPackAsync(CancellationToken cancellationToken = default)
+ {
+ try
+ {
+
+ // 使用 ManualResetEventSlim 替代 SemaphoreSlim,支持异步等待
+ await Task.Factory.StartNew(
+ () => m_GlobalSem.WaitOne(),
+ cancellationToken,
+ TaskCreationOptions.None,
+ TaskScheduler.Default
+ );
+
+ // 创建心跳包
+ var messagePack = new MessagePack
+ {
+ m_pData = new byte[9] { 0xAA, 0x55, 0x00, 0x90, 0x90, 0x0D, 0x00, 0x00, 0x0D }
+ };
+
+ // 检查通信服务
+ if (m_ICommunicateService == null)
+ {
+ LogInfo.Error("Communication service is not initialized.");
+ return 2; // 通讯连接器失败或网络故障
+ }
+
+ // 发送心跳包
+ bool sendSuccess = await Task.Factory.StartNew(
+ () => m_ICommunicateService.SendMessage(messagePack),
+ cancellationToken,
+ TaskCreationOptions.None,
+ TaskScheduler.Default
+ );
+
+ if (!sendSuccess)
+ {
+ LogInfo.Warn("Failed to send heartbeat message.");
+ return 2; // 通讯连接器失败或网络故障
+ }
+ // 使用 WaitHandle.WaitOne 的超时机制
+ var waitTask = Task.Factory.StartNew(
+ () => m_GetHeartSem.WaitOne(2000, false),
+ cancellationToken,
+ TaskCreationOptions.None,
+ TaskScheduler.Default
+ );
+
+ // 不需要第二个超时,直接等待任务完成
+ await waitTask;
+
+ if (waitTask.Result)
+ {
+ LogInfo.Debug("Heartbeat response received successfully.");
+ return 1; // 通讯连接和读写器都正常
+ }
+ else
+ {
+ // 处理超时的情况
+ LogInfo.Warn("Heartbeat response timed out after 2000ms.");
+ return 0; // 或者抛出异常,取决于你的需求
+ }
+
+
+ }
+ catch (OperationCanceledException)
+ {
+ LogInfo.Info("Heartbeat operation was canceled.");
+ return 2;
+ }
+ catch (Exception ex)
+ {
+ LogInfo.Error($"Exception in Device_SendHeartPackAsync: {ex.Message}");
+ return 2; // 发生异常,返回通讯故障
+ }
+ finally
+ {
+ // 确保信号量总是被释放
+ try
+ {
+ m_GlobalSem.Release();
+ }
+ catch (ApplicationException)
+ {
+ LogInfo.Error("Global semaphore was already released.");
+ }
+ }
+ }
public byte Device_SendHeartPack()
{
byte iResult = 0;
diff --git a/Mesnac.DeviceAdapter.RFly_I160/_system~.ini b/Mesnac.DeviceAdapter.RFly_I160/_system~.ini
deleted file mode 100644
index e69de29..0000000