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;
}
}
}
}