@@ -0,0 +1,66 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmart.Model | |||||
{ | |||||
public class AddressConvert | |||||
{ | |||||
private volatile static AddressConvert _Instance; | |||||
public static AddressConvert GetInstance => _Instance ?? (_Instance = new AddressConvert()); | |||||
private AddressConvert() { } | |||||
public int PlcConverter(ICommunicationDevice device, string Address) | |||||
{ | |||||
int address = -1; | |||||
if (Address != null && int.TryParse(Address, out int result)) return result; | |||||
if (device != null && Address != null && Address.Length > 0) | |||||
{ | |||||
switch (device) | |||||
{ | |||||
case Invoance _tempInvoance: | |||||
if (Address.ToUpper().Contains("LW") && Address.Length >= 3) | |||||
{ | |||||
var res = Address.Substring(2); | |||||
if (res != null && int.TryParse(res, out int LwAddress)) return LwAddress; | |||||
} | |||||
break; | |||||
case kinco _tempKinco: | |||||
if (Address.ToUpper().Contains("M") && Address.Length >= 4) | |||||
{ | |||||
var res = Address.Substring(1).Split('.'); | |||||
if (res != null && res.Length == 2) | |||||
{ | |||||
if (int.TryParse(res[0], out int firstAddress) && int.TryParse(res[1], out int ExitAddress)) | |||||
{ | |||||
if (ExitAddress >= 0 && ExitAddress <= 7) | |||||
{ | |||||
return (firstAddress * 8) + 320 + ExitAddress; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
else if ((Address.ToUpper().Contains("VW") || Address.ToUpper().Contains("VD")) && Address.Length >= 3) | |||||
{ | |||||
var res = Address.Substring(2); | |||||
if (res != null && int.TryParse(res, out int tempAddress)) return (tempAddress / 2) + 100; | |||||
} | |||||
break; | |||||
case KincoOneMachine _tempKincoOneMachine: | |||||
if (Address.ToUpper().Contains("D") && Address.Length >= 2) | |||||
{ | |||||
var res = Address.Substring(1); | |||||
if (res != null && int.TryParse(res, out int LwAddress)) return LwAddress; | |||||
} | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
return address; | |||||
} | |||||
} | |||||
} |
@@ -33,7 +33,9 @@ namespace BPASmart.Model | |||||
public string DeviceName { get { return _mDeviceName; } set { _mDeviceName = value; OnPropertyChanged(); } } | public string DeviceName { get { return _mDeviceName; } set { _mDeviceName = value; OnPropertyChanged(); } } | ||||
private string _mDeviceName; | private string _mDeviceName; | ||||
/// <summary> | |||||
/// 通讯模块名称 | |||||
/// </summary> | |||||
public string ModelName { get { return _mModelName; } set { _mModelName = value; OnPropertyChanged(); } } | public string ModelName { get { return _mModelName; } set { _mModelName = value; OnPropertyChanged(); } } | ||||
private string _mModelName; | private string _mModelName; | ||||
@@ -0,0 +1,13 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmart.Model | |||||
{ | |||||
public class PublishInfo | |||||
{ | |||||
public List<PublishModel> PublishModels { get; set; } = new List<PublishModel>(); | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmart.Model | |||||
{ | |||||
public class PublishModel | |||||
{ | |||||
public string DeviceName { get; set; } | |||||
public string Address { get; set; } | |||||
public string Value { get; set; } | |||||
public int Sleep { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,17 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace BPASmart.Model | |||||
{ | |||||
public class ReadDataModel | |||||
{ | |||||
public ushort StartAddress { get; set; } | |||||
public ushort Length { get; set; } | |||||
} | |||||
} |
@@ -11,13 +11,19 @@ using Newtonsoft.Json; | |||||
using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||
using System.Windows; | using System.Windows; | ||||
using Microsoft.Toolkit.Mvvm.Input; | using Microsoft.Toolkit.Mvvm.Input; | ||||
using System.Reflection; | |||||
namespace BPASmart.Model | namespace BPASmart.Model | ||||
{ | { | ||||
public class VariableInfo : AlarmSet | public class VariableInfo : AlarmSet | ||||
{ | { | ||||
private ICommunicationDevice DeviceType; | |||||
public VariableInfo(params object[] s) | public VariableInfo(params object[] s) | ||||
{ | { | ||||
if (s != null && s.Length >= 0) | |||||
{ | |||||
DeviceType = s[0] as ICommunicationDevice; | |||||
} | |||||
CancelCommand = new RelayCommand(() => { IsOpen = false; }); | CancelCommand = new RelayCommand(() => { IsOpen = false; }); | ||||
ConfirmCommand = new RelayCommand(() => { IsOpen = false; }); | ConfirmCommand = new RelayCommand(() => { IsOpen = false; }); | ||||
} | } | ||||
@@ -30,7 +36,7 @@ namespace BPASmart.Model | |||||
/// </summary> | /// </summary> | ||||
public string VarName | public string VarName | ||||
{ | { | ||||
get { return _mVarName; } | |||||
get { return _mVarName.Trim()?.Replace(" ", ""); } | |||||
set | set | ||||
{ | { | ||||
_mVarName = value; | _mVarName = value; | ||||
@@ -43,9 +49,24 @@ namespace BPASmart.Model | |||||
/// <summary> | /// <summary> | ||||
/// 地址 | /// 地址 | ||||
/// </summary> | /// </summary> | ||||
public string Address { get { return _mAddress; } set { _mAddress = value; OnPropertyChanged(); } } | |||||
public string Address | |||||
{ | |||||
get { return _mAddress.Trim()?.Replace(" ", "").ToUpper(); } | |||||
set | |||||
{ | |||||
_mAddress = value; | |||||
OnPropertyChanged(); | |||||
int address = AddressConvert.GetInstance.PlcConverter(DeviceType, value); | |||||
if (address >= 0) RealAddress = address; | |||||
} | |||||
} | |||||
private string _mAddress = string.Empty; | private string _mAddress = string.Empty; | ||||
/// <summary> | |||||
/// 实际地址 | |||||
/// </summary> | |||||
public int RealAddress { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// 数据类型 | /// 数据类型 | ||||
/// </summary> | /// </summary> | ||||
@@ -10,26 +10,165 @@ namespace BPASmart.Server | |||||
public void Init() | public void Init() | ||||
{ | { | ||||
BPASmartClient.Message.MessageLog.GetInstance.ShowDebugLog("通讯模块初始化"); | BPASmartClient.Message.MessageLog.GetInstance.ShowDebugLog("通讯模块初始化"); | ||||
Json<CommunicationPar>.Data.CommunicationDevices.ToList()?.ForEach(item => | Json<CommunicationPar>.Data.CommunicationDevices.ToList()?.ForEach(item => | ||||
{ | { | ||||
switch (item.CommDevice) | |||||
#region 数据加载测试 | |||||
#endregion | |||||
ThreadManage.GetInstance().Start(new Action(() => | |||||
{ | |||||
switch (item.CommDevice) | |||||
{ | |||||
case ModbusRtu _modbusRtu: | |||||
break; | |||||
case ModbusTcp _modbusTcp: | |||||
ModbusTcpMaster modbusTcpMaster = new ModbusTcpMaster(); | |||||
modbusTcpMaster.ConnectOk = new Action(() => | |||||
{ | |||||
ThreadManage.GetInstance().StartLong(new Action(() => | |||||
{ | |||||
GetReadDataModels(item).ToList()?.ForEach(temp => | |||||
{ | |||||
switch (temp.Key) | |||||
{ | |||||
case EDataType.Bool: | |||||
temp.Value?.ForEach(value => | |||||
{ | |||||
var res = modbusTcpMaster.ReadCoils(value.StartAddress, value.Length); | |||||
SetValue(res, item.DeviceName, value, 1); | |||||
}); | |||||
break; | |||||
case EDataType.Byte: | |||||
break; | |||||
case EDataType.Int: | |||||
break; | |||||
case EDataType.Word: | |||||
temp.Value?.ForEach(value => | |||||
{ | |||||
var res = modbusTcpMaster.ReadHoldingRegisters(value.StartAddress, value.Length); | |||||
SetValue(res, item.DeviceName, value, 1); | |||||
}); | |||||
break; | |||||
case EDataType.Dint: | |||||
break; | |||||
case EDataType.Dword: | |||||
temp.Value?.ForEach(value => | |||||
{ | |||||
var res = modbusTcpMaster.ReadHoldingRegisters(value.StartAddress, value.Length); | |||||
SetValue(res, item.DeviceName, value, 2); | |||||
}); | |||||
break; | |||||
case EDataType.Float: | |||||
temp.Value?.ForEach(value => | |||||
{ | |||||
var res = modbusTcpMaster.ReadHoldingRegisters(value.StartAddress, value.Length); | |||||
SetValue(res, item.DeviceName, value, 2); | |||||
}); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
}); | |||||
Thread.Sleep(100); | |||||
}), $"{item.DeviceName} 设备数据采集"); | |||||
var DeviceModel = item; | |||||
}); | |||||
modbusTcpMaster.IsReconnect = true; | |||||
modbusTcpMaster.ModbusTcpConnect(DeviceType.kinco_PLC, _modbusTcp.IP, _modbusTcp.PortNum); | |||||
break; | |||||
case Siemens _siemens: | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
}), $"{item.DeviceName} 初始化连接"); | |||||
}); | |||||
} | |||||
private void SetValue<TArray>(TArray[] arrays, string DeviceName, ReadDataModel readDataModel, ushort by) | |||||
{ | |||||
if (arrays != null) | |||||
{ | |||||
int index = Array.FindIndex(Json<CommunicationPar>.Data.CommunicationDevices.ToArray(), p => p.DeviceName == DeviceName);//获取设备所在集合位置 | |||||
if (index >= 0 && index < Json<CommunicationPar>.Data.CommunicationDevices.Count) | |||||
{ | { | ||||
case ModbusRtu _modbusRtu: | |||||
break; | |||||
case ModbusTcp _modbusTcp: | |||||
ModbusTcpMaster modbusTcpMaster = new ModbusTcpMaster(); | |||||
modbusTcpMaster.ConnectOk = new Action(() => | |||||
var tempArray = Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(index).VarTableModels.ToArray(); | |||||
for (int i = 0; i < arrays.Length; i++) | |||||
{ | |||||
int varIndex = Array.FindIndex(tempArray, p => p.RealAddress == readDataModel.StartAddress + (i * by)); | |||||
if (varIndex >= 0 && varIndex < tempArray.Length) | |||||
{ | { | ||||
Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(index).VarTableModels.ElementAt(varIndex).CurrentValue = arrays[i].ToString(); | |||||
} | |||||
} | |||||
}); | |||||
modbusTcpMaster.ModbusTcpConnect(DeviceType.kinco_PLC, _modbusTcp.IP, _modbusTcp.PortNum); | |||||
break; | |||||
case Siemens _siemens: | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
private Dictionary<EDataType, List<ReadDataModel>> GetReadDataModels(CommunicationModel communicationModel) | |||||
{ | |||||
Dictionary<EDataType, List<ReadDataModel>> readDataModels = new Dictionary<EDataType, List<ReadDataModel>>(); | |||||
communicationModel.VarTableModels.GroupBy(p => p.DataType)?.ToList()?.ForEach(tempVar => | |||||
{ | |||||
if (tempVar.Key != null && tempVar.Key.Length > 0) | |||||
{ | |||||
int address = tempVar.Min(p => p.RealAddress); | |||||
EDataType dataType = (EDataType)Enum.Parse(typeof(EDataType), tempVar.Key); | |||||
switch (dataType) | |||||
{ | |||||
case EDataType.Bool: | |||||
case EDataType.Byte: | |||||
case EDataType.Int: | |||||
case EDataType.Word: | |||||
if (!readDataModels.ContainsKey(dataType)) readDataModels.TryAdd(dataType, GetDataGroup(tempVar)); | |||||
break; | |||||
case EDataType.Dint: | |||||
case EDataType.Dword: | |||||
case EDataType.Float: | |||||
if (!readDataModels.ContainsKey(dataType)) readDataModels.TryAdd(dataType, GetDataGroup(tempVar, 2)); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | } | ||||
}); | }); | ||||
return readDataModels; | |||||
} | |||||
private List<ReadDataModel> GetDataGroup(IGrouping<string, VariableInfo> variableInfos, int by = 1) | |||||
{ | |||||
List<ReadDataModel> ReturnValue = new List<ReadDataModel>(); | |||||
var res = variableInfos?.OrderBy(p => p.RealAddress).ToList(); | |||||
int count = 0; | |||||
if (res != null) | |||||
{ | |||||
int address = variableInfos.Min(p => p.RealAddress); | |||||
int startAddress = address; | |||||
for (int i = 0; i < res.Count; i++) | |||||
{ | |||||
if (res.ElementAt(i).RealAddress == address) | |||||
{ | |||||
count++; | |||||
address += by; | |||||
} | |||||
else | |||||
{ | |||||
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count }); | |||||
count = 1; | |||||
address = res.ElementAt(i).RealAddress + by; | |||||
startAddress = res.ElementAt(i).RealAddress; | |||||
} | |||||
} | |||||
ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count }); | |||||
} | |||||
return ReturnValue; | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -20,13 +20,13 @@ namespace BPASmart.VariableManager.ViewModels | |||||
public class VariableConfigViewModel : NoticeBase | public class VariableConfigViewModel : NoticeBase | ||||
{ | { | ||||
private int varialeInfosIndex = -1; | private int varialeInfosIndex = -1; | ||||
string DeviceName = string.Empty; | |||||
ICommunicationDevice DeviceType; | |||||
public VariableConfigViewModel(string o) | public VariableConfigViewModel(string o) | ||||
{ | { | ||||
DeviceName = o; | |||||
varialeInfosIndex = Array.FindIndex(Json<CommunicationPar>.Data.CommunicationDevices.ToArray(), p => p.DeviceName == o); | varialeInfosIndex = Array.FindIndex(Json<CommunicationPar>.Data.CommunicationDevices.ToArray(), p => p.DeviceName == o); | ||||
if (varialeInfosIndex >= 0 && varialeInfosIndex < Json<CommunicationPar>.Data.CommunicationDevices.Count) | if (varialeInfosIndex >= 0 && varialeInfosIndex < Json<CommunicationPar>.Data.CommunicationDevices.Count) | ||||
{ | { | ||||
DeviceType = Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(varialeInfosIndex).CommDevice; | |||||
varialeInfos = Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(varialeInfosIndex).VarTableModels; | varialeInfos = Json<CommunicationPar>.Data.CommunicationDevices.ElementAt(varialeInfosIndex).VarTableModels; | ||||
if (varialeInfos.Count <= 0) AddRow(); | if (varialeInfos.Count <= 0) AddRow(); | ||||
} | } | ||||
@@ -42,16 +42,32 @@ namespace BPASmart.VariableManager.ViewModels | |||||
DelegationNotifi.GetInstance.VarNameChanged = new Action<int>((p) => | DelegationNotifi.GetInstance.VarNameChanged = new Action<int>((p) => | ||||
{ | { | ||||
var res = varialeInfos.FirstOrDefault(w => w.ID == p); | |||||
var temp = varialeInfos.Where(s => s.VarName == res?.VarName)?.ToList(); | |||||
if (temp != null && temp.Count > 1) | |||||
var result = varialeInfos.GroupBy(P => P.VarName).ToList(); | |||||
if (result != null && result.Count < varialeInfos.Count) | |||||
{ | { | ||||
temp.ForEach(item => | |||||
result.ForEach(x => | |||||
{ | { | ||||
int index = Array.FindIndex(varialeInfos.ToArray(), t => t.VarName == item.VarName && t.ID == item.ID); | |||||
if (index >= 0 && index < varialeInfos.Count) | |||||
if (x.Key.Length > 0) | |||||
{ | { | ||||
varialeInfos.ElementAt(index).IsRedundant = true; | |||||
if (x.Count() > 1) | |||||
{ | |||||
x.ToList().ForEach(item => | |||||
{ | |||||
int index = Array.FindIndex(varialeInfos.ToArray(), p => p.VarName == item.VarName && p.ID == item.ID); | |||||
if (index >= 0 && index < varialeInfos.Count) | |||||
{ | |||||
varialeInfos.ElementAt(index).IsRedundant = true; | |||||
} | |||||
}); | |||||
} | |||||
else if (x.Count() == 1) | |||||
{ | |||||
int index = Array.FindIndex(varialeInfos.ToArray(), p => p.VarName == x.ElementAt(0).VarName && p.ID == x.ElementAt(0).ID); | |||||
if (index >= 0 && index < varialeInfos.Count) | |||||
{ | |||||
varialeInfos.ElementAt(index).IsRedundant = false; | |||||
} | |||||
} | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -68,13 +84,13 @@ namespace BPASmart.VariableManager.ViewModels | |||||
{ | { | ||||
if (varialeInfos?.Count >= p) | if (varialeInfos?.Count >= p) | ||||
{ | { | ||||
if (varialeInfos.ElementAt(p - 1).VarName != null) | |||||
//if (varialeInfos.ElementAt(p - 1).VarName != null) | |||||
//{ | |||||
if (varialeInfos.ElementAt(p - 1).VarName?.Length > 0) | |||||
{ | { | ||||
if (varialeInfos.ElementAt(p - 1).VarName.Length > 0) | |||||
{ | |||||
if (varialeInfos.Count == p) AddRow(); | |||||
} | |||||
if (varialeInfos.Count == p) AddRow(); | |||||
} | } | ||||
//} | |||||
} | } | ||||
} | } | ||||
}); | }); | ||||
@@ -124,7 +140,7 @@ namespace BPASmart.VariableManager.ViewModels | |||||
{ | { | ||||
if (varialeInfosIndex >= 0 && varialeInfosIndex < Json<CommunicationPar>.Data.CommunicationDevices.Count) | if (varialeInfosIndex >= 0 && varialeInfosIndex < Json<CommunicationPar>.Data.CommunicationDevices.Count) | ||||
{ | { | ||||
varialeInfos.Add(new VariableInfo(DeviceName) { ID = varialeInfos.Count + 1 }); | |||||
varialeInfos.Add(new VariableInfo(DeviceType) { ID = varialeInfos.Count + 1 }); | |||||
} | } | ||||
})); | })); | ||||
@@ -1,14 +1,12 @@ | |||||
<UserControl x:Class="BPASmartClient.CustomResource.Pages.View.PermissionConfigurationView" | |||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||||
xmlns:local="clr-namespace:BPASmartClient.CustomResource.Pages.View" | |||||
Width="800" | |||||
Height="450" | |||||
mc:Ignorable="d"> | |||||
<Grid> | |||||
</Grid> | |||||
<UserControl | |||||
x:Class="BPASmartClient.CustomResource.Pages.View.PermissionConfigurationView" | |||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||||
xmlns:local="clr-namespace:BPASmartClient.CustomResource.Pages.View" | |||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||||
Width="800" | |||||
Height="450" | |||||
mc:Ignorable="d"> | |||||
<Grid /> | |||||
</UserControl> | </UserControl> |
@@ -1,12 +1,12 @@ | |||||
<UserControl x:Class="BPASmartClient.CustomResource.Pages.View.RecipeQueueView" | |||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||||
xmlns:local="clr-namespace:BPASmartClient.CustomResource.Pages.View" | |||||
mc:Ignorable="d" | |||||
d:DesignHeight="450" d:DesignWidth="800"> | |||||
<Grid> | |||||
</Grid> | |||||
<UserControl | |||||
x:Class="BPASmartClient.CustomResource.Pages.View.RecipeQueueView" | |||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |||||
xmlns:local="clr-namespace:BPASmartClient.CustomResource.Pages.View" | |||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |||||
d:DesignHeight="450" | |||||
d:DesignWidth="800" | |||||
mc:Ignorable="d"> | |||||
<Grid /> | |||||
</UserControl> | </UserControl> |