123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- using MV485.db;
- using MV485.Dlg;
- using MV485.model;
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MV485.helper
- {
- public class SerialPollingGroup
- {
- public string PortName { get; } //串口号为主键
- private List<TSlave> _slaveList = new List<TSlave>();
- private RWRunConfig _reader = new RWRunConfig();
- private Timer _pollingTimer;
- //private bool _isReading = false; //控制串行读取
- private int _isPolling = 0; // 控制是否正在轮询中,防止重入
- private SemaphoreSlim _portLock = new SemaphoreSlim(1, 1);
- public event Action<TSlaveDetail> SlaveDetailAdded;
- public event Action<string, RunStatusType> SlaveStatusChanged;
- private bool _isPause;
- public SerialPollingGroup(string portName,bool isPause)
- {
- PortName = portName;
- _isPause = isPause;
- }
- public void Pause()
- {
- _isPause = true;
- }
- public void Resume()
- {
- _isPause = false;
- }
- public void AddDevice(TSlave slave)
- {
- if (_slaveList.Find(a => a.SlaveId == slave.SlaveId) == null)
- {
- _slaveList.Add(slave);
- }
- }
- public void AddDevice(ObservableCollection<TSlave> slaveList)
- {
- foreach(var slave in slaveList)
- {
- _slaveList.Add(slave);
- }
- }
- public void RemoveDevice(string slaveId)
- {
- _slaveList.RemoveAll(d => d.SlaveId == slaveId);
- }
- public void RemoveAllDevice()
- {
- _slaveList.Clear();
- }
- public bool HasAnyDevice()
- {
- return _slaveList.Count > 0;
- }
- public void StartPolling()
- {
- _pollingTimer = new Timer(PollDevices, null, 0, 1000 * 1);
- }
- private void PollDevices(object state)
- {
- if (_isPause == true) return;
- // 如果已经有轮询在进行,直接跳过这轮触发
- if (Interlocked.CompareExchange(ref _isPolling, 1, 0) == 1)
- return;
- try
- {
- foreach (var slave in _slaveList)
- {
- if (DateTime.Now >= slave.NextReadTime && slave.RunFlag == 1)
- {
- // 每轮最多处理一个设备
- _ = PollDeviceAsync(slave); // fire-and-forget 异步执行
- break;
- }
- }
- }
- catch(Exception ex)
- {
- throw new Exception(ex.Message);
- }
- Interlocked.Exchange(ref _isPolling, 0); // 标记当前已完成
- }
- private async Task PollDeviceAsync(TSlave slave)
- {
- await _portLock.WaitAsync();
- try
- {
- SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_READING);
- var data = _reader.ReadWMData(slave.PortName, slave.BaudRate, (byte)slave.Address);
- var dtReadTime = DateTime.Now;
- var detail = new TSlaveDetail
- {
- DetailId = Guid.NewGuid().ToString("N"),
- SlaveId = slave.SlaveId,
- ReadTime = dtReadTime.ToString("yyyy-MM-dd HH:mm:ss"),
- DeviceSn = "",
- SampleResult = 0,
- SampleTime = "",
- MeterType = 0,
- ImageFile = "",
- };
- //判断是否读取照片
- string imageFilePath = "";
- if(data != null && detail != null &&slave.ReadImageFlag == 1)
- {
- ushort imageSize = _reader.ReadImageSize(slave.PortName, slave.BaudRate, (byte)slave.Address);
- imageFilePath = $"{data.DeviceSn}_{data.SampleTime.ToString("yyyyMMddHHmm")}_{dtReadTime.ToString("yyyyMMddHHmmss")}.jpg";
- string savePath = ConfigManager.Instance.GetConfigValue(ConfigKey.SaveImagePath, DlgSaveImagePath.DefaultImagePath);
- //imageFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
- // "wm_image", $"{DateTime.Now.ToString("yyyyMMdd")}",imageFilePath);
- imageFilePath = Path.Combine(savePath, $"{DateTime.Now.ToString("yyyyMMdd")}", imageFilePath);
- if (imageSize > 0)
- {
- XModemReceiver receiver = new XModemReceiver();
- receiver.OnProgress += (receiveSize, fileSize) =>
- {
- Console.WriteLine($"已接受{receiveSize}/{fileSize}");
- };
- receiver.RWLog += message =>
- {
- Console.WriteLine(message);
- };
- bool blRecv = receiver.StartReceiveFile(slave.PortName, slave.BaudRate, imageFilePath,imageSize);
- if (blRecv)
- {
- detail.ImageFile = imageFilePath;
- }
- }
- }
- if (data != null)
- {
- detail.DeviceSn = data.DeviceSn;
- //detail.ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- detail.SampleResult = data.TotalFlow;
- detail.SampleTime = data.SampleTime.ToString("yyyy-MM-dd HH:mm:ss");
- detail.MeterType = data.ResultType;
- //detail.ImageFile = "";
- detail.ReadMemo = "成功读取";
- }
- else
- {
- detail.ReadMemo = _reader.GetLastError();
- }
- if (DBSlaveDetail.InsertTSlaveDetail(detail))
- {
- SlaveDetailAdded?.Invoke(detail);
- }
- slave.LastReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_IDLE);
- }
- catch (Exception ex)
- {
- SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_UNCONNECTED);
- Logger.Error(ex.Message);
- }
- finally
- {
- //SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_IDLE);
- _portLock.Release();
- }
- }
- //private void PollDevices(object state)
- //{
- // if (_isReading) return;
- // foreach (var slave in _slaveList)
- // {
- // DateTime dtReadTime = DateTime.Now;
- // if (dtReadTime >= slave.NextReadTime && slave.RunFlag == 1)
- // {
- // _isReading = true;
- // Task.Run(() =>
- // {
- // try
- // {
- // slave.RunStatus = RunStatusType.STATUS_READING;
- // SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_READING);
- // var data = _reader.ReadWMData(slave.PortName, slave.BaudRate, (byte)slave.Address);
- // //根据WMData生成TSlaveDetail
- // if (data != null)
- // {
- // TSlaveDetail detail = new TSlaveDetail()
- // {
- // DetailId = Guid.NewGuid().ToString().Replace("-", ""),
- // SlaveId = slave.SlaveId,
- // DeviceSn = data.DeviceSn,
- // ReadTime = dtReadTime.ToString("yyyy-MM-dd HH:mm:ss"),
- // SampleResult = data.TotalFlow,
- // SampleTime = data.SampleTime.ToString("yyyy-MM-dd HH:mm:ss"),
- // MeterType = data.MeterType,
- // ImageFile = ""
- // };
- // //插入数据库
- // bool blInsert = DBSlaveDetail.InsertTSlaveDetail(detail);
- // if (blInsert)
- // {
- // SlaveDetailAdded?.Invoke(detail);
- // }
- // }
- // }
- // catch (Exception ex)
- // {
- // slave.RunStatus = RunStatusType.STATUS_UNCONNECTED;
- // SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_UNCONNECTED);
- // //日志等处理
- // Logger.Error(ex.Message);
- // }
- // finally
- // {
- // //设置上一次读的时间
- // slave.LastReadTime = dtReadTime.ToString("yyyy-MM-dd HH:mm:ss");
- // //DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- // //slave.RunStatus = RunStatusType.STATUS_IDLE;
- // SlaveStatusChanged?.Invoke(slave.SlaveId, RunStatusType.STATUS_IDLE);
- // _isReading = false;
- // }
- // });
- // break; //当前时间只处理一个
- // }
- // }//for each
- //}
- public void StopPolling()
- {
- _pollingTimer?.Dispose();
- }
- //----------------------------------------------------------------------------------------------------
- }
- //-------------------------------------------------------------------------------------------------------
- }
|