using CommunityToolkit.Mvvm.ComponentModel; using HslCommunication; using HslCommunication.Profinet.Siemens; using S7.Net; using Serilog; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Threading; using WPFWCSDemo.Common; using WPFWCSDemo.Data; using WPFWCSDemo.Models.Devices; using WPFWCSDemo.Models.Devices.CircleRGV; using WPFWCSDemo.Models.Devices.CircleRGVStation; using WPFWCSDemo.Utilities; using WPFWCSDemo.Views.Devices; namespace WPFWCSDemo.ViewModels { public partial class CircleRGVsViewModel : ObservableObject { /// /// 用于监控环穿状态参数的定时器 /// private DispatcherTimer dispatcherTimer; static int deviceCount = RGVStation.RGVCount; private CircleRGVsViewModel() { States = new ObservableCollection(); CircleRGVStates = new ObservableCollection(); CircleRGVStateInitialize(); dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Interval=TimeSpan.FromSeconds(2); dispatcherTimer.Tick += DispatcherTimer_Tick; dispatcherTimer.Start(); } private void DispatcherTimer_Tick(object? sender, EventArgs e) { States.Clear(); for (int i = 1; i <= deviceCount; i++) { States.Add(GetCircleRGVState(i)); } for (int i = 0; i < States.Count; i++) { try { if (States[i] is null) continue; CircleRGVStates[i].Read_Phase = States[i].Read_Phase; CircleRGVStates[i].Read_DeviceState = States[i].Read_DeviceState; CircleRGVStates[i].Read_TaskNumber = States[i].Read_TaskNumber; //CircleRGVStates[i].Read_TaskType = 1; CircleRGVStates[i].Read_Mode = States[i].Read_Mode; CircleRGVStates[i].Read_SourceLocation = States[i].Read_SourceLocation; CircleRGVStates[i].Read_TargetLocation = States[i].Read_TargetLocation; } catch { //Log.Warning($"【读取环穿状态】{i + 1}#环穿读取错误!"); } } } /// /// 状态参数监控集合 /// [ObservableProperty] ObservableCollection _states; /// /// 环穿入出对应的路径 /// public static Dictionary route = new Dictionary() { {1001, 1012}, {1003, 1009}, {1005, 1010}, {1007, 1011}, {1008, 1011}, }; /// /// 环穿状态集合 /// [ObservableProperty] ObservableCollection _circleRGVStates; /// /// 穿梭车plc连接 /// [Obsolete] private static SiemensS7Net[] circleRgvConnection = new SiemensS7Net[9] { new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.120"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.123"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.126"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.129"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.132"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.135"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.138"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.141"), new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.144"), }; /// /// 地面站plc连接 /// private static SiemensS7Net stationConnection = new SiemensS7Net(SiemensPLCS.S1500, ipStation); //初始化懒加载---保证线程安全 private static readonly Lazy instanceHolder = new(()=>new CircleRGVsViewModel(),LazyThreadSafetyMode.ExecutionAndPublication); //外部获取类实例 public static CircleRGVsViewModel Instance { get { return instanceHolder.Value; } } /// /// 地面站plc IP /// const string ipStation = "192.168.6.100"; #region 地面站plc参数地址 //====================环穿写入:plc地址==================== /// /// 任务号 /// const string plcWriteStation_TaskNumber = $"DB610.0"; /// /// 取货站点 /// const string plcWriteStation_SourceLocation = $"DB610.4"; /// /// 放货站点 /// const string plcWriteStation_TargetLocation = $"DB610.6"; /// /// 任务类型 /// const string plcWriteStation_TaskType = $"DB610.8"; /// /// 小车编号(任意数字-plc自行判断) /// const string plcWriteStation_DeviceNumber = $"DB610.10"; /// /// 下发完成 /// const string plcWriteStation_SendFinish = $"DB610.12"; /// /// 检验码 /// const string plcWriteStation_Checksum = $"DB610.14"; //====================环穿读取:plc地址==================== /// /// 允许下发 /// const string plcReadStation_Permission = $"DB611.0"; /// /// 下发状态 /// const string plcReadStation_SendState = $"DB611.2"; /// /// 任务号 /// const string plcReadStation_TaskNumber = $"DB611.4"; #endregion #region 输送请求 /// /// 取货请求---1001供应实垛 --- √ /// const string plcReadStation_GetRequest1001 = $"DB622.0.4"; /// /// 取货请求---1003供应实垛 --- √ /// const string plcReadStation_GetRequest1003 = $"DB622.9.1"; /// /// 取货请求---1005供应实垛 --- √ /// const string plcReadStation_GetRequest1005 = $"DB622.11.1"; /// /// 取货请求---1007供应实垛 --- √ /// const string plcReadStation_GetRequest1007 = $"DB622.2.5"; /// /// 取货请求---1008供应实垛 --- √ /// const string plcReadStation_GetRequest1008 = $"DB622.2.6"; /// /// 系统正常---1001供实垛 --- √ /// const string plcReadStation_IsNotException1001 = $"DB622.0.2"; /// /// 系统正常---1003供实垛 --- √ --- 同1004 /// const string plcReadStation_IsNotException1003 = $"DB622.8.1"; /// /// 系统正常---1005供实垛 --- √ /// const string plcReadStation_IsNotException1005 = $"DB622.10.1"; /// /// 系统正常---1007供实垛 --- √ /// const string plcReadStation_IsNotException1007 = $"DB622.2.2"; /// /// 系统正常---1008供实垛 --- √ /// const string plcReadStation_IsNotException1008 = $"DB622.2.3"; /// /// 空托供应请求---1013供空托 --- √ /// const string plcReadStation_GetRequest1013 = $"DB622.7.1"; /// /// 空托供应请求---1002放空托 --- √ /// const string plcReadStation_PutRequest1002 = $"DB622.0.3"; /// /// 空托供应请求---1004放空托 --- √ /// const string plcReadStation_PutRequest1004 = $"DB622.9.2"; /// /// 空托供应请求---1006放空托 --- √ /// const string plcReadStation_PutRequest1006 = $"DB622.2.4"; /// /// 空托供应请求---1013供空托 --- √ /// const string plcReadStation_IsNotException1013 = $"DB622.6.1"; /// /// 系统正常---1002供空托 --- √ /// const string plcReadStation_IsNotException1002 = $"DB622.0.1"; /// /// 系统正常---1004供空托 --- √ --- 同1003 /// const string plcReadStation_IsNotException1004 = $"DB622.8.1"; /// /// 系统正常---1006供空托 --- √ /// const string plcReadStation_IsNotException1006 = $"DB622.2.1"; //******************************************2025.9新增1009、1010输送口放货允许信号****************************************** /// /// 放货允许---1009 --- √ /// const string plcReadStation_PutRequest1009 = $"DB2200.0.0"; /// /// 放货允许---1010 --- √ /// const string plcReadStation_PutRequest1010 = $"DB2200.4.0"; #endregion /// /// 通过外部获取PLC连接对象 /// /// public SiemensS7Net GetStationConnection() { return stationConnection; } /// /// 穿梭车初始化连接 /// public static void InitializeRgv() { #region 直读小车状态(已弃用) //for (int i = 0; i < circleRgvConnection.Length; i++) //{ // circleRgvConnection[i].ConnectTimeOut = 100; // OperateResult result = circleRgvConnection[i].ConnectServer(); // if (result.IsSuccess) // { // Log.Warning($"【设备连接初始化】{i + 1}#环穿初始化连接成功!"); // continue; // } // else // { // Log.Warning($"【设备连接初始化】{i + 1}#环穿初始化连接失败,{result.Message},错误代码:RgvData0001"); // } //} #endregion //Instance.GetStationConnection().ConnectTimeOut = 5000; Instance.GetStationConnection().ConnectTimeOut = 50; OperateResult result = stationConnection.ConnectServer(); if (result.IsSuccess) { Log.Warning($"【设备连接初始化】地面站初始化连接成功!"); return; } else { Log.Warning($"【设备连接初始化】地面站初始化连接失败,{result.Message},错误代码:RgvStationData0001"); } } /// /// 环穿plc连接---地面站 /// /// 1--正常 -1--失败 0-未知异常 [Obsolete] public static int PlcConnect() { if (stationConnection is null) { stationConnection = new SiemensS7Net(SiemensPLCS.S1500, ipStation); } try { stationConnection.ConnectTimeOut = 5000; //切换长连接 OperateResult result = Instance.GetStationConnection().ConnectServer(); if (result.IsSuccess) { return 1; } else { Instance.GetStationConnection().ConnectClose(); return 0; } } catch (Exception e) { Log.Warning($"地面站连接异常,{e.Message},错误代码:RGVStationData0003"); return -1; } } /// /// 获取环穿状态参数 /// /// 设备编号 /// 环穿状态参数 public static CircleRGVState? GetCircleRGVState(int id) { //if (PlcConnect(id) == -1) //{ // return null; //} using CircleRGVState circleRGVState = new CircleRGVState(); try { //设备状态 circleRGVState.Read_DeviceState = stationConnection.ReadInt16($"DB611.{20 + (id - 1) * 30}").Content; //任务号 circleRGVState.Read_TaskNumber = stationConnection.ReadInt32($"DB611.{34 + (id - 1) * 30}").Content; //任务类型 circleRGVState.Read_TaskType = 1; //操作模式 circleRGVState.Read_Mode = stationConnection.ReadInt16($"DB611.{22 + (id - 1) * 30}").Content; //执行阶段 circleRGVState.Read_Phase = stationConnection.ReadInt16($"DB611.{42 + (id - 1) * 30}").Content; //取货站点 circleRGVState.Read_SourceLocation = stationConnection.ReadInt16($"DB611.{38 + (id - 1) * 30}").Content.ToString(); //目标站点 circleRGVState.Read_TargetLocation = stationConnection.ReadInt16($"DB611.{40 + (id - 1) * 30}").Content.ToString(); //允许下发 circleRGVState.Read_Permission = stationConnection.ReadBool($"DB611.{44 + (id - 1) * 30}").Content; } catch (Exception) { return null; } return circleRGVState; } /// /// 获取全部环穿状态参数 /// /// 设备编号 /// 环穿状态参数 public static List? GetAllCircleRGVState() { //if (PlcConnect(id) == -1) //{ // return null; //} List circleRGVStates = new List(); for (int i = 1; i <= deviceCount; i++) { CircleRGVState circleRGVState = new CircleRGVState(); try { //设备状态 circleRGVState.Read_DeviceState = stationConnection.ReadInt16($"DB611.{20 + (i - 1) * 30}").Content; //任务号 circleRGVState.Read_TaskNumber = stationConnection.ReadInt32($"DB611.{34 + (i - 1) * 30}").Content; //任务类型 circleRGVState.Read_TaskType = 1; //操作模式 circleRGVState.Read_Mode = stationConnection.ReadInt16($"DB611.{22 + (i - 1) * 30}").Content; //执行阶段 circleRGVState.Read_Phase = stationConnection.ReadInt16($"DB611.{42 + (i - 1) * 30}").Content; //取货站点 circleRGVState.Read_SourceLocation = stationConnection.ReadInt16($"DB611.{38 + (i - 1) * 30}").Content.ToString(); //目标站点 circleRGVState.Read_TargetLocation = stationConnection.ReadInt16($"DB611.{40 + (i - 1) * 30}").Content.ToString(); //允许下发 circleRGVState.Read_Permission = stationConnection.ReadBool($"DB611.{44 + (i - 1) * 30}").Content; //里程 circleRGVState.Read_Mileage = stationConnection.ReadDouble($"DB{300 + i}.36").Content; circleRGVStates.Add(circleRGVState); } catch (Exception) { return null; } } return circleRGVStates; } /// /// 获取设备运行里程数 /// /// public List GetDeviceMileage() { List lists = new List(new double[deviceCount]); for (int i = 0; i < lists.Count; i++) { lists.Add(stationConnection.ReadDouble($"DB{300 + i + 1}.36").Content); } return lists; } /// /// 获取环穿地面站状态参数 /// /// 环穿状态参数 public static CircleRGVStationState? GetCircleRGVStaionState() { //if (PlcConnect() == -1) //{ // Log.Warning("【尝试获取地面站请求状态】地面站连接失败!"); // return null; //} CircleRGVStationState circleRGVStationState = new CircleRGVStationState(); try { //允许下发 circleRGVStationState.Read_Permission = stationConnection.ReadInt16(plcReadStation_Permission).Content; //下发状态 circleRGVStationState.Read_SendState = stationConnection.ReadInt16(plcReadStation_SendState).Content; //任务号 circleRGVStationState.Read_TaskNumber = stationConnection.ReadInt32(plcReadStation_TaskNumber).Content; //取货请求---1001出实垛 circleRGVStationState.Read_GetRequest_1001 = stationConnection.ReadBool(plcReadStation_GetRequest1001).Content; //取货请求---1003出实垛 circleRGVStationState.Read_GetRequest_1003 = stationConnection.ReadBool(plcReadStation_GetRequest1003).Content; //取货请求---1005出实垛 circleRGVStationState.Read_GetRequest_1005 = stationConnection.ReadBool(plcReadStation_GetRequest1005).Content; //取货请求---1007出实垛 circleRGVStationState.Read_GetRequest_1007 = stationConnection.ReadBool(plcReadStation_GetRequest1007).Content; //取货请求---1008出实垛 circleRGVStationState.Read_GetRequest_1008 = stationConnection.ReadBool(plcReadStation_GetRequest1008).Content; //系统正常---1001出实垛 circleRGVStationState.Read_IsNotException_1001 = stationConnection.ReadBool(plcReadStation_IsNotException1001).Content; //系统正常---1003出实垛 circleRGVStationState.Read_IsNotException_1003 = stationConnection.ReadBool(plcReadStation_IsNotException1003).Content; //系统正常---1005出实垛 circleRGVStationState.Read_IsNotException_1005 = stationConnection.ReadBool(plcReadStation_IsNotException1005).Content; //系统正常---1007出实垛 circleRGVStationState.Read_IsNotException_1007 = stationConnection.ReadBool(plcReadStation_IsNotException1007).Content; //系统正常---1008出实垛 circleRGVStationState.Read_IsNotException_1008 = stationConnection.ReadBool(plcReadStation_IsNotException1008).Content; //回空托请求---1013供空托请求 circleRGVStationState.Read_GetRequest_1013 = stationConnection.ReadBool(plcReadStation_GetRequest1013).Content; //回空托请求---1002空托请求 circleRGVStationState.Read_PutRequest_1002 = stationConnection.ReadBool(plcReadStation_PutRequest1002).Content; //回空托请求---1004空托请求 circleRGVStationState.Read_PutRequest_1004 = stationConnection.ReadBool(plcReadStation_PutRequest1004).Content; //回空托请求---1006空托请求 circleRGVStationState.Read_PutRequest_1006 = stationConnection.ReadBool(plcReadStation_PutRequest1006).Content; //系统正常---1002放空托 circleRGVStationState.Read_IsNotException_1002 = stationConnection.ReadBool(plcReadStation_IsNotException1002).Content; //系统正常---1004放空托 circleRGVStationState.Read_IsNotException_1004 = stationConnection.ReadBool(plcReadStation_IsNotException1004).Content; //系统正常---1006放空托 circleRGVStationState.Read_IsNotException_1006 = stationConnection.ReadBool(plcReadStation_IsNotException1006).Content; //**************************************************2025.9新增1009、1010输送口放货允许************************************************** //回空托请求---1004空托请求 circleRGVStationState.Read_PutRequest_1009 = stationConnection.ReadBool(plcReadStation_PutRequest1009).Content; //回空托请求---1006空托请求 circleRGVStationState.Read_PutRequest_1010 = stationConnection.ReadBool(plcReadStation_PutRequest1010).Content; } catch (Exception e) { Log.Warning($"【尝试获取地面站请求状态】读取地面站请求值失败!{e.Message}"); Log.Warning($"【尝试获取地面站请求状态】{e.InnerException}"); return null; } return circleRGVStationState; } /// /// 向环穿地面站下发指令 /// /// 指定下发环穿的编号 /// 环穿指令 public static bool SendRGVStationCommand(CircleRGVStationCommand circleRGVStationCommand) { //if (PlcConnect() == -1) //{ // //Log.Warning("【向地面站下发指令】尝试连接地面站失败!"); // return false; //} if (circleRGVStationCommand is null) { Log.Warning("【向地面站下发指令】下发指令为空【command is null】!"); return false; } //CircleRGVStationCommand circleRGVStationCommand1 = new CircleRGVStationCommand(); //circleRGVStationCommand1.Write_SourceLocation = (ushort)1009; //circleRGVStationCommand1.Write_TargetLocation = (ushort)1004; //circleRGVStationCommand1.Write_TaskNumber = 138181; //circleRGVStationCommand1.Write_DeviceNumber = (ushort)0; //circleRGVStationCommand1.Write_TaskType = (ushort)1; //int i = Checksum.GetChecksum(circleRGVStationCommand1); #region 有写入校验 //1. 校验写入是否成功 bool bTaskNumber = WritePlcForCheck(stationConnection, plcWriteStation_TaskNumber, circleRGVStationCommand.Write_TaskNumber); bool bSourceLocation = WritePlcForCheck(stationConnection, plcWriteStation_SourceLocation, (ushort)circleRGVStationCommand.Write_SourceLocation); bool bTargetLocation = WritePlcForCheck(stationConnection, plcWriteStation_TargetLocation, (ushort)circleRGVStationCommand.Write_TargetLocation); bool bTaskType = WritePlcForCheck(stationConnection, plcWriteStation_TaskType, (short)circleRGVStationCommand.Write_TaskType); bool bDeviceNumber = WritePlcForCheck(stationConnection, plcWriteStation_DeviceNumber, (short)circleRGVStationCommand.Write_DeviceNumber); bool bChecksum = WritePlcForCheck(stationConnection, plcWriteStation_Checksum, Checksum.GetChecksum(circleRGVStationCommand)); //以此判断地面站参数是否写入成功 if (!bTaskNumber) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务号读写错误!"); return false; } if (!bSourceLocation) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},源站点读写错误!"); return false; } if (!bTargetLocation) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},目标站点读写错误!"); return false; } if (!bTaskType) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务类型读写错误!"); return false; } if (!bDeviceNumber) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},设备编号读写错误!"); return false; } if (!bChecksum) { Log.Warning($"【WCS写入信息至地面站<写入异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码读写错误!"); return false; } //2. 检查下发站点是否合法 short sourceLocation = stationConnection.ReadInt16(plcWriteStation_SourceLocation).Content; short targetLocation = stationConnection.ReadInt16(plcWriteStation_TargetLocation).Content; //查找下发的源站点是否有对应的目标站点 var context = new AppDbContext(); var tar = context.LineState .Where(a => a.Source == sourceLocation && a.Target == targetLocation) .Count(); //站点非法---禁止下发 if (tar == 0) { Log.Warning( $"【WCS写入信息至地面站<检查到异常:非法站点>】任务号:{circleRGVStationCommand.Write_TaskNumber}," + $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " + $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " + $"取货站点:{(ushort)sourceLocation}, " + $"放货站点:{(ushort)targetLocation}, " + $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},下发失败!" ); return false; } //3. 写【下发完成】 OperateResult result = stationConnection.Write(plcWriteStation_SendFinish, (short)1); //下发完成写入成功 Log.Information( $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," + $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " + $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " + $"取货站点:{(ushort)sourceLocation}, " + $"放货站点:{(ushort)targetLocation}, " + $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},尝试下发任务!" ); //todo @@@可能需要判断设备是否已经开始执行 //todo @@@可能需要判断设备是否已经开始执行 //todo @@@可能需要判断设备是否已经开始执行 Task.Delay(100).Wait(); //【下发完成】写入操作成功 if (result.IsSuccess) { //获取所有输送口请求状态 CircleRGVStationState circleRGVStationState = GetCircleRGVStaionState(); //4. 获取地面站【下发状态】 int number = circleRGVStationState.Read_SendState; if (number == 1) { //下发完成写入成功 Log.Information( $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," + $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " + $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " + $"取货站点:{(ushort)sourceLocation}, " + $"放货站点:{(ushort)targetLocation}, " + $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},PLC反馈【接收正常】,下发成功!" ); //Log.Warning($"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写:{Checksum.GetChecksum(circleRGVStationCommand)},读:{stationConnection.ReadInt16("DB60.904").Content},测试测试测试"); } else { //需要详细了解可能【接收异常】的情况 //需要详细了解可能【接收异常】的情况 //需要详细了解可能【接收异常】的情况 Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},PLC反馈【接收异常】!"); Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写入:{Checksum.GetChecksum(circleRGVStationCommand)},读取:{stationConnection.ReadInt16("DB60.904").Content},PLC反馈【接收异常】!"); } //此处更新true的作用:就算【接收异常】,也可以更新任务状态,如果更新状态之后设备未执行,那么更新状态之后仍然可以定时重新下发 //可以避免由于某种意外原因导致的结果为false后设备执行但状态不更新的情况 return true; } else { Log.Warning($"【WCS写入信息至地面站<写入失败>】任务号:{circleRGVStationCommand.Write_TaskNumber},【下发完成】写入失败!"); return false; } #endregion } /// /// 向环穿地面站下发指令(手动无站点校验) /// /// 指定下发环穿的编号 /// 任意字符串 /// 环穿指令 public static bool SendRGVStationCommand(CircleRGVStationCommand circleRGVStationCommand, string msg) { //if (PlcConnect() == -1) //{ // //Log.Warning("【向地面站下发指令】尝试连接地面站失败!"); // return false; //} if (circleRGVStationCommand is null) { Log.Warning("【向地面站下发指令】下发指令为空【command is null】!"); return false; } //CircleRGVStationCommand circleRGVStationCommand1 = new CircleRGVStationCommand(); //circleRGVStationCommand1.Write_SourceLocation = (ushort)1009; //circleRGVStationCommand1.Write_TargetLocation = (ushort)1004; //circleRGVStationCommand1.Write_TaskNumber = 138181; //circleRGVStationCommand1.Write_DeviceNumber = (ushort)0; //circleRGVStationCommand1.Write_TaskType = (ushort)1; //int i = Checksum.GetChecksum(circleRGVStationCommand1); #region 有写入校验 //1. 校验写入是否成功 bool bTaskNumber = WritePlcForCheck(stationConnection, plcWriteStation_TaskNumber, circleRGVStationCommand.Write_TaskNumber); bool bSourceLocation = WritePlcForCheck(stationConnection, plcWriteStation_SourceLocation, (ushort)circleRGVStationCommand.Write_SourceLocation); bool bTargetLocation = WritePlcForCheck(stationConnection, plcWriteStation_TargetLocation, (ushort)circleRGVStationCommand.Write_TargetLocation); bool bTaskType = WritePlcForCheck(stationConnection, plcWriteStation_TaskType, (short)circleRGVStationCommand.Write_TaskType); bool bDeviceNumber = WritePlcForCheck(stationConnection, plcWriteStation_DeviceNumber, (short)circleRGVStationCommand.Write_DeviceNumber); bool bChecksum = WritePlcForCheck(stationConnection, plcWriteStation_Checksum, Checksum.GetChecksum(circleRGVStationCommand)); //以此判断地面站参数是否写入成功 if (!bTaskNumber) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务号读写错误!"); return false; } if (!bSourceLocation) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},源站点读写错误!"); return false; } if (!bTargetLocation) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},目标站点读写错误!"); return false; } if (!bTaskType) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务类型读写错误!"); return false; } if (!bDeviceNumber) { Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},设备编号读写错误!"); return false; } if (!bChecksum) { Log.Warning($"【WCS写入信息至地面站<写入异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码读写错误!"); return false; } //2. 检查下发站点是否合法 short sourceLocation = stationConnection.ReadInt16(plcWriteStation_SourceLocation).Content; short targetLocation = stationConnection.ReadInt16(plcWriteStation_TargetLocation).Content; //查找下发的源站点是否有对应的目标站点 var context = new AppDbContext(); var tar = context.LineState .Where(a => a.Source == sourceLocation) .Select(a => a.Target) .FirstOrDefault(); //站点非法 --- 禁止下发 if (tar != targetLocation || tar == 0) { Log.Warning( $"【WCS写入信息至地面站<检查到异常:非法站点>】任务号:{circleRGVStationCommand.Write_TaskNumber}," + $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " + $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " + $"取货站点:{(ushort)sourceLocation}, " + $"放货站点:{(ushort)targetLocation}, " + $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},下发失败!" ); return false; } //3. 写【下发完成】 OperateResult result = stationConnection.Write(plcWriteStation_SendFinish, (short)1); //下发完成写入成功 Log.Information( $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," + $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " + $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " + $"取货站点:{(ushort)sourceLocation}, " + $"放货站点:{(ushort)targetLocation}, " + $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},尝试下发任务!" ); //todo @@@可能需要判断设备是否已经开始执行 //todo @@@可能需要判断设备是否已经开始执行 //todo @@@可能需要判断设备是否已经开始执行 Task.Delay(100).Wait(); //【下发完成】写入操作成功 if (result.IsSuccess) { //获取所有输送口请求状态 CircleRGVStationState circleRGVStationState = GetCircleRGVStaionState(); //4. 获取地面站【下发状态】 int number = circleRGVStationState.Read_SendState; if (number == 1) { //下发完成写入成功 Log.Information( $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," + $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " + $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " + $"取货站点:{(ushort)sourceLocation}, " + $"放货站点:{(ushort)targetLocation}, " + $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},PLC反馈【接收正常】,下发成功!" ); //Log.Warning($"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写:{Checksum.GetChecksum(circleRGVStationCommand)},读:{stationConnection.ReadInt16("DB60.904").Content},测试测试测试"); } else { //需要详细了解可能【接收异常】的情况 //需要详细了解可能【接收异常】的情况 //需要详细了解可能【接收异常】的情况 Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},PLC反馈【接收异常】!"); Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写入:{Checksum.GetChecksum(circleRGVStationCommand)},读取:{stationConnection.ReadInt16("DB60.904").Content},PLC反馈【接收异常】!"); } //此处更新true的作用:就算【接收异常】,也可以更新任务状态,如果更新状态之后设备未执行,那么更新状态之后仍然可以定时重新下发 //可以避免由于某种意外原因导致的结果为false后设备执行但状态不更新的情况 return true; } else { Log.Warning($"【WCS写入信息至地面站<写入失败>】任务号:{circleRGVStationCommand.Write_TaskNumber},【下发完成】写入失败!"); return false; } #endregion } #region 环穿显示在界面的状态参数/属性 //---------------执行阶段--------------- [ObservableProperty] ObservableCollection _phases = new ObservableCollection(new short[RGVStation.RGVCount]); //---------------设备状态--------------- [ObservableProperty] ObservableCollection _deviceStates = new ObservableCollection(new short[RGVStation.RGVCount]); //----------------任务号---------------- [ObservableProperty] ObservableCollection _taskNumbers = new ObservableCollection(new int[RGVStation.RGVCount]); //---------------任务类型--------------- [ObservableProperty] ObservableCollection _taskTypes = new ObservableCollection(new short[RGVStation.RGVCount]); //---------------操作模式--------------- [ObservableProperty] ObservableCollection _mode = new ObservableCollection(new short[RGVStation.RGVCount]); //---------------源站点--------------- [ObservableProperty] ObservableCollection _sourceLocations = new ObservableCollection(new string[RGVStation.RGVCount]); //---------------目标站点--------------- [ObservableProperty] ObservableCollection _targetLocations = new ObservableCollection(new string[RGVStation.RGVCount]); #endregion /// /// 环穿状态初始化/加载 /// void CircleRGVStateInitialize() { CircleRGVStates.Clear(); for (int i = 0; i < RGVStation.RGVCount; i++) { CircleRGVStates.Add(new CircleRGVState() { Title = $"{i + 1}#环穿", Read_Phase = Phases[i], Read_DeviceState = DeviceStates[i], Read_TaskNumber = TaskNumbers[i], Read_Mode = Mode[i], Read_SourceLocation = SourceLocations[i], Read_TargetLocation = TargetLocations[i] }); } #region //CircleRGVStates.Add(new CircleRGVState() { Title = "1#环穿", Read_Phase = Phases[0], Read_DeviceState = DeviceStates[0], Read_TaskNumber = TaskNumbers[0], Read_Mode = Mode[0], Read_SourceLocation = SourceLocations[0], Read_TargetLocation = TargetLocations[0] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "2#环穿", Read_Phase = Phases[1], Read_DeviceState = DeviceStates[1], Read_TaskNumber = TaskNumbers[1], Read_Mode = Mode[1], Read_SourceLocation = SourceLocations[1], Read_TargetLocation = TargetLocations[1] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "3#环穿", Read_Phase = Phases[2], Read_DeviceState = DeviceStates[2], Read_TaskNumber = TaskNumbers[2], Read_Mode = Mode[2], Read_SourceLocation = SourceLocations[2], Read_TargetLocation = TargetLocations[2] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "4#环穿", Read_Phase = Phases[3], Read_DeviceState = DeviceStates[3], Read_TaskNumber = TaskNumbers[3], Read_Mode = Mode[3], Read_SourceLocation = SourceLocations[3], Read_TargetLocation = TargetLocations[3] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "5#环穿", Read_Phase = Phases[4], Read_DeviceState = DeviceStates[4], Read_TaskNumber = TaskNumbers[4], Read_Mode = Mode[4], Read_SourceLocation = SourceLocations[4], Read_TargetLocation = TargetLocations[4] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "6#环穿", Read_Phase = Phases[5], Read_DeviceState = DeviceStates[5], Read_TaskNumber = TaskNumbers[5], Read_Mode = Mode[5], Read_SourceLocation = SourceLocations[5], Read_TargetLocation = TargetLocations[5] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "7#环穿", Read_Phase = Phases[6], Read_DeviceState = DeviceStates[6], Read_TaskNumber = TaskNumbers[6], Read_Mode = Mode[6], Read_SourceLocation = SourceLocations[6], Read_TargetLocation = TargetLocations[6] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "8#环穿", Read_Phase = Phases[7], Read_DeviceState = DeviceStates[7], Read_TaskNumber = TaskNumbers[7], Read_Mode = Mode[7], Read_SourceLocation = SourceLocations[7], Read_TargetLocation = TargetLocations[7] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "9#环穿", Read_Phase = Phases[8], Read_DeviceState = DeviceStates[8], Read_TaskNumber = TaskNumbers[8], Read_Mode = Mode[8], Read_SourceLocation = SourceLocations[8], Read_TargetLocation = TargetLocations[8] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "10#环穿", Read_Phase = Phases[9], Read_DeviceState = DeviceStates[9], Read_TaskNumber = TaskNumbers[9], Read_Mode = Mode[9], Read_SourceLocation = SourceLocations[9], Read_TargetLocation = TargetLocations[9] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "11#环穿", Read_Phase = Phases[10], Read_DeviceState = DeviceStates[10], Read_TaskNumber = TaskNumbers[10], Read_Mode = Mode[10], Read_SourceLocation = SourceLocations[10], Read_TargetLocation = TargetLocations[10] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "12#环穿", Read_Phase = Phases[11], Read_DeviceState = DeviceStates[11], Read_TaskNumber = TaskNumbers[11], Read_Mode = Mode[11], Read_SourceLocation = SourceLocations[11], Read_TargetLocation = TargetLocations[11] }); //CircleRGVStates.Add(new CircleRGVState() { Title = "13#环穿", Read_Phase = Phases[12], Read_DeviceState = DeviceStates[12], Read_TaskNumber = TaskNumbers[12], Read_Mode = Mode[12], Read_SourceLocation = SourceLocations[12], Read_TargetLocation = TargetLocations[12] }); #endregion } //================需要校验【是否写入成功】的写入操作================ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, bool value) { if (siemens.Write(address, value).IsSuccess) { if (value == siemens.ReadBool(address).Content) { return true; } else { return false; } } else { return false; } } private static bool WritePlcForCheck(SiemensS7Net siemens, string address, short value) { if (siemens.Write(address, value).IsSuccess) { OperateResult result = siemens.ReadInt16(address); if (value == result.Content) { return true; } else { return false; } } else { return false; } } private static bool WritePlcForCheck(SiemensS7Net siemens, string address, ushort value) { if (siemens.Write(address, value).IsSuccess) { OperateResult result = siemens.ReadUInt16(address); if (value == result.Content) { return true; } else { return false; } } else { return false; } } private static bool WritePlcForCheck(SiemensS7Net siemens, string address, int value) { if (siemens.Write(address, value).IsSuccess) { OperateResult result = siemens.ReadInt32(address); if (value == result.Content) { return true; } else { return false; } } else { return false; } } private static bool WritePlcForCheck(SiemensS7Net siemens, string address, uint value) { if (siemens.Write(address, value).IsSuccess) { if (value == siemens.ReadUInt32(address).Content) { return true; } else { return false; } } else { return false; } } private static bool WritePlcForCheck(SiemensS7Net siemens, string address, string value) { if (siemens.Write(address, value).IsSuccess) { if (value == siemens.ReadString(address).Content) { return true; } else { return false; } } else { return false; } } } }