Files
FT479/WPFWCSDemo/ViewModels/CircleRGVsViewModel.cs
2026-06-29 14:46:32 +08:00

1116 lines
47 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// 用于监控环穿状态参数的定时器
/// </summary>
private DispatcherTimer dispatcherTimer;
static int deviceCount = RGVStation.RGVCount;
private CircleRGVsViewModel()
{
States = new ObservableCollection<CircleRGVState>();
CircleRGVStates = new ObservableCollection<CircleRGVState>();
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}#环穿读取错误!");
}
}
}
/// <summary>
/// 状态参数监控集合
/// </summary>
[ObservableProperty]
ObservableCollection<CircleRGVState> _states;
/// <summary>
/// 环穿入出对应的路径
/// </summary>
public static Dictionary<int, int> route = new Dictionary<int, int>()
{
{1001, 1012},
{1003, 1009},
{1005, 1010},
{1007, 1011},
{1008, 1011},
};
/// <summary>
/// 环穿状态集合
/// </summary>
[ObservableProperty]
ObservableCollection<CircleRGVState> _circleRGVStates;
/// <summary>
/// 穿梭车plc连接
/// </summary>
[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"),
};
/// <summary>
/// 地面站plc连接
/// </summary>
private static SiemensS7Net stationConnection = new SiemensS7Net(SiemensPLCS.S1500, ipStation);
//初始化懒加载---保证线程安全
private static readonly Lazy<CircleRGVsViewModel> instanceHolder =
new(()=>new CircleRGVsViewModel(),LazyThreadSafetyMode.ExecutionAndPublication);
//外部获取类实例
public static CircleRGVsViewModel Instance
{
get { return instanceHolder.Value; }
}
/// <summary>
/// 地面站plc IP
/// </summary>
const string ipStation = "192.168.6.100";
#region 地面站plc参数地址
//====================环穿写入:plc地址====================
/// <summary>
/// 任务号
/// </summary>
const string plcWriteStation_TaskNumber = $"DB610.0";
/// <summary>
/// 取货站点
/// </summary>
const string plcWriteStation_SourceLocation = $"DB610.4";
/// <summary>
/// 放货站点
/// </summary>
const string plcWriteStation_TargetLocation = $"DB610.6";
/// <summary>
/// 任务类型
/// </summary>
const string plcWriteStation_TaskType = $"DB610.8";
/// <summary>
/// 小车编号(任意数字-plc自行判断)
/// </summary>
const string plcWriteStation_DeviceNumber = $"DB610.10";
/// <summary>
/// 下发完成
/// </summary>
const string plcWriteStation_SendFinish = $"DB610.12";
/// <summary>
/// 检验码
/// </summary>
const string plcWriteStation_Checksum = $"DB610.14";
//====================环穿读取:plc地址====================
/// <summary>
/// 允许下发
/// </summary>
const string plcReadStation_Permission = $"DB611.0";
/// <summary>
/// 下发状态
/// </summary>
const string plcReadStation_SendState = $"DB611.2";
/// <summary>
/// 任务号
/// </summary>
const string plcReadStation_TaskNumber = $"DB611.4";
#endregion
#region 输送请求
/// <summary>
/// 取货请求---1001供应实垛 --- √
/// </summary>
const string plcReadStation_GetRequest1001 = $"DB622.0.4";
/// <summary>
/// 取货请求---1003供应实垛 --- √
/// </summary>
const string plcReadStation_GetRequest1003 = $"DB622.9.1";
/// <summary>
/// 取货请求---1005供应实垛 --- √
/// </summary>
const string plcReadStation_GetRequest1005 = $"DB622.11.1";
/// <summary>
/// 取货请求---1007供应实垛 --- √
/// </summary>
const string plcReadStation_GetRequest1007 = $"DB622.2.5";
/// <summary>
/// 取货请求---1008供应实垛 --- √
/// </summary>
const string plcReadStation_GetRequest1008 = $"DB622.2.6";
/// <summary>
/// 系统正常---1001供实垛 --- √
/// </summary>
const string plcReadStation_IsNotException1001 = $"DB622.0.2";
/// <summary>
/// 系统正常---1003供实垛 --- √ --- 同1004
/// </summary>
const string plcReadStation_IsNotException1003 = $"DB622.8.1";
/// <summary>
/// 系统正常---1005供实垛 --- √
/// </summary>
const string plcReadStation_IsNotException1005 = $"DB622.10.1";
/// <summary>
/// 系统正常---1007供实垛 --- √
/// </summary>
const string plcReadStation_IsNotException1007 = $"DB622.2.2";
/// <summary>
/// 系统正常---1008供实垛 --- √
/// </summary>
const string plcReadStation_IsNotException1008 = $"DB622.2.3";
/// <summary>
/// 空托供应请求---1013供空托 --- √
/// </summary>
const string plcReadStation_GetRequest1013 = $"DB622.7.1";
/// <summary>
/// 空托供应请求---1002放空托 --- √
/// </summary>
const string plcReadStation_PutRequest1002 = $"DB622.0.3";
/// <summary>
/// 空托供应请求---1004放空托 --- √
/// </summary>
const string plcReadStation_PutRequest1004 = $"DB622.9.2";
/// <summary>
/// 空托供应请求---1006放空托 --- √
/// </summary>
const string plcReadStation_PutRequest1006 = $"DB622.2.4";
/// <summary>
/// 空托供应请求---1013供空托 --- √
/// </summary>
const string plcReadStation_IsNotException1013 = $"DB622.6.1";
/// <summary>
/// 系统正常---1002供空托 --- √
/// </summary>
const string plcReadStation_IsNotException1002 = $"DB622.0.1";
/// <summary>
/// 系统正常---1004供空托 --- √ --- 同1003
/// </summary>
const string plcReadStation_IsNotException1004 = $"DB622.8.1";
/// <summary>
/// 系统正常---1006供空托 --- √
/// </summary>
const string plcReadStation_IsNotException1006 = $"DB622.2.1";
//******************************************2025.9新增1009、1010输送口放货允许信号******************************************
/// <summary>
/// 放货允许---1009 --- √
/// </summary>
const string plcReadStation_PutRequest1009 = $"DB2200.0.0";
/// <summary>
/// 放货允许---1010 --- √
/// </summary>
const string plcReadStation_PutRequest1010 = $"DB2200.4.0";
#endregion
/// <summary>
/// 通过外部获取PLC连接对象
/// </summary>
/// <returns></returns>
public SiemensS7Net GetStationConnection()
{
return stationConnection;
}
/// <summary>
/// 穿梭车初始化连接
/// </summary>
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");
}
}
/// <summary>
/// 环穿plc连接---地面站
/// </summary>
/// <returns>1--正常 -1--失败 0-未知异常</returns>
[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;
}
}
/// <summary>
/// 获取环穿状态参数
/// </summary>
/// <param name="id">设备编号</param>
/// <returns>环穿状态参数</returns>
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;
}
/// <summary>
/// 获取全部环穿状态参数
/// </summary>
/// <param name="id">设备编号</param>
/// <returns>环穿状态参数</returns>
public static List<CircleRGVState>? GetAllCircleRGVState()
{
//if (PlcConnect(id) == -1)
//{
// return null;
//}
List<CircleRGVState> circleRGVStates = new List<CircleRGVState>();
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;
}
/// <summary>
/// 获取设备运行里程数
/// </summary>
/// <returns></returns>
public List<double> GetDeviceMileage()
{
List<double> lists = new List<double>(new double[deviceCount]);
for (int i = 0; i < lists.Count; i++)
{
lists.Add(stationConnection.ReadDouble($"DB{300 + i + 1}.36").Content);
}
return lists;
}
/// <summary>
/// 获取环穿地面站状态参数
/// </summary>
/// <returns>环穿状态参数</returns>
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;
}
/// <summary>
/// 向环穿地面站下发指令
/// </summary>
/// <param name="id">指定下发环穿的编号</param>
/// <param name="circleRGVCommand">环穿指令</param>
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
}
/// <summary>
/// 向环穿地面站下发指令(手动无站点校验)
/// </summary>
/// <param name="id">指定下发环穿的编号</param>
/// <param name="msg">任意字符串</param>
/// <param name="circleRGVCommand">环穿指令</param>
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<short> _phases = new ObservableCollection<short>(new short[RGVStation.RGVCount]);
//---------------设备状态---------------
[ObservableProperty]
ObservableCollection<short> _deviceStates = new ObservableCollection<short>(new short[RGVStation.RGVCount]);
//----------------任务号----------------
[ObservableProperty]
ObservableCollection<int> _taskNumbers = new ObservableCollection<int>(new int[RGVStation.RGVCount]);
//---------------任务类型---------------
[ObservableProperty]
ObservableCollection<short> _taskTypes = new ObservableCollection<short>(new short[RGVStation.RGVCount]);
//---------------操作模式---------------
[ObservableProperty]
ObservableCollection<short> _mode = new ObservableCollection<short>(new short[RGVStation.RGVCount]);
//---------------源站点---------------
[ObservableProperty]
ObservableCollection<string> _sourceLocations = new ObservableCollection<string>(new string[RGVStation.RGVCount]);
//---------------目标站点---------------
[ObservableProperty]
ObservableCollection<string> _targetLocations = new ObservableCollection<string>(new string[RGVStation.RGVCount]);
#endregion
/// <summary>
/// 环穿状态初始化/加载
/// </summary>
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<short> 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<ushort> 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<int> 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;
}
}
}
}