整合设备
This commit is contained in:
parent
a25a4bc6ed
commit
d2bf7ab4c0
@ -59,7 +59,12 @@ namespace BOB
|
||||
containerRegistry.RegisterSingleton<StepRunning>();
|
||||
containerRegistry.RegisterSingleton<Devices>();
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
{
|
||||
var devices = Container.Resolve<Devices>();
|
||||
devices.Dispose();
|
||||
base.OnExit(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -13,6 +13,9 @@ namespace BOB.Singleton
|
||||
{
|
||||
public class Devices
|
||||
{
|
||||
private CancellationTokenSource _appCancellationTokenSource = new();
|
||||
public CancellationToken AppCancellationToken => _appCancellationTokenSource.Token;
|
||||
|
||||
public Dictionary<string, object> DeviceDic { get; private set; } = new Dictionary<string, object>();
|
||||
|
||||
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
|
||||
@ -230,5 +233,11 @@ namespace BOB.Singleton
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_appCancellationTokenSource.Cancel();
|
||||
_appCancellationTokenSource.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using Model;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -21,156 +22,30 @@ namespace BOB.ViewModels.Dialogs
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
private ObservableCollection<string> _types = ["串口", "Tcp", "ModbusRtu", "ModbusTcp", "CAN", "Udp"];
|
||||
public ObservableCollection<string> Types
|
||||
{
|
||||
get => _types;
|
||||
set => SetProperty(ref _types, value);
|
||||
}
|
||||
|
||||
private string _Mode;
|
||||
public string Mode
|
||||
{
|
||||
get => _Mode;
|
||||
set => SetProperty(ref _Mode, value);
|
||||
}
|
||||
private bool _IsAdd;
|
||||
public bool IsAdd
|
||||
{
|
||||
get => _IsAdd;
|
||||
set => SetProperty(ref _IsAdd, value);
|
||||
}
|
||||
|
||||
private ProgramModel _program;
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _program;
|
||||
set => SetProperty(ref _program, value);
|
||||
}
|
||||
private DeviceModel _Device;
|
||||
public DeviceModel Device
|
||||
private DeviceInfoModel _Device;
|
||||
public DeviceInfoModel Device
|
||||
{
|
||||
get => _Device;
|
||||
set => SetProperty(ref _Device, value);
|
||||
}
|
||||
private ObservableCollection<DeviceConnectSettingModel> _DeviceConnectSettings=new();
|
||||
public ObservableCollection<DeviceConnectSettingModel> DeviceConnectSettings
|
||||
{
|
||||
get => _DeviceConnectSettings;
|
||||
set => SetProperty(ref _DeviceConnectSettings, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
public ICommand CancelCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
public ICommand SelectionChangedCommand { get; set; }
|
||||
public DeviceSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
_globalVariables = globalVariables;
|
||||
CancelCommand = new DelegateCommand(Cancel);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
SelectionChangedCommand = new DelegateCommand(SelectionChanged);
|
||||
}
|
||||
|
||||
private void SelectionChanged()
|
||||
{
|
||||
if (Device == null) return;
|
||||
DeviceConnectSettings.Clear();
|
||||
switch (Device!.Type)
|
||||
{
|
||||
case "Tcp":
|
||||
case "ModbusTcp":
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "IP地址",
|
||||
Value = "127.0.0.1"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "端口号",
|
||||
Value = "502"
|
||||
});
|
||||
break;
|
||||
case "串口":
|
||||
case "ModbusRtu":
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "COM口",
|
||||
Value = "COM1"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "波特率",
|
||||
Value = "9600"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "数据位",
|
||||
Value = "8"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "停止位",
|
||||
Value = "1"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "奇偶",
|
||||
Value = "无"
|
||||
});
|
||||
break;
|
||||
case "Udp":
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "远程IP地址",
|
||||
Value = "127.0.0.1"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "远程端口号",
|
||||
Value = "8080"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "本地端口号",
|
||||
Value = "0"
|
||||
});
|
||||
break;
|
||||
}
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "读超时",
|
||||
Value = "3000"
|
||||
});
|
||||
DeviceConnectSettings.Add(new()
|
||||
{
|
||||
Name = "写超时",
|
||||
Value = "3000"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void Save()
|
||||
{
|
||||
if (Mode == "ADD")
|
||||
{
|
||||
Program.Devices.Add(Device);
|
||||
_globalVariables.SelectedDevice = Device;
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = Program.Devices
|
||||
.Select((x, i) => new { x, i })
|
||||
.FirstOrDefault(p => p.x.ID == _globalVariables.SelectedDevice.ID)?.i;
|
||||
|
||||
if (index.HasValue)
|
||||
{
|
||||
Program.Devices[index.Value] = Device;
|
||||
}
|
||||
}
|
||||
RequestClose.Invoke(ButtonResult.OK);
|
||||
}
|
||||
|
||||
@ -192,20 +67,7 @@ namespace BOB.ViewModels.Dialogs
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Program = _globalVariables.Program;
|
||||
Mode = parameters.GetValue<string>("Mode");
|
||||
if(Mode == "ADD")
|
||||
{
|
||||
Device = new();
|
||||
IsAdd = true;
|
||||
Device.Type = "Tcp";
|
||||
SelectionChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
Device = new DeviceModel(_globalVariables.SelectedDevice);
|
||||
IsAdd = false;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
using BOB.Models;
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Base;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@ -16,6 +21,21 @@ namespace BOB.ViewModels
|
||||
public class ParametersManagerViewModel:BindableBase
|
||||
{
|
||||
#region 属性
|
||||
private ObservableCollection<DeviceConfigModel> _DeviceList;
|
||||
|
||||
public ObservableCollection<DeviceConfigModel> DeviceList
|
||||
{
|
||||
get { return _DeviceList; }
|
||||
set { SetProperty(ref _DeviceList,value); }
|
||||
}
|
||||
private ObservableCollection<DeviceInfoModel> _DeviceInfoModel;
|
||||
|
||||
public ObservableCollection<DeviceInfoModel> DeviceInfoModel
|
||||
{
|
||||
get { return _DeviceInfoModel; }
|
||||
set { SetProperty(ref _DeviceInfoModel, value); }
|
||||
}
|
||||
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _globalVariables.Program;
|
||||
@ -40,85 +60,149 @@ namespace BOB.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
private DeviceModel _SelectedDevice;
|
||||
public DeviceModel SelectedDevice
|
||||
private DeviceInfoModel _SelectedDevice;
|
||||
public DeviceInfoModel SelectedDevice
|
||||
{
|
||||
get => _SelectedDevice;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _SelectedDevice, value))
|
||||
{
|
||||
_globalVariables.SelectedDevice = value;
|
||||
}
|
||||
}
|
||||
get { return _SelectedDevice; }
|
||||
set { SetProperty(ref _SelectedDevice, value); }
|
||||
}
|
||||
#endregion
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private IDialogService _dialogService { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public ICommand ParameterAddCommand { get; set; }
|
||||
public ICommand ParameterEditCommand { get; set; }
|
||||
public ICommand ParameterDeleteCommand { get; set; }
|
||||
public ICommand DeviceAddCommand { get; set; }
|
||||
public ICommand DeviceEditCommand { get; set; }
|
||||
public ICommand DeviceDeleteCommand { get; set; }
|
||||
public ICommand ReconnnectCommand { get; set; }
|
||||
|
||||
|
||||
|
||||
public ParametersManagerViewModel(GlobalVariables GlobalVariables,IDialogService dialogService,IEventAggregator eventAggregator)
|
||||
public ParametersManagerViewModel(GlobalVariables GlobalVariables,IDialogService dialogService,IEventAggregator eventAggregator,IContainerProvider containerProvider)
|
||||
{
|
||||
_globalVariables = GlobalVariables;
|
||||
_eventAggregator= eventAggregator;
|
||||
_devices=containerProvider.Resolve<Devices>();
|
||||
_dialogService = dialogService;
|
||||
Program = _globalVariables.Program;
|
||||
ParameterAddCommand = new DelegateCommand(ParameterAdd);
|
||||
ParameterEditCommand = new DelegateCommand(ParameterEdit);
|
||||
ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
|
||||
DeviceAddCommand = new DelegateCommand(DeviceAdd);
|
||||
DeviceEditCommand = new DelegateCommand(DeviceEdit);
|
||||
DeviceDeleteCommand = new DelegateCommand(DeviceDelete);
|
||||
|
||||
|
||||
ReconnnectCommand = new DelegateCommand(Reconnnect);
|
||||
DeviceList = new ObservableCollection<DeviceConfigModel>(SystemConfig.Instance.DeviceList);
|
||||
InitData();
|
||||
}
|
||||
|
||||
private void Reconnnect()
|
||||
{
|
||||
if(SelectedDevice!=null)
|
||||
{
|
||||
if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case ITcp tcpDevice:
|
||||
await tcpDevice.ConnectAsync();
|
||||
break;
|
||||
|
||||
case ISerialPort serialDevice:
|
||||
await serialDevice.ConnectAsync();
|
||||
break;
|
||||
|
||||
case IModbusDevice modbusDevice:
|
||||
await modbusDevice.ConnectAsync();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitData()
|
||||
{
|
||||
DeviceInfoModel = new ObservableCollection<DeviceInfoModel>();
|
||||
for (int i = 0; i < DeviceList.Count; i++)
|
||||
{
|
||||
DeviceInfoModel.Add(new DeviceInfoModel
|
||||
{
|
||||
DeviceName = DeviceList[i].DeviceName,
|
||||
Remark = DeviceList[i].Remark,
|
||||
IsConnected = false,
|
||||
IsEnabled= DeviceList[i].IsEnabled,
|
||||
DeviceType= DeviceList[i].DeviceType,
|
||||
CommunicationConfig= DeviceList[i].CommunicationConfig
|
||||
});
|
||||
}
|
||||
|
||||
var progress = new Progress<(int index, bool isConnected)>();
|
||||
progress.ProgressChanged += (s, e) =>
|
||||
{
|
||||
DeviceInfoModel[e.index].IsConnected = e.isConnected;
|
||||
};
|
||||
|
||||
var token = _devices.AppCancellationToken;
|
||||
Task.Run(() => PollingConnection(progress, token));
|
||||
}
|
||||
|
||||
private async Task PollingConnection(IProgress<(int index, bool isConnected)> progress, CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
for (int i = 0; i < DeviceList.Count; i++)
|
||||
{
|
||||
bool isConnected = false;
|
||||
|
||||
if (_devices.DeviceDic.TryGetValue(DeviceList[i].Remark, out var device) && device != null)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case ITcp tcpDevice:
|
||||
isConnected = tcpDevice.TcpClient?.Connected ?? false;
|
||||
break;
|
||||
|
||||
case ISerialPort serialDevice:
|
||||
isConnected = serialDevice.SerialPort?.IsOpen ?? false;
|
||||
break;
|
||||
|
||||
case IModbusDevice modbusDevice:
|
||||
isConnected = (modbusDevice.TcpClient?.Connected ?? false) || (modbusDevice.SerialPort?.IsOpen ?? false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
progress.Report((i, isConnected));
|
||||
}
|
||||
|
||||
await Task.Delay(200, token); // 支持取消
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region 委托命令
|
||||
|
||||
private void DeviceDelete()
|
||||
{
|
||||
Program.Devices.Remove(SelectedDevice);
|
||||
}
|
||||
|
||||
|
||||
private void DeviceEdit()
|
||||
{
|
||||
if(SelectedDevice==null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var param = new DialogParameters
|
||||
{
|
||||
{ "Mode", SelectedDevice==null?"ADD":"Edit" }
|
||||
{ "Devices", SelectedDevice }
|
||||
};
|
||||
_dialogService.ShowDialog("DeviceSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void DeviceAdd()
|
||||
{
|
||||
var param = new DialogParameters
|
||||
{
|
||||
{ "Mode", "ADD" }
|
||||
};
|
||||
_dialogService.ShowDialog("DeviceSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
@ -56,31 +56,12 @@
|
||||
<StackPanel Height="30"
|
||||
Orientation="Horizontal"
|
||||
Margin="7">
|
||||
<Label Content="通讯协议类型"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="85" />
|
||||
<ComboBox ItemsSource="{Binding Types}"
|
||||
SelectedItem="{Binding Device.Type,UpdateSourceTrigger=PropertyChanged}"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="120"
|
||||
materialDesign:HintAssist.Hint="通讯协议类型"
|
||||
IsEnabled="{Binding IsAdd}">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<prism:InvokeCommandAction Command="{Binding SelectionChangedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Orientation="Horizontal"
|
||||
Margin="7">
|
||||
<Label Content="设备描述"
|
||||
<Label Content="是否启用"
|
||||
Width="85"
|
||||
VerticalAlignment="Bottom" />
|
||||
<TextBox Text="{Binding Device.Description}"
|
||||
<CheckBox IsChecked="{Binding IsEnable}"
|
||||
VerticalAlignment="Bottom"
|
||||
materialDesign:HintAssist.Hint="设备描述"
|
||||
materialDesign:HintAssist.Hint="是否启用"
|
||||
Width="120" />
|
||||
</StackPanel>
|
||||
<Label Content="连接参数"
|
||||
|
||||
@ -70,7 +70,7 @@
|
||||
<TabItem Header="设备">
|
||||
<DataGrid Padding="10"
|
||||
Background="Transparent"
|
||||
ItemsSource="{Binding Program.Devices}"
|
||||
ItemsSource="{Binding DeviceInfoModel}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
@ -90,12 +90,12 @@
|
||||
<Setter Property="Fill"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Connected}"
|
||||
<DataTrigger Binding="{Binding IsConnected}"
|
||||
Value="True">
|
||||
<Setter Property="Fill"
|
||||
Value="LimeGreen" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Connected}"
|
||||
<DataTrigger Binding="{Binding IsConnected}"
|
||||
Value="False">
|
||||
<Setter Property="Fill"
|
||||
Value="Red" />
|
||||
@ -109,25 +109,24 @@
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTextColumn Header="设备名称"
|
||||
Binding="{Binding Name}" />
|
||||
<DataGridTextColumn Header="备注"
|
||||
Binding="{Binding Description}" />
|
||||
</DataGrid.Columns>
|
||||
Binding="{Binding DeviceName}" />
|
||||
<DataGridTemplateColumn Header="是否启用">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox IsChecked="{Binding IsEnabled}" IsEnabled="False" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
</DataGrid.Columns>
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="新增"
|
||||
Command="{Binding DeviceAddCommand}" />
|
||||
<MenuItem Header="编辑"
|
||||
Command="{Binding DeviceEditCommand}"
|
||||
/>
|
||||
<MenuItem Header="删除"
|
||||
Foreground="Red"
|
||||
Command="{Binding DeviceDeleteCommand}"
|
||||
/>
|
||||
<!--<MenuItem Header="编辑"
|
||||
Command="{Binding DeviceEditCommand}" />-->
|
||||
<MenuItem Header="重新连接"
|
||||
Command="{Binding ReconnnectCommand}" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
|
||||
</DataGrid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using NModbus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -8,6 +11,9 @@ namespace DeviceCommand.Base
|
||||
{
|
||||
public interface IModbusDevice
|
||||
{
|
||||
public TcpClient TcpClient { get; set; }
|
||||
public SerialPort SerialPort { get; set; }
|
||||
public IModbusMaster Modbus { get; set; }
|
||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||
void Close();
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ namespace DeviceCommand.Base
|
||||
{
|
||||
public interface ISerialPort
|
||||
{
|
||||
public SerialPort SerialPort { get; set; }
|
||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||
|
||||
void Close();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -6,6 +7,7 @@ namespace DeviceCommand.Base
|
||||
{
|
||||
public interface ITcp
|
||||
{
|
||||
public TcpClient TcpClient { get; set; }
|
||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||
|
||||
void Close();
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using NModbus.Serial;
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -17,8 +18,9 @@ namespace DeviceCommand.Base
|
||||
public int ReadTimeout { get; private set; } = 3000;
|
||||
public int WriteTimeout { get; private set; } = 3000;
|
||||
|
||||
public SerialPort SerialPort { get; private set; } = new SerialPort();
|
||||
public IModbusMaster Modbus { get; private set; }
|
||||
public SerialPort SerialPort { get; set; } = new SerialPort();
|
||||
public TcpClient TcpClient { get; set; }
|
||||
public IModbusMaster Modbus { get; set; }
|
||||
|
||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using NModbus;
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
@ -13,8 +14,9 @@ namespace DeviceCommand.Base
|
||||
public int Port { get; private set; } = 502;
|
||||
public int SendTimeout { get; private set; } = 3000;
|
||||
public int ReceiveTimeout { get; private set; } = 3000;
|
||||
public TcpClient TcpClient { get; private set; } = new TcpClient();
|
||||
public IModbusMaster Modbus { get; private set; }
|
||||
public SerialPort SerialPort { get; set; }
|
||||
public TcpClient TcpClient { get; set; } = new TcpClient();
|
||||
public IModbusMaster Modbus { get; set; }
|
||||
|
||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Base
|
||||
{
|
||||
public class Serial_Port: ISerialPort
|
||||
public class Serial_Port : ISerialPort
|
||||
{
|
||||
public string PortName { get; set; } = "COM1";
|
||||
public int BaudRate { get; set; } = 9600;
|
||||
@ -15,8 +15,8 @@ namespace DeviceCommand.Base
|
||||
public Parity Parity { get; set; } = Parity.None;
|
||||
public int ReadTimeout { get; set; } = 3000;
|
||||
public int WriteTimeout { get; set; } = 3000;
|
||||
public SerialPort _SerialPort { get; private set; } = new SerialPort();
|
||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||
public SerialPort SerialPort { get; set; } = new SerialPort();
|
||||
private readonly SemaphoreSlim commLock = new(1, 1);
|
||||
|
||||
public void ConfigureDevice(string portName, int baudRate, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, int readTimeout = 3000, int writeTimeout = 3000)
|
||||
{
|
||||
@ -30,43 +30,43 @@ namespace DeviceCommand.Base
|
||||
}
|
||||
public async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||||
{
|
||||
await _commLock.WaitAsync(ct);
|
||||
await commLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
if (_SerialPort.IsOpen) _SerialPort.Close();
|
||||
if (SerialPort.IsOpen) SerialPort.Close();
|
||||
|
||||
_SerialPort.PortName = PortName;
|
||||
_SerialPort.BaudRate = BaudRate;
|
||||
_SerialPort.DataBits = DataBits;
|
||||
_SerialPort.StopBits = StopBits;
|
||||
_SerialPort.Parity = Parity;
|
||||
_SerialPort.ReadTimeout = ReadTimeout;
|
||||
_SerialPort.WriteTimeout = WriteTimeout;
|
||||
SerialPort.PortName = PortName;
|
||||
SerialPort.BaudRate = BaudRate;
|
||||
SerialPort.DataBits = DataBits;
|
||||
SerialPort.StopBits = StopBits;
|
||||
SerialPort.Parity = Parity;
|
||||
SerialPort.ReadTimeout = ReadTimeout;
|
||||
SerialPort.WriteTimeout = WriteTimeout;
|
||||
|
||||
_SerialPort.Open();
|
||||
SerialPort.Open();
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_commLock.Release();
|
||||
commLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (_SerialPort.IsOpen) _SerialPort.Close();
|
||||
if (SerialPort.IsOpen) SerialPort.Close();
|
||||
}
|
||||
|
||||
public async Task SendAsync(string data, CancellationToken ct = default)
|
||||
{
|
||||
await _commLock.WaitAsync(ct);
|
||||
await commLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
if (!_SerialPort.IsOpen) return;
|
||||
if (!SerialPort.IsOpen) return;
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(data);
|
||||
|
||||
var timeoutTask = Task.Delay(WriteTimeout > 0 ? WriteTimeout : Timeout.Infinite, ct);
|
||||
var sendTask = Task.Run(() => _SerialPort.Write(bytes, 0, bytes.Length), ct);
|
||||
var sendTask = Task.Run(() => SerialPort.Write(bytes, 0, bytes.Length), ct);
|
||||
|
||||
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||
if (completedTask == timeoutTask) throw new TimeoutException($"写入操作在 {WriteTimeout} ms内未完成");
|
||||
@ -74,16 +74,16 @@ namespace DeviceCommand.Base
|
||||
}
|
||||
finally
|
||||
{
|
||||
_commLock.Release();
|
||||
commLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default)
|
||||
{
|
||||
await _commLock.WaitAsync(ct);
|
||||
await commLock.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
if (!_SerialPort.IsOpen) return null;
|
||||
if (!SerialPort.IsOpen) return null;
|
||||
|
||||
delimiter ??= "\n";
|
||||
var sb = new StringBuilder();
|
||||
@ -91,9 +91,9 @@ namespace DeviceCommand.Base
|
||||
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
if (_SerialPort.BytesToRead > 0)
|
||||
if (SerialPort.BytesToRead > 0)
|
||||
{
|
||||
int bytesRead = _SerialPort.Read(buffer, 0, buffer.Length);
|
||||
int bytesRead = SerialPort.Read(buffer, 0, buffer.Length);
|
||||
sb.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
|
||||
|
||||
int index = sb.ToString().IndexOf(delimiter, StringComparison.Ordinal);
|
||||
@ -112,7 +112,7 @@ namespace DeviceCommand.Base
|
||||
}
|
||||
finally
|
||||
{
|
||||
_commLock.Release();
|
||||
commLock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ namespace DeviceCommand.Base
|
||||
public int Port { get; private set; } = 502;
|
||||
public int SendTimeout { get; private set; } = 3000;
|
||||
public int ReceiveTimeout { get; private set; } = 3000;
|
||||
public TcpClient TcpClient { get; private set; } = new TcpClient();
|
||||
public TcpClient TcpClient { get; set; } = new TcpClient();
|
||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||
|
||||
public void ConfigureDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
||||
|
||||
@ -8,6 +8,14 @@ public class LoggingInterceptor : IInterceptor
|
||||
{
|
||||
string className = invocation.TargetType.Name;
|
||||
string methodName = invocation.Method.Name;
|
||||
// 排除 TcpClient, SerialPort, Modbus 的 getter
|
||||
if (methodName.Contains("get_TcpClient") ||
|
||||
methodName.Contains("get_SerialPort") ||
|
||||
methodName.Contains("get_Modbus"))
|
||||
{
|
||||
invocation.Proceed(); // 不拦截
|
||||
return;
|
||||
}
|
||||
|
||||
LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 开始");
|
||||
|
||||
|
||||
20
Model/DeviceInfoModel.cs
Normal file
20
Model/DeviceInfoModel.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
public class DeviceInfoModel
|
||||
{
|
||||
public string DeviceName { get; set; }
|
||||
public string DeviceType { get; set; }
|
||||
public string Remark { get; set; }
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
public bool IsConnected { get; set; }
|
||||
public ICommunicationConfig CommunicationConfig { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user