diff --git a/BPASmartClient.Business/BPASmartClient.Business.csproj b/BPASmartClient.Business/BPASmartClient.Business.csproj index 88631d12..79841b02 100644 --- a/BPASmartClient.Business/BPASmartClient.Business.csproj +++ b/BPASmartClient.Business/BPASmartClient.Business.csproj @@ -8,7 +8,7 @@ - + diff --git a/BPASmartClient.CustomResource/BPASmartClient.CustomResource.csproj b/BPASmartClient.CustomResource/BPASmartClient.CustomResource.csproj index 28267f47..f712ea77 100644 --- a/BPASmartClient.CustomResource/BPASmartClient.CustomResource.csproj +++ b/BPASmartClient.CustomResource/BPASmartClient.CustomResource.csproj @@ -229,7 +229,7 @@ - + diff --git a/BPASmartClient.CustomResource/Converters/StatusConverter.cs b/BPASmartClient.CustomResource/Converters/StatusConverter.cs new file mode 100644 index 00000000..cf9a2c9d --- /dev/null +++ b/BPASmartClient.CustomResource/Converters/StatusConverter.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using System.Windows.Media; + +namespace BPASmartClient.CustomResource.Converters +{ + public class StatusConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + SolidColorBrush returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 204, 255)); + if (value != null && value is ushort statusValue) + { + switch (statusValue) + { + case 0: + returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 204, 255)); + break; + case 1: + returnValue = new SolidColorBrush(Color.FromArgb(255, 0, 255, 127)); + break; + case 2: + returnValue = new SolidColorBrush(Color.FromArgb(255, 255, 215, 00)); + break; + case 3: + returnValue = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)); + break; + default: + break; + } + } + return returnValue; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/BPASmartClient.Device/BPASmartClient.Device.csproj b/BPASmartClient.Device/BPASmartClient.Device.csproj index 5e442528..a15d3f48 100644 --- a/BPASmartClient.Device/BPASmartClient.Device.csproj +++ b/BPASmartClient.Device/BPASmartClient.Device.csproj @@ -7,7 +7,7 @@ - + diff --git a/BPASmartClient.Modbus/ModbusTcp.cs b/BPASmartClient.Modbus/ModbusTcp.cs index a437ead2..c97dc4a8 100644 --- a/BPASmartClient.Modbus/ModbusTcp.cs +++ b/BPASmartClient.Modbus/ModbusTcp.cs @@ -49,11 +49,11 @@ namespace BPASmartClient.Modbus Port = port; modbusFactory = new ModbusFactory(); Connect(); - master.Transport.ReadTimeout = 2000;//读取超时时间 - master.Transport.WriteTimeout = 2000;//写入超时时间 - master.Transport.Retries = 10;//重试次数 if (Connected) { + master.Transport.ReadTimeout = 2000;//读取超时时间 + master.Transport.WriteTimeout = 2000;//写入超时时间 + master.Transport.Retries = 10;//重试次数 ConnectOk?.Invoke(); MessageLog.GetInstance.Show($"设备【{ip}:{port}】连接成功"); } diff --git a/BPASmartClient.Model/BPASmartClient.Model.csproj b/BPASmartClient.Model/BPASmartClient.Model.csproj index 9a94b652..d042f82e 100644 --- a/BPASmartClient.Model/BPASmartClient.Model.csproj +++ b/BPASmartClient.Model/BPASmartClient.Model.csproj @@ -17,7 +17,7 @@ - + diff --git a/DosingSystem/App.xaml b/DosingSystem/App.xaml index 1f7b318e..a0fd7aba 100644 --- a/DosingSystem/App.xaml +++ b/DosingSystem/App.xaml @@ -23,6 +23,7 @@ + diff --git a/DosingSystem/DosingSystem.csproj b/DosingSystem/DosingSystem.csproj index 7dff77c7..f661812d 100644 --- a/DosingSystem/DosingSystem.csproj +++ b/DosingSystem/DosingSystem.csproj @@ -14,7 +14,7 @@ - + diff --git a/DosingSystem/Model/DeviceInquire.cs b/DosingSystem/Model/DeviceInquire.cs index f1c0671d..1a9cdaae 100644 --- a/DosingSystem/Model/DeviceInquire.cs +++ b/DosingSystem/Model/DeviceInquire.cs @@ -14,16 +14,15 @@ namespace DosingSystem.Model { public class DeviceInquire { - private volatile static DeviceInquire _Instance; public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); private DeviceInquire() { } string IPSegment = "192.168.1."; - string NameAddress = "VW5000"; + string NameAddress = "VW0"; int count = 0; private static readonly object _lock = new object(); - ConcurrentDictionary modbusTcps = new ConcurrentDictionary(); + ConcurrentDictionary DeviceLists = new ConcurrentDictionary(); List InvalidIP = new List(); public void Init() @@ -36,10 +35,14 @@ namespace DosingSystem.Model }), "配料机设备上线监听", true); } - public ModbusTcp GetModbusTcp(string ip) + public DeviceStatus GetDevice(string deviceName) { - if (modbusTcps.ContainsKey(ip)) return modbusTcps[ip]; - else return default; + if (deviceName != null) + { + var res = DeviceLists.Values.FirstOrDefault(p => p.DeviceName == deviceName); + if (res != null) return res; + } + return default; } private void IpAddressLines() @@ -48,8 +51,7 @@ namespace DosingSystem.Model { if (!InvalidIP.Contains($"{IPSegment}{i}")) { - Ping myPing; - myPing = new Ping(); + Ping myPing = new Ping(); myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted); string pingIP = $"{IPSegment}{i}"; myPing.SendAsync(pingIP, 1000, null); @@ -69,17 +71,23 @@ namespace DosingSystem.Model if (e.Reply.Status == IPStatus.Success) { string ip = e.Reply.Address.ToString(); - if (!modbusTcps.ContainsKey(ip)) + if (!DeviceLists.ContainsKey(ip)) { - modbusTcps.TryAdd(ip, new ModbusTcp()); - modbusTcps[ip].IsReconnect = false; - Task.Run(new Action(() => { modbusTcps[ip].ModbusTcpConnect(ip); })); - - modbusTcps[ip].ConnectOk = new Action(() => + DeviceStatus DS = new DeviceStatus(); + //DeviceLists.TryAdd(ip, new DeviceStatus()); + //DeviceLists[ip].modbusTcp.IsReconnect = false; + //Task.Run(new Action(() => { DeviceLists[ip].modbusTcp.ModbusTcpConnect(ip, 508); })); + DS.modbusTcp.IsReconnect = false; + Task.Run(new Action(() => { DS.modbusTcp.ModbusTcpConnect(ip, 508); })); + DS.modbusTcp.ConnectOk = new Action(() => { - string DeviceName = modbusTcps[ip].GetString(NameAddress, 10); + //string DeviceName = DeviceLists[ip].modbusTcp.GetString(NameAddress, 20); + string DeviceName = DS.modbusTcp.GetString(NameAddress, 20); if (DeviceName.Length > 0) { + DeviceLists.TryAdd(ip, DS); + DeviceLists[ip].Init(DeviceName); + DeviceLists[ip].modbusTcp.IsReconnect = true; App.Current.Dispatcher.Invoke(new Action(() => { DeviceListViewModel.devices.Add(new Devices() @@ -87,6 +95,9 @@ namespace DosingSystem.Model DeviceName = DeviceName, IpAddress = ip }); + if (!NewRecipeViewModel.RawMaterialNames.Contains(DeviceName)) + NewRecipeViewModel.RawMaterialNames.Add(DeviceName); + })); } else @@ -95,23 +106,71 @@ namespace DosingSystem.Model } }); - modbusTcps[ip].ConnectFail = new Action(() => + DS.modbusTcp.ConnectFail = new Action(() => { if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); }); - modbusTcps[ip].Disconnect = new Action(() => + DS.modbusTcp.Disconnect = new Action(() => { if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip); var res = DeviceListViewModel.devices.FirstOrDefault(P => P.IpAddress == ip); if (res != null && DeviceListViewModel.devices.Contains(res)) - App.Current.Dispatcher.Invoke(new Action(() => { DeviceListViewModel.devices.Remove(res); })); + App.Current.Dispatcher.Invoke(new Action(() => + { + DeviceListViewModel.devices.Remove(res); + if (!NewRecipeViewModel.RawMaterialNames.Contains(res.DeviceName)) + NewRecipeViewModel.RawMaterialNames.Remove(res.DeviceName); + })); + //DeviceLists[ip].Dispose(); + DS.Dispose(); }); } } CompleteCount(); } + } + public class DeviceStatus + { + public string DeviceName = String.Empty; + public ModbusTcp modbusTcp = new ModbusTcp(); + public void Init(string DeviceName) + { + this.DeviceName = DeviceName; + if (modbusTcp.Connected) + { + ThreadManage.GetInstance().StartLong(new Action(() => + { + var res = this.modbusTcp.Read("VW100"); + if (res is ushort ushortValue) + { + RunStatus = ushortValue; + } + Thread.Sleep(100); + }), $"{DeviceName} 开始监听", true); + } + } + + public void Dispose() + { + ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听"); + } + public bool IsConnected => modbusTcp.Connected; + + /// + /// 配料系统运行状态 + /// + public ushort RunStatus { get; private set; } + public void Start(float Value) + { + if (modbusTcp.Connected) + { + modbusTcp.SetReal("VW40", Value);//写入配方量 + modbusTcp.Write("M0.0", true);//设备启动写入 + } + } } + } diff --git a/DosingSystem/Model/LocaPar.cs b/DosingSystem/Model/LocaPar.cs index 3addd1f2..ab3a8c56 100644 --- a/DosingSystem/Model/LocaPar.cs +++ b/DosingSystem/Model/LocaPar.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections.ObjectModel; +using DosingSystem.ViewModel; namespace DosingSystem.Model { diff --git a/DosingSystem/Model/RawMaterialModel.cs b/DosingSystem/Model/RawMaterialModel.cs new file mode 100644 index 00000000..1378de4d --- /dev/null +++ b/DosingSystem/Model/RawMaterialModel.cs @@ -0,0 +1,48 @@ +using Microsoft.Toolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DosingSystem.Model +{ + /// + /// 原料模块 + /// + public class RawMaterialModel : ObservableObject + { + /// + /// 原料名称 + /// + public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } + private string _mRawMaterialName; + + /// + /// 原料设备IP + /// + public string DeviceIp { get; set; } + + /// + /// 原料重量 + /// + public float RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; OnPropertyChanged(); } } + private float _mRawMaterialWeight; + + /// + /// 原料ID + /// + public string RawMaterialId { get { return _mRawMaterialId; } set { _mRawMaterialId = value; OnPropertyChanged(); } } + private string _mRawMaterialId; + + /// + /// 原料设备执行状态 + /// 1:等待下料 + /// 2:下料中 + /// 3:下料完成 + /// + public int RecipeStatus { get { return _mRecipeStatus; } set { _mRecipeStatus = value; OnPropertyChanged(); } } + private int _mRecipeStatus; + + } +} diff --git a/DosingSystem/Model/RecipeModel.cs b/DosingSystem/Model/RecipeModel.cs index 8fdeedba..de2d214e 100644 --- a/DosingSystem/Model/RecipeModel.cs +++ b/DosingSystem/Model/RecipeModel.cs @@ -9,8 +9,13 @@ using Microsoft.Toolkit.Mvvm.ComponentModel; namespace DosingSystem.Model { + /// + /// 配方模块 + /// public class RecipeModel : ObservableObject { + public bool IsEnable { get { return _mIsEnable; } set { _mIsEnable = value; OnPropertyChanged(); } } + private bool _mIsEnable = true; /// /// 序号 @@ -30,7 +35,11 @@ namespace DosingSystem.Model public string RecipCode { get { return _mRecipCode; } set { _mRecipCode = value; OnPropertyChanged(); } } private string _mRecipCode; - public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); + /// + /// 原料集合 + /// + public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); + } diff --git a/DosingSystem/View/RecipeControlView.xaml b/DosingSystem/View/RecipeControlView.xaml index 4f37f811..cea82354 100644 --- a/DosingSystem/View/RecipeControlView.xaml +++ b/DosingSystem/View/RecipeControlView.xaml @@ -2,26 +2,187 @@ x:Class="DosingSystem.View.RecipeControlView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:control="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:control="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" - xmlns:pry="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" - xmlns:vm="clr-namespace:DosingSystem.ViewModel" xmlns:local="clr-namespace:DosingSystem.View" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:pry="clr-namespace:BPASmartClient.CustomResource.UserControls;assembly=BPASmartClient.CustomResource" + xmlns:vm="clr-namespace:DosingSystem.ViewModel" d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + +