整合设备
This commit is contained in:
parent
a25a4bc6ed
commit
d2bf7ab4c0
@ -59,7 +59,12 @@ namespace BOB
|
|||||||
containerRegistry.RegisterSingleton<StepRunning>();
|
containerRegistry.RegisterSingleton<StepRunning>();
|
||||||
containerRegistry.RegisterSingleton<Devices>();
|
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
|
public class Devices
|
||||||
{
|
{
|
||||||
|
private CancellationTokenSource _appCancellationTokenSource = new();
|
||||||
|
public CancellationToken AppCancellationToken => _appCancellationTokenSource.Token;
|
||||||
|
|
||||||
public Dictionary<string, object> DeviceDic { get; private set; } = new Dictionary<string, object>();
|
public Dictionary<string, object> DeviceDic { get; private set; } = new Dictionary<string, object>();
|
||||||
|
|
||||||
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
|
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 BOB.Models;
|
||||||
using Common.PubEvent;
|
using Common.PubEvent;
|
||||||
|
using Model;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -21,156 +22,30 @@ namespace BOB.ViewModels.Dialogs
|
|||||||
get => _title;
|
get => _title;
|
||||||
set => SetProperty(ref _title, value);
|
set => SetProperty(ref _title, value);
|
||||||
}
|
}
|
||||||
private ObservableCollection<string> _types = ["串口", "Tcp", "ModbusRtu", "ModbusTcp", "CAN", "Udp"];
|
private DeviceInfoModel _Device;
|
||||||
public ObservableCollection<string> Types
|
public DeviceInfoModel Device
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
get => _Device;
|
get => _Device;
|
||||||
set => SetProperty(ref _Device, value);
|
set => SetProperty(ref _Device, value);
|
||||||
}
|
}
|
||||||
private ObservableCollection<DeviceConnectSettingModel> _DeviceConnectSettings=new();
|
|
||||||
public ObservableCollection<DeviceConnectSettingModel> DeviceConnectSettings
|
|
||||||
{
|
|
||||||
get => _DeviceConnectSettings;
|
|
||||||
set => SetProperty(ref _DeviceConnectSettings, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
public DialogCloseListener RequestClose { get; set; }
|
public DialogCloseListener RequestClose { get; set; }
|
||||||
private GlobalVariables _globalVariables;
|
private GlobalVariables _globalVariables;
|
||||||
private IEventAggregator _eventAggregator;
|
private IEventAggregator _eventAggregator;
|
||||||
public ICommand CancelCommand { get; set; }
|
public ICommand CancelCommand { get; set; }
|
||||||
public ICommand SaveCommand { get; set; }
|
public ICommand SaveCommand { get; set; }
|
||||||
public ICommand SelectionChangedCommand { get; set; }
|
|
||||||
public DeviceSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
|
public DeviceSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
|
||||||
{
|
{
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_globalVariables = globalVariables;
|
_globalVariables = globalVariables;
|
||||||
CancelCommand = new DelegateCommand(Cancel);
|
CancelCommand = new DelegateCommand(Cancel);
|
||||||
SaveCommand = new DelegateCommand(Save);
|
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()
|
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);
|
RequestClose.Invoke(ButtonResult.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,20 +67,7 @@ namespace BOB.ViewModels.Dialogs
|
|||||||
public void OnDialogOpened(IDialogParameters parameters)
|
public void OnDialogOpened(IDialogParameters parameters)
|
||||||
{
|
{
|
||||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
_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
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
using BOB.Models;
|
using BOB.Models;
|
||||||
|
using BOB.Singleton;
|
||||||
using Common.PubEvent;
|
using Common.PubEvent;
|
||||||
|
using DeviceCommand.Base;
|
||||||
|
using DeviceCommand.Device;
|
||||||
|
using Logger;
|
||||||
using MaterialDesignThemes.Wpf;
|
using MaterialDesignThemes.Wpf;
|
||||||
|
using Model;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
@ -16,6 +21,21 @@ namespace BOB.ViewModels
|
|||||||
public class ParametersManagerViewModel:BindableBase
|
public class ParametersManagerViewModel:BindableBase
|
||||||
{
|
{
|
||||||
#region 属性
|
#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
|
public ProgramModel Program
|
||||||
{
|
{
|
||||||
get => _globalVariables.Program;
|
get => _globalVariables.Program;
|
||||||
@ -40,85 +60,149 @@ namespace BOB.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private DeviceModel _SelectedDevice;
|
private DeviceInfoModel _SelectedDevice;
|
||||||
public DeviceModel SelectedDevice
|
public DeviceInfoModel SelectedDevice
|
||||||
{
|
{
|
||||||
get => _SelectedDevice;
|
get { return _SelectedDevice; }
|
||||||
set
|
set { SetProperty(ref _SelectedDevice, value); }
|
||||||
{
|
|
||||||
if (SetProperty(ref _SelectedDevice, value))
|
|
||||||
{
|
|
||||||
_globalVariables.SelectedDevice = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
private GlobalVariables _globalVariables { get; set; }
|
private GlobalVariables _globalVariables { get; set; }
|
||||||
private IDialogService _dialogService { get; set; }
|
private IDialogService _dialogService { get; set; }
|
||||||
|
private Devices _devices { get; set; }
|
||||||
private IEventAggregator _eventAggregator { get; set; }
|
private IEventAggregator _eventAggregator { get; set; }
|
||||||
public ICommand ParameterAddCommand { get; set; }
|
public ICommand ParameterAddCommand { get; set; }
|
||||||
public ICommand ParameterEditCommand { get; set; }
|
public ICommand ParameterEditCommand { get; set; }
|
||||||
public ICommand ParameterDeleteCommand { get; set; }
|
public ICommand ParameterDeleteCommand { get; set; }
|
||||||
public ICommand DeviceAddCommand { get; set; }
|
|
||||||
public ICommand DeviceEditCommand { 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;
|
_globalVariables = GlobalVariables;
|
||||||
_eventAggregator= eventAggregator;
|
_eventAggregator= eventAggregator;
|
||||||
|
_devices=containerProvider.Resolve<Devices>();
|
||||||
_dialogService = dialogService;
|
_dialogService = dialogService;
|
||||||
Program = _globalVariables.Program;
|
Program = _globalVariables.Program;
|
||||||
ParameterAddCommand = new DelegateCommand(ParameterAdd);
|
ParameterAddCommand = new DelegateCommand(ParameterAdd);
|
||||||
ParameterEditCommand = new DelegateCommand(ParameterEdit);
|
ParameterEditCommand = new DelegateCommand(ParameterEdit);
|
||||||
ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
|
ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
|
||||||
DeviceAddCommand = new DelegateCommand(DeviceAdd);
|
|
||||||
DeviceEditCommand = new DelegateCommand(DeviceEdit);
|
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 委托命令
|
#region 委托命令
|
||||||
|
|
||||||
private void DeviceDelete()
|
|
||||||
{
|
|
||||||
Program.Devices.Remove(SelectedDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeviceEdit()
|
private void DeviceEdit()
|
||||||
{
|
{
|
||||||
|
if(SelectedDevice==null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
var param = new DialogParameters
|
var param = new DialogParameters
|
||||||
{
|
{
|
||||||
{ "Mode", SelectedDevice==null?"ADD":"Edit" }
|
{ "Devices", SelectedDevice }
|
||||||
};
|
};
|
||||||
_dialogService.ShowDialog("DeviceSetting", param, (r) =>
|
_dialogService.ShowDialog("DeviceSetting", param, (r) =>
|
||||||
{
|
{
|
||||||
if (r.Result == ButtonResult.OK)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@ -56,31 +56,12 @@
|
|||||||
<StackPanel Height="30"
|
<StackPanel Height="30"
|
||||||
Orientation="Horizontal"
|
Orientation="Horizontal"
|
||||||
Margin="7">
|
Margin="7">
|
||||||
<Label Content="通讯协议类型"
|
<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="设备描述"
|
|
||||||
Width="85"
|
Width="85"
|
||||||
VerticalAlignment="Bottom" />
|
VerticalAlignment="Bottom" />
|
||||||
<TextBox Text="{Binding Device.Description}"
|
<CheckBox IsChecked="{Binding IsEnable}"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
materialDesign:HintAssist.Hint="设备描述"
|
materialDesign:HintAssist.Hint="是否启用"
|
||||||
Width="120" />
|
Width="120" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Label Content="连接参数"
|
<Label Content="连接参数"
|
||||||
|
|||||||
@ -70,7 +70,7 @@
|
|||||||
<TabItem Header="设备">
|
<TabItem Header="设备">
|
||||||
<DataGrid Padding="10"
|
<DataGrid Padding="10"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
ItemsSource="{Binding Program.Devices}"
|
ItemsSource="{Binding DeviceInfoModel}"
|
||||||
AutoGenerateColumns="False"
|
AutoGenerateColumns="False"
|
||||||
CanUserAddRows="False"
|
CanUserAddRows="False"
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
@ -90,12 +90,12 @@
|
|||||||
<Setter Property="Fill"
|
<Setter Property="Fill"
|
||||||
Value="Transparent" />
|
Value="Transparent" />
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<DataTrigger Binding="{Binding Connected}"
|
<DataTrigger Binding="{Binding IsConnected}"
|
||||||
Value="True">
|
Value="True">
|
||||||
<Setter Property="Fill"
|
<Setter Property="Fill"
|
||||||
Value="LimeGreen" />
|
Value="LimeGreen" />
|
||||||
</DataTrigger>
|
</DataTrigger>
|
||||||
<DataTrigger Binding="{Binding Connected}"
|
<DataTrigger Binding="{Binding IsConnected}"
|
||||||
Value="False">
|
Value="False">
|
||||||
<Setter Property="Fill"
|
<Setter Property="Fill"
|
||||||
Value="Red" />
|
Value="Red" />
|
||||||
@ -109,25 +109,24 @@
|
|||||||
</DataGridTemplateColumn>
|
</DataGridTemplateColumn>
|
||||||
|
|
||||||
<DataGridTextColumn Header="设备名称"
|
<DataGridTextColumn Header="设备名称"
|
||||||
Binding="{Binding Name}" />
|
Binding="{Binding DeviceName}" />
|
||||||
<DataGridTextColumn Header="备注"
|
<DataGridTemplateColumn Header="是否启用">
|
||||||
Binding="{Binding Description}" />
|
<DataGridTemplateColumn.CellTemplate>
|
||||||
</DataGrid.Columns>
|
<DataTemplate>
|
||||||
|
<CheckBox IsChecked="{Binding IsEnabled}" IsEnabled="False" />
|
||||||
|
</DataTemplate>
|
||||||
|
</DataGridTemplateColumn.CellTemplate>
|
||||||
|
</DataGridTemplateColumn>
|
||||||
|
|
||||||
|
</DataGrid.Columns>
|
||||||
<DataGrid.ContextMenu>
|
<DataGrid.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem Header="新增"
|
<!--<MenuItem Header="编辑"
|
||||||
Command="{Binding DeviceAddCommand}" />
|
Command="{Binding DeviceEditCommand}" />-->
|
||||||
<MenuItem Header="编辑"
|
<MenuItem Header="重新连接"
|
||||||
Command="{Binding DeviceEditCommand}"
|
Command="{Binding ReconnnectCommand}" />
|
||||||
/>
|
|
||||||
<MenuItem Header="删除"
|
|
||||||
Foreground="Red"
|
|
||||||
Command="{Binding DeviceDeleteCommand}"
|
|
||||||
/>
|
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</DataGrid.ContextMenu>
|
</DataGrid.ContextMenu>
|
||||||
|
|
||||||
</DataGrid>
|
</DataGrid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
using System;
|
using NModbus;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Ports;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -8,6 +11,9 @@ namespace DeviceCommand.Base
|
|||||||
{
|
{
|
||||||
public interface IModbusDevice
|
public interface IModbusDevice
|
||||||
{
|
{
|
||||||
|
public TcpClient TcpClient { get; set; }
|
||||||
|
public SerialPort SerialPort { get; set; }
|
||||||
|
public IModbusMaster Modbus { get; set; }
|
||||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ namespace DeviceCommand.Base
|
|||||||
{
|
{
|
||||||
public interface ISerialPort
|
public interface ISerialPort
|
||||||
{
|
{
|
||||||
|
public SerialPort SerialPort { get; set; }
|
||||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -6,6 +7,7 @@ namespace DeviceCommand.Base
|
|||||||
{
|
{
|
||||||
public interface ITcp
|
public interface ITcp
|
||||||
{
|
{
|
||||||
|
public TcpClient TcpClient { get; set; }
|
||||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using NModbus.Serial;
|
using NModbus.Serial;
|
||||||
using System;
|
using System;
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -17,8 +18,9 @@ namespace DeviceCommand.Base
|
|||||||
public int ReadTimeout { get; private set; } = 3000;
|
public int ReadTimeout { get; private set; } = 3000;
|
||||||
public int WriteTimeout { get; private set; } = 3000;
|
public int WriteTimeout { get; private set; } = 3000;
|
||||||
|
|
||||||
public SerialPort SerialPort { get; private set; } = new SerialPort();
|
public SerialPort SerialPort { get; set; } = new SerialPort();
|
||||||
public IModbusMaster Modbus { get; private set; }
|
public TcpClient TcpClient { get; set; }
|
||||||
|
public IModbusMaster Modbus { get; set; }
|
||||||
|
|
||||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using NModbus;
|
using NModbus;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO.Ports;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -13,8 +14,9 @@ namespace DeviceCommand.Base
|
|||||||
public int Port { get; private set; } = 502;
|
public int Port { get; private set; } = 502;
|
||||||
public int SendTimeout { get; private set; } = 3000;
|
public int SendTimeout { get; private set; } = 3000;
|
||||||
public int ReceiveTimeout { get; private set; } = 3000;
|
public int ReceiveTimeout { get; private set; } = 3000;
|
||||||
public TcpClient TcpClient { get; private set; } = new TcpClient();
|
public SerialPort SerialPort { get; set; }
|
||||||
public IModbusMaster Modbus { get; private set; }
|
public TcpClient TcpClient { get; set; } = new TcpClient();
|
||||||
|
public IModbusMaster Modbus { get; set; }
|
||||||
|
|
||||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace DeviceCommand.Base
|
namespace DeviceCommand.Base
|
||||||
{
|
{
|
||||||
public class Serial_Port: ISerialPort
|
public class Serial_Port : ISerialPort
|
||||||
{
|
{
|
||||||
public string PortName { get; set; } = "COM1";
|
public string PortName { get; set; } = "COM1";
|
||||||
public int BaudRate { get; set; } = 9600;
|
public int BaudRate { get; set; } = 9600;
|
||||||
@ -15,8 +15,8 @@ namespace DeviceCommand.Base
|
|||||||
public Parity Parity { get; set; } = Parity.None;
|
public Parity Parity { get; set; } = Parity.None;
|
||||||
public int ReadTimeout { get; set; } = 3000;
|
public int ReadTimeout { get; set; } = 3000;
|
||||||
public int WriteTimeout { get; set; } = 3000;
|
public int WriteTimeout { get; set; } = 3000;
|
||||||
public SerialPort _SerialPort { get; private set; } = new SerialPort();
|
public SerialPort SerialPort { get; set; } = new SerialPort();
|
||||||
private readonly SemaphoreSlim _commLock = new(1, 1);
|
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)
|
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)
|
public async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
await _commLock.WaitAsync(ct);
|
await commLock.WaitAsync(ct);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_SerialPort.IsOpen) _SerialPort.Close();
|
if (SerialPort.IsOpen) SerialPort.Close();
|
||||||
|
|
||||||
_SerialPort.PortName = PortName;
|
SerialPort.PortName = PortName;
|
||||||
_SerialPort.BaudRate = BaudRate;
|
SerialPort.BaudRate = BaudRate;
|
||||||
_SerialPort.DataBits = DataBits;
|
SerialPort.DataBits = DataBits;
|
||||||
_SerialPort.StopBits = StopBits;
|
SerialPort.StopBits = StopBits;
|
||||||
_SerialPort.Parity = Parity;
|
SerialPort.Parity = Parity;
|
||||||
_SerialPort.ReadTimeout = ReadTimeout;
|
SerialPort.ReadTimeout = ReadTimeout;
|
||||||
_SerialPort.WriteTimeout = WriteTimeout;
|
SerialPort.WriteTimeout = WriteTimeout;
|
||||||
|
|
||||||
_SerialPort.Open();
|
SerialPort.Open();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_commLock.Release();
|
commLock.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
if (_SerialPort.IsOpen) _SerialPort.Close();
|
if (SerialPort.IsOpen) SerialPort.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendAsync(string data, CancellationToken ct = default)
|
public async Task SendAsync(string data, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
await _commLock.WaitAsync(ct);
|
await commLock.WaitAsync(ct);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_SerialPort.IsOpen) return;
|
if (!SerialPort.IsOpen) return;
|
||||||
byte[] bytes = Encoding.UTF8.GetBytes(data);
|
byte[] bytes = Encoding.UTF8.GetBytes(data);
|
||||||
|
|
||||||
var timeoutTask = Task.Delay(WriteTimeout > 0 ? WriteTimeout : Timeout.Infinite, ct);
|
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);
|
var completedTask = await Task.WhenAny(sendTask, timeoutTask);
|
||||||
if (completedTask == timeoutTask) throw new TimeoutException($"写入操作在 {WriteTimeout} ms内未完成");
|
if (completedTask == timeoutTask) throw new TimeoutException($"写入操作在 {WriteTimeout} ms内未完成");
|
||||||
@ -74,16 +74,16 @@ namespace DeviceCommand.Base
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_commLock.Release();
|
commLock.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default)
|
public async Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
await _commLock.WaitAsync(ct);
|
await commLock.WaitAsync(ct);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_SerialPort.IsOpen) return null;
|
if (!SerialPort.IsOpen) return null;
|
||||||
|
|
||||||
delimiter ??= "\n";
|
delimiter ??= "\n";
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@ -91,9 +91,9 @@ namespace DeviceCommand.Base
|
|||||||
|
|
||||||
while (!ct.IsCancellationRequested)
|
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));
|
sb.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
|
||||||
|
|
||||||
int index = sb.ToString().IndexOf(delimiter, StringComparison.Ordinal);
|
int index = sb.ToString().IndexOf(delimiter, StringComparison.Ordinal);
|
||||||
@ -112,7 +112,7 @@ namespace DeviceCommand.Base
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_commLock.Release();
|
commLock.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace DeviceCommand.Base
|
|||||||
public int Port { get; private set; } = 502;
|
public int Port { get; private set; } = 502;
|
||||||
public int SendTimeout { get; private set; } = 3000;
|
public int SendTimeout { get; private set; } = 3000;
|
||||||
public int ReceiveTimeout { 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);
|
private readonly SemaphoreSlim _commLock = new(1, 1);
|
||||||
|
|
||||||
public void ConfigureDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
|
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 className = invocation.TargetType.Name;
|
||||||
string methodName = invocation.Method.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}() 开始");
|
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