using FluentModbus; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Markup; namespace AwInitilizer { internal class ZhongShengLedControl : IDisposable { private readonly MainWindow mainWindow; private const int DevAddress = 1; private const int GreenAddress = 0; private const int YelloAddress = 1; private const int EmergencyAddress = 2; private ModbusRtuClient modbusRtuClient; private Task poolingMonitorTask; private bool isInEmergency = false; private CancellationTokenSource cancellationSource; private bool IsInitCompleted => modbusRtuClient != null; private SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); private bool isDisposing = false; private bool isPoolingMonitorTaskComplete = false; public ZhongShengLedControl(ModbusRtuClient comportClient, MainWindow mainWindow) { if (comportClient is null) { return; } cancellationSource = new CancellationTokenSource(); this.mainWindow = mainWindow; //mainWindow.OnUpdateStarting += MainWindow_OnUpdateStarting; //mainWindow.OnUpdateCompleted += MainWindow_OnUpdateCompleted; InitComport(comportClient); InitMoniter(); } public ZhongShengLedControl(string comport, MainWindow mainWindow) { if (string.IsNullOrEmpty(comport)) { return; } cancellationSource = new CancellationTokenSource(); this.mainWindow = mainWindow; //mainWindow.OnUpdateStarting += MainWindow_OnUpdateStarting; //mainWindow.OnUpdateCompleted += MainWindow_OnUpdateCompleted; InitComport(comport); InitMoniter(); } private async void MainWindow_OnUpdateCompleted(object sender, EventArgs e) { if (!IsInitCompleted || isInEmergency) { return; } await SetGreenOn(true); await SetYelloOn(false); } private async void MainWindow_OnUpdateStarting(object sender, EventArgs e) { if (!IsInitCompleted || isInEmergency) { return; } await SetGreenOn(false); await SetYelloOn(true); } public void Dispose() { Application.Current.Dispatcher.Invoke(() => { isDisposing = true; //cancellationSource.Cancel(); Task.Delay(1000).Wait(); SetGreenOn(true).Wait(); SetYelloOn(false).Wait(); //mainWindow.OnUpdateStarting -= MainWindow_OnUpdateStarting; //mainWindow.OnUpdateCompleted -= MainWindow_OnUpdateCompleted; modbusRtuClient.Dispose(); }); } public async Task DisposeAsync() { isDisposing = true; //cancellationSource.Cancel(); //var wai = poolingMonitorTask.Result; while(!isPoolingMonitorTaskComplete) { await Task.Delay(1000); } var test = poolingMonitorTask.Status; await SetGreenOn(true); await SetYelloOn(false); //mainWindow.OnUpdateStarting -= MainWindow_OnUpdateStarting; //mainWindow.OnUpdateCompleted -= MainWindow_OnUpdateCompleted; modbusRtuClient.Dispose(); } private void InitComport(ModbusRtuClient comportClient) { modbusRtuClient = comportClient; } private void InitComport(string comport) { try { modbusRtuClient = new ModbusRtuClient() { BaudRate = 38400, StopBits = System.IO.Ports.StopBits.One, Parity = System.IO.Ports.Parity.None //arity奇偶 }; modbusRtuClient.Connect(comport); } catch (Exception ex) { MessageBox.Show("ZhongShengLed port open failed"); throw; } } private void InitMoniter() { if (poolingMonitorTask != null) { return; } //poolingMonitorTask = MonitorTask(cancellationSource.Token); poolingMonitorTask = Task.Factory.StartNew(() => MonitorTask().Wait(), TaskCreationOptions.AttachedToParent); } private async Task MonitorTask(CancellationToken token = default) { try { while (!token.IsCancellationRequested && !isDisposing) { var emergencyDataRead = await Read(EmergencyAddress, token); if (isDisposing) return ; isInEmergency = emergencyDataRead > 0; if (isInEmergency) { //await SetGreenOn(false); await SetYelloOn(false, token); if (isDisposing) return ; } else { await SetGreenOn(false, token); if (isDisposing) return ; await SetYelloOn(true, token); if (isDisposing) return ; } await Task.Delay(1000); } } catch { } finally { isPoolingMonitorTaskComplete = true; } return ; } public async Task SetGreenOn(bool isOn, CancellationToken token = default) { try { //var greenValue = await Read(GreenAddress); //var isGreenOn = greenValue == 0; //if (isGreenOn != isOn) //{ // await Write(GreenAddress, 1); //} await Write(GreenAddress, isOn ? (short)0 : (short)256, token); } catch (Exception ex) { } } public async Task SetYelloOn(bool isOn, CancellationToken token = default) { try { //var yelloValue = await Read(YelloAddress); //var isYellowOn = yelloValue > 0; //if (isYellowOn != isOn) //{ // await Write(YelloAddress, 1); //} await Write(YelloAddress, isOn ? (short)256 : (short)0, token); } catch (Exception ex) { } } private async Task Write(int address, short value, CancellationToken token = default) { //await semaphore.WaitAsync(); try { await modbusRtuClient.WriteSingleRegisterAsync(DevAddress, address, value, token); } catch (Exception e) { } finally { //semaphore.Release(); } return; } private async Task Read(int address, CancellationToken token = default) { //await semaphore.WaitAsync(); try { //var result = await modbusRtuClient.ReadInputRegistersAsync(DevAddress, address, 1); var result = await modbusRtuClient.ReadHoldingRegistersAsync(DevAddress, address, 1, token); var resultArray = result.ToArray(); if (resultArray.Length == 0) { return null; } return resultArray[0]; } catch (Exception ex) { return null; } finally { //semaphore.Release(); } } } }