using LogLibrary.Log;
|
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Logging;
|
using Newtonsoft.Json;
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Reflection;
|
using System.Text;
|
using WIDESEA_Common;
|
using WIDESEA_Core;
|
using WIDESEA_Core.Enums;
|
using WIDESEA_Core.Helper;
|
using WIDESEA_DTO.AGV;
|
using WIDESEA_DTO;
|
using WIDESEA_IStorageBasicRepository;
|
using WIDESEA_IStorageSocketServices;
|
using WIDESEA_IStorageTaskRepository;
|
using WIDESEA_Model.Models.AGV;
|
using WIDESEA_Model.Models;
|
using WIDESEAWCS_BasicInfoRepository;
|
using WIDESEAWCS_Model.Models;
|
using WIDESEA_Core.BaseRepository;
|
using AutoMapper;
|
using Mapster;
|
using AngleSharp.Dom;
|
using Masuit.Tools.Security;
|
using WIDESEA_IStorageTaskServices;
|
using System.Threading.Tasks;
|
using Microsoft.Extensions.DependencyInjection;
|
using WIDESEA_IBusinessesRepository;
|
using WIDESEA_Repository;
|
using static MailKit.Telemetry;
|
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
|
using System.Runtime.InteropServices;
|
|
namespace WIDESEA_StorageSocketServices
|
{
|
public class SocketClientService : ISocketClientServices
|
{
|
System.Net.Sockets.Socket socket;
|
const byte STX = 2;
|
const byte ETX = 3;
|
private readonly ILogger<SocketClientService> _logger;
|
private readonly LogFactory LogFactory = new LogFactory();
|
private readonly IDt_StationManagerRepository _stationManagerRepository;
|
private readonly IDt_TaskRepository BaseDal;
|
Connection connection = AppSettings.Configuration.GetSection("Connection").Get<Connection>();
|
string url = AppSettings.Configuration["AGVIP"];
|
private readonly IDt_TaskService _taskService;
|
private readonly IDt_HostLogRepository _hostLogRepository;
|
private bool _IsOnline=false;
|
public DateTime Time { get; set; } = DateTime.Now;
|
|
|
public SocketClientService(IDt_TaskService TaskService, IDt_TaskRepository TaskRepository, IDt_StationManagerRepository stationManagerRepository, ILogger<SocketClientService> logger,IDt_HostLogRepository hostLogRepository)
|
{
|
BaseDal = TaskRepository;
|
_stationManagerRepository = stationManagerRepository;
|
_logger = logger;
|
_taskService = TaskService;
|
_hostLogRepository = hostLogRepository;
|
}
|
|
/// <summary>
|
/// TCPSocket连接
|
/// </summary>
|
/// <param name="IP"></param>
|
/// <param name="Port"></param>
|
public void ConnectServer(string IP, int Port)
|
{
|
try
|
{
|
// 检查是否已连接,避免重复创建
|
if (socket != null && socket.Connected)
|
{
|
ConsoleHelper.WriteErrorLine($"Socket已处于连接状态");
|
return;
|
}
|
|
//创建负责通信的socket
|
socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
IPAddress ip = IPAddress.Parse(IP);
|
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(Port));
|
|
//获得要连接的远程服务器应用程序的IP地址和端口号
|
socket.Connect(point);
|
|
_logger.LogInformation("Socket连接成功");
|
ConsoleHelper.WriteSuccessLine("Socket连接成功");
|
|
DeleteHostLog(910);
|
|
_IsOnline = true;
|
RequestCommunication();
|
AGVStatusRespone status = GetAGVStatus();
|
|
DeviceStateReport(GetAGVStatus(status.RuntimeStatus));
|
|
//开启一个新的线程不停的接收服务端发来的信息
|
Thread th = new Thread(Receive);
|
th.IsBackground = true;
|
th.Start();
|
return;
|
}
|
catch (Exception ex)
|
{
|
_IsOnline = false;
|
ConsoleHelper.WriteErrorLine($"Socket连接失败{ex.Message}");
|
HandleDisconnection();
|
}
|
}
|
|
|
public bool Socketonline()
|
{
|
return _IsOnline;
|
}
|
|
/// <summary>
|
/// 线程读取数据
|
/// </summary>
|
void Receive()
|
{
|
Time = DateTime.Now;
|
while (true)
|
{
|
try
|
{
|
byte[] buffer = new byte[1024]; // 接收缓冲区
|
int bytesReceived = socket.Receive(buffer); // 接收数据
|
byte[] receivedData = new byte[bytesReceived];
|
|
Array.Copy(buffer, receivedData, bytesReceived); // 复制有效数据
|
var Y = Encoding.UTF8.GetString(receivedData);
|
|
// 检查是否以 STX 开头、ETX 结尾
|
if (receivedData[0] == STX && receivedData[receivedData.Length - 1] == ETX)
|
{
|
int newLength = receivedData.Length - 2;
|
int newCheckSumLength = receivedData.Length - 3;
|
|
if (newLength < 0)
|
{
|
throw new ArgumentException("数组长度不足,无法去掉最后两位。");
|
}
|
|
byte[] newArray = new byte[newLength];
|
|
Array.Copy(receivedData, 1, newArray, 0, newLength);
|
string calculatedChecksum = GetCheckSumone(newArray);
|
|
var str = Encoding.UTF8.GetString(newArray);
|
string receivedChecksum = str.Substring(str.Length - 2);
|
|
LogFactory.GetLog("接收Socket数据").Info(true, $"{JsonConvert.SerializeObject(GetParse(str))}{Environment.NewLine}");
|
if (calculatedChecksum == receivedChecksum)
|
{
|
var x = Encoding.UTF8.GetString(newArray);
|
ParseMessage parseMessage = new ParseMessage()
|
{
|
bDir = x.Substring(0, 1),
|
bObjID = x.Substring(2, 10),
|
bReply = x.Substring(11, 1),
|
bCmdID = x.Substring(12, 3),
|
nSeqNo = x.Substring(15, 5),
|
};
|
ProcessCommand(parseMessage.bCmdID, x);
|
}
|
else
|
{
|
CheckSum("3");
|
LogFactory.GetLog("Socket接收数据").Error(true, $"CheckSum校验失败,解析{calculatedChecksum}、读取{receivedChecksum}");
|
}
|
}
|
else
|
{
|
LogFactory.GetLog("Socket接收数据").Error(true, $"无效报文格式:{JsonConvert.SerializeObject(Y)}{Environment.NewLine}");
|
}
|
}
|
catch
|
{
|
_IsOnline = false;
|
HandleDisconnection();
|
}
|
}
|
}
|
|
|
/// <summary>
|
/// 作业JobType
|
/// </summary>
|
/// <param name="cmdId"></param>
|
/// <param name="x"></param>
|
private void ProcessCommand(string cmdId, string x)
|
{
|
switch (cmdId)
|
{
|
case "102":
|
ReceiveCommandResponse(x);
|
break;
|
case "906":
|
AGVJobStartOrEndResponse(x.Substring(20, 1), x.Substring(21, 1));
|
break;
|
case "902":
|
DataReportResponse(x.Substring(20, 1));
|
break;
|
case "935":
|
DeviceStationStatusInvite(x.Substring(15, 5));
|
break;
|
case "103":
|
HOSTOutBoundTask(x);
|
break;
|
case "106":
|
RecreateGetLocation(x);
|
break;
|
case "108":
|
EmptyOutBoundResponse(x.Substring(20, 1));
|
break;
|
case "909":
|
DeviceStatusReportRequest();
|
break;
|
case "987":
|
FireAlarm(x.Substring(21, 6), x.Substring(15, 5));
|
break;
|
case "301":
|
UpdateLocalTime(x.Substring(30), x.Substring(15, 5));
|
break;
|
case "918":
|
break;
|
default:
|
CheckSum("1");
|
break;
|
}
|
}
|
|
#region
|
//private void HandleDisconnection()
|
//{
|
// int attempts = 100;
|
// do
|
// {
|
// string message = "连接已断开..." + '\n';
|
// message += "等待5秒后重新连接" + '\n';
|
// Console.WriteLine(message);
|
|
// // 关闭当前连接
|
// try
|
// {
|
// socket?.Close();
|
// }
|
// catch { }
|
|
// // 等待5秒
|
// Thread.Sleep(5000);
|
|
// // 尝试重新连接
|
// ConnectServer(connection.IP, connection.Port);
|
// attempts--;
|
// } while (!socket.Connected && attempts > 0);
|
//}
|
#endregion
|
|
/// <summary>
|
/// 重连
|
/// </summary>
|
public void HandleDisconnection()
|
{
|
int maxAttempts = 10; // 最大尝试次数
|
int currentAttempts = 0;
|
|
while (currentAttempts < maxAttempts)
|
{
|
string message = "与Host系统连接已断开..." + '\n';
|
message += "等待5秒后重新连接" + '\n';
|
Console.WriteLine(message);
|
|
// 关闭当前连接
|
try
|
{
|
socket?.Close();
|
}
|
catch { }
|
|
// 等待5秒
|
Thread.Sleep(5000);
|
|
// 尝试重新连接
|
ConnectServer(connection.IP, connection.Port);
|
currentAttempts++;
|
|
// 检查是否已连接
|
if (socket?.Connected ?? false)
|
{
|
break; // 连接成功,退出循环
|
}
|
}
|
|
if (currentAttempts >= maxAttempts)
|
{
|
Console.WriteLine("已达到最大重连次数,停止重连。");
|
// 可以在这里进行其他处理,例如通知用户或记录日志
|
}
|
}
|
|
/// <summary>
|
/// 下发
|
/// </summary>
|
/// <param name="buffer"></param>
|
public void clientSend(byte[] buffer)
|
{
|
socket.Send(buffer);
|
|
|
int newLength = buffer.Length - 2;
|
byte[] newArray = new byte[newLength];
|
|
Array.Copy(buffer, 1, newArray, 0, newLength);
|
string calculatedChecksum = GetCheckSumone(newArray);
|
|
var str = Encoding.UTF8.GetString(newArray);
|
string receivedChecksum = str.Substring(str.Length - 2);
|
|
var x = Encoding.UTF8.GetString(newArray);
|
|
LogFactory.GetLog("Socket发送数据").Info(true, $"{JsonConvert.SerializeObject(GetParse(x))}{Environment.NewLine}");
|
}
|
|
/// <summary>
|
/// CheckSum解析
|
/// </summary>
|
/// <param name="x"></param>
|
/// <returns></returns>
|
/// <exception cref="Exception"></exception>
|
public string GetCheckSumone(byte[] x)
|
{
|
int sum = 0;
|
try
|
{
|
for (int i = 0; i < x.Length - 2; i++)
|
{
|
sum += x[i];
|
}
|
string str = sum.ToString();
|
return str.Substring(str.Length - 2);
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
}
|
|
|
#region 常量
|
//public const byte STX = 2;
|
//public const byte ETX = 3;
|
|
/// <summary>
|
/// 作业任务ID 预留
|
/// </summary>
|
public const string JobOrderID = "0000000000000000";
|
|
public const string JobOrderIDPDA = "PDA0000000000000";
|
|
public const string JobOrderIDF = "FIRE000000000000";
|
|
/// <summary>
|
/// 优先级 预留
|
/// </summary>
|
public const string priority = "1";
|
|
/// <summary>
|
/// 重入库
|
/// </summary>
|
public const string Restocking = "2100";
|
|
|
public const string EmptyOutBoundconst = "2101";
|
|
/// <summary>
|
/// 托盘个数 预留
|
/// </summary>
|
public const string TrayCnt = "1";
|
|
/// <summary>
|
/// 设备编号
|
/// </summary>
|
public const string DeviceID = "0013130010";
|
/// <summary>
|
/// 发送不需要回复
|
/// </summary>
|
public const string SendNotReply = "1" + DeviceID + "0";
|
/// <summary>
|
/// 发送需要回复
|
/// </summary>
|
public const string SendandReply = "1" + DeviceID + "1";
|
/// <summary>
|
/// 出库站台启用已分配任务
|
/// </summary>
|
public const string OutBoundStationEnableDistribution = "1000";
|
/// <summary>
|
/// 出库站台启用未分配任务
|
/// </summary>
|
public const string OutBoundStationEnableUndistributed = "1100";
|
/// <summary>
|
/// 出库站台禁用
|
/// </summary>
|
public const string OutBoundStationDisabled = "0000";
|
/// <summary>
|
/// 入库站台个数
|
/// </summary>
|
public const string InBoundStationCount = "1";
|
|
/// <summary>
|
/// 入库站台状态
|
/// </summary>
|
public const string InBoundStationStatus = "1010001";
|
/// <summary>
|
/// 预留
|
/// </summary>
|
public const string Spare1 = "0000000000000000000000000000000000000000000000000000000000000000000000";
|
|
/// <summary>
|
/// 出库站台预留
|
/// </summary>
|
public const string OutStationSpare2 = "000000000000";
|
|
/// <summary>
|
/// 预留
|
/// </summary>
|
public const string Spare3 = "000";
|
|
/// <summary>
|
/// 托盘号
|
/// </summary>
|
public const string Spare4 = "0000000000";
|
|
#endregion
|
|
#region WMS下发HOST方法
|
|
/// <summary>
|
/// 设备请求入库 工序101
|
/// </summary>
|
/// <param name="PallteCode">托盘号</param>
|
/// <param name="InStation">入库站台</param>
|
public void DeviceRequestInbound(HOSTAGVStatus Agvstatus, List<OutStationStatus> outStations, InStationStatus inStation)
|
{
|
try
|
{
|
string str = SendandReply + "101" + BaseDal.GetSeqNo().Result.ToString("D5") + GetFieldsAsString(Agvstatus) + GetListStringOutStation(outStations) + OutStationSpare2 + "1" + GetFieldsAsString(inStation);
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("DeviceRequestInbound").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// <summary>
|
/// 请求通讯 工序925
|
/// </summary>
|
/// <param name="PallteCode">托盘号</param>
|
/// <param name="InStation">入库站台</param>
|
public void RequestCommunication()
|
{
|
try
|
{
|
string str = SendandReply + "925" + BaseDal.GetSeqNo().Result.ToString("D5");
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("RequestCommunication").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// <summary>
|
/// 不允许下发任务 工序915
|
/// </summary>
|
/// <param name="Command">命令</param>
|
/// <returns></returns>
|
public void JobReady(string Command)
|
{
|
try
|
{
|
string str = SendNotReply + "915" + BaseDal.GetSeqNo().Result.ToString("D5") + Command;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("JobReady").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// 设备状态上报 工序913
|
/// </summary>
|
/// <param name="state">状态\、R运行</param>
|
/// <returns></returns>
|
public void DeviceStateReport(string Status)
|
{
|
try
|
{
|
string str = SendNotReply + "913" + BaseDal.GetSeqNo().Result.ToString("D5") + Status;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("DeviceStateReport").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// 设备状态上报 工序917
|
/// </summary>
|
/// <param name="state">状态\、R运行</param>
|
/// <returns></returns>
|
public void DeviceAutoStatusReport(string Status)
|
{
|
try
|
{
|
string str = SendandReply + "917" + BaseDal.GetSeqNo().Result.ToString("D5") + Status;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("DeviceAutoStatusReport").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// /// <summary>
|
/// 作业开始或结束 工序905
|
/// </summary>
|
/// <param name="Status">状态 L指AGV将托盘叉到货叉上、U指AGV将托盘放到库位上</param>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="TaskType">任务类型 I入库、O出库、S站台到站台、R移库</param>
|
/// <param name="PallteCode">托盘号</param>
|
public void JobStartOrEnd(string Status, string FormLocation, string ToLocation, string TaskType, string PallteCode)
|
{
|
try
|
{
|
string str = SendandReply + "905" + BaseDal.GetSeqNo().Result.ToString("D5") + Status + JobOrderID + priority + FormLocation + ToLocation + TaskType + TrayCnt + PallteCode;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("JobStartOrEnd").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// 托盘动作上报 工序907
|
/// </summary>
|
/// <param name="Status">状态 L指AGV将托盘叉到货叉上、U指AGV将托盘放到库位上</param>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="TaskType">任务类型 I入库、O出库、S站台到站台、R移库</param>
|
/// <param name="PallteCode">托盘号</param>
|
/// <returns></returns>
|
public void PalletActionReport(string Status, string FormLocation, string ToLocation, string TaskType, string PallteCode)
|
{
|
try
|
{
|
string str = SendNotReply + "907" + BaseDal.GetSeqNo().Result.ToString("D5") + Status + JobOrderID + priority + FormLocation + ToLocation + TaskType + TrayCnt + PallteCode;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("PalletActionReport工序907").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// 作业完成上报 工序901
|
/// </summary>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="TaskType">任务类型 I入库、O出库、S站台到站台、R移库</param>
|
/// <param name="PallteCode">托盘号</param>
|
/// <returns></returns>
|
public void PalletActionReport(string FormLocation, string ToLocation, string TaskType, string PallteCode)
|
{
|
try
|
{
|
string str = SendandReply + "901" + BaseDal.GetSeqNo().Result.ToString("D5") + "0" + JobOrderID + priority + FormLocation + ToLocation + TaskType + TrayCnt + PallteCode;
|
Dt_HostLog hostLog = new Dt_HostLog()
|
{
|
CommandID = 901,
|
Count=0,
|
Messgae=str,
|
};
|
_hostLogRepository.AddData(hostLog);
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("PalletActionReport工序901").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
public void PalletActionReportPDA(string FormLocation, string ToLocation, string TaskType, string PallteCode)
|
{
|
try
|
{
|
string str = SendandReply + "901" + BaseDal.GetSeqNo().Result.ToString("D5") + "0" + JobOrderIDPDA + priority + FormLocation + ToLocation + TaskType + TrayCnt + PallteCode;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("PalletActionReportPDA工序901").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
public void PalletActionReportFrie(string FormLocation, string ToLocation, string TaskType, string PallteCode)
|
{
|
try
|
{
|
string str = SendandReply + "901" + BaseDal.GetSeqNo().Result.ToString("D5") + "0" + JobOrderIDF + priority + FormLocation + ToLocation + TaskType + TrayCnt + PallteCode;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("PalletActionReportPDA工序901").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// 设备站台状态上报 工序936
|
/// </summary>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="TaskType">任务类型 I入库、O出库、S站台到站台、R移库</param>
|
/// <param name="PallteCode">托盘号</param>
|
/// <returns></returns>
|
public void DeviceStationStatusReport(HOSTAGVStatus Agvstatus, List<OutStationStatus> outStations, List<InStationStatus> inStation, string sGetSeqNo)
|
{
|
try
|
{
|
var agvstatus = GetFieldsAsString(Agvstatus);
|
var outstation = GetListStringOutStation(outStations);
|
var instation = GetListStringInStation(inStation);
|
string str = SendNotReply + "936" + sGetSeqNo + agvstatus + outstation + OutStationSpare2 + "2" + instation;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("DeviceStationStatusReport").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// /// <summary>
|
/// 重新获取货位信息 工序105
|
/// </summary>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="TaskType">任务类型 I入库、O出库、S站台到站台、R移库</param>
|
/// <param name="PallteCode">托盘号</param>
|
public void RecreateGetLocation(string FormLocation, string ToLocation, string TaskType, string PallteCode)
|
{
|
try
|
{
|
ErrorReport(Restocking, "A", "00");
|
string str = SendandReply + "105" + BaseDal.GetSeqNo().Result.ToString("D5") + "R" + JobOrderID + priority + FormLocation + ToLocation + TaskType + TrayCnt + PallteCode;
|
Dt_HostLog hostLog = new Dt_HostLog()
|
{
|
CommandID = 105,
|
Count = 0,
|
Messgae = str,
|
};
|
_hostLogRepository.AddData(hostLog);
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("RecreateGetLocation").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// CheckSum校验 工序981
|
/// </summary>
|
/// <param name="message"></param>
|
public void CheckSum(string message)
|
{
|
try
|
{
|
string str = SendNotReply + "981" + BaseDal.GetSeqNo().Result.ToString("D5") + message;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("CheckSum").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// /// <summary>
|
/// 异常上报 工序985
|
/// </summary>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="Location">00表示AGV错误、01-08表示站台错误、99表示作业接收前数据错误</param>
|
public void ErrorReport(string Trouble, string Level, string Location)
|
{
|
try
|
{
|
string str = SendNotReply + "985" + BaseDal.GetSeqNo().Result.ToString("D5") + Trouble + Level + Location;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("ErrorReport").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// <summary>
|
/// 接收HOST工序103回馈响应 工序104
|
/// </summary>
|
/// <param name="Statues">0表示OK接收作业、1表示拒绝、9表示作业任务验证有误</param>
|
/// <returns></returns>
|
public void DeviceReceiveJobResponse(string Statues)
|
{
|
try
|
{
|
string str = SendNotReply + "104" + BaseDal.GetSeqNo().Result.ToString("D5") + Statues;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("DeviceReceiveJobResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// /// <summary>
|
/// 空出库 工序107
|
/// </summary>
|
/// <param name="FormLocation">起点</param>
|
/// <param name="ToLocation">终点</param>
|
/// <param name="TaskType">任务类型 I入库、O出库、S站台到站台、R移库</param>
|
/// <param name="PallteCode">托盘号</param>
|
public void EmptyOutBound(string FormLocation, string ToLocation, string PallteCode)
|
{
|
try
|
{
|
ErrorReport(EmptyOutBoundconst, "A", "00");
|
string str = SendandReply + "107" + BaseDal.GetSeqNo().Result.ToString("D5") + "1" + JobOrderID + priority + FormLocation + ToLocation + "O" + TrayCnt + PallteCode;
|
Dt_HostLog hostLog = new Dt_HostLog()
|
{
|
CommandID = 107,
|
Count = 0,
|
Messgae = str,
|
};
|
_hostLogRepository.AddData(hostLog);
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("EmptyOutBound").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
/// <summary>
|
/// 回复HOST909工序 工序910
|
/// </summary>
|
/// <param name="AgvStatus"></param>
|
public void DeviceStatusReportResponse(HOSTAGVStatus AgvStatus, string X, string Y)
|
{
|
try
|
{
|
string str = SendNotReply + "910" + BaseDal.GetSeqNo().Result.ToString("D5") + GetFieldsAsString(AgvStatus) + X + Y;
|
clientSend(MakeStringToByteMsg(str));
|
Dt_HostLog hostLog = new Dt_HostLog()
|
{
|
CommandID = 910,
|
Count = 0,
|
Messgae = str,
|
};
|
_hostLogRepository.AddData(hostLog);
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("DeviceStatusReportResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// <summary>
|
/// 回复HOST987工序 工序988
|
/// </summary>
|
/// <param name="AgvStatus"></param>
|
/// <param name="X"></param>
|
/// <param name="Y"></param>
|
public void FireAlarmReportResponse(string SeqNo,string IsOK,string Location)
|
{
|
try
|
{
|
string str = SendNotReply + "988" + SeqNo + IsOK + Location;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("FireAlarmReportResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
|
/// <summary>
|
/// 回复HOST301工序 工序302
|
/// </summary>
|
/// <param name="AgvStatus"></param>
|
/// <param name="X"></param>
|
/// <param name="Y"></param>
|
public void UpdateLocalTimeResponse(string message,string SeqNo)
|
{
|
try
|
{
|
string str = SendNotReply + "302" + SeqNo + message;
|
clientSend(MakeStringToByteMsg(str));
|
}
|
catch (Exception ex)
|
{
|
LogFactory.GetLog("UpdateLocalTimeResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
#endregion
|
|
#region WMS接收HOST回传方法
|
|
/// <summary>
|
/// 接收HOST 响应请求 工序102 回复工序101
|
/// </summary>
|
/// <param name="message"></param>
|
public void ReceiveCommandResponse(string message)
|
{
|
try
|
{
|
ParseMessage parseMessage = GetParse(message);
|
var lcationEnd = parseMessage.body.ToLocation;
|
switch (parseMessage.body.ret)
|
{
|
//OK
|
case "0":
|
GetLocation(parseMessage);
|
break;
|
//NG
|
case "1":
|
AddErrorMessage("2013", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
//无库位分配
|
case "2":
|
AddErrorMessage("2014", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
//站台到站台,出库站台未准备好
|
case "3":
|
AddErrorMessage("2015", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
//非常温工程
|
case "4":
|
AddErrorMessage("2016", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
case "9":
|
AddErrorMessage("2017", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host102回复WMS101ReceiveCommandResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// <summary>
|
/// 接收HOST响应AGV作业开始或启动 工序906 回复工序905
|
/// </summary>
|
public void AGVJobStartOrEndResponse(string status, string message)
|
{
|
try
|
{
|
switch (message)
|
{
|
//OK
|
case "0":
|
if (status == "E")
|
{
|
AGVStatusRespone Agvstatus = GetAGVStatus();
|
|
DeviceStateReport(GetAGVStatus(Agvstatus.RuntimeStatus));
|
Thread.Sleep(3000);
|
JobReady("1");
|
}
|
break;
|
//NG
|
case "1":
|
//调用AGV暂停接口
|
AddErrorMessage("2004", "Host", "");
|
break;
|
case "9":
|
AddErrorMessage("2005", "Host", "");
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host906回复WMS905AGVJobStartOrEndResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
|
|
}
|
|
/// <summary>
|
/// 数据报告响应 工序902 回复工序901
|
/// </summary>
|
public void DataReportResponse(string message)
|
{
|
try
|
{
|
DeleteHostLog(901);
|
#region
|
switch (message)
|
{
|
case "0":
|
|
break;
|
case "1":
|
AddErrorMessage("2001", "Host", "");
|
break;
|
case "9":
|
AddErrorMessage("2002", "Host", "");
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host902回复WMS901DataReportResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
#endregion
|
}
|
/// <summary>
|
/// HOST下发出库任务 工序103
|
/// </summary>
|
/// <param name="message"></param>
|
public void HOSTOutBoundTask(string message)
|
{
|
try
|
{
|
var parseMessage = GetParse(message);
|
switch (parseMessage.body.ret)
|
{
|
//OK
|
case "0":
|
GetLocation(parseMessage);
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host103HOSTOutBoundTask").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
/// <summary>
|
/// HOST设备状态获取 工序935
|
/// </summary>
|
/// <param name="message"></param>
|
public void DeviceStationStatusInvite(string sSeqNo)
|
{
|
try
|
{
|
//回复936
|
|
StationStatus stationIn = GetStationStatus("B002");
|
StationStatus stationOut = GetStationStatus("B001");
|
|
if(stationIn == null || stationOut == null)
|
{
|
ErrorReport("2103", "A", "00");
|
}
|
|
List<OutStationStatus> outStationStatus = GetOutStationStatus(stationOut);
|
List<InStationStatus> inStationStatus = GetInStationStatus(stationIn);
|
|
#region
|
//inStationStatus.Add(new InStationStatus()
|
//{
|
// StationName = "02",
|
// StationEnable = stationIn.WorkstationO == "1" ? "0" : "1",
|
// IsDistributionTask = "0",
|
// PallteCode = "0000000000",
|
//});
|
//inStationStatus.Add(new InStationStatus()
|
//{
|
// StationName = "01",
|
// StationEnable = stationIn.WorkstationT == "1" ? "0" : "1",
|
// IsDistributionTask = "0",
|
// PallteCode = "0000000000",
|
//});
|
//var taskOutStationO = BaseDal.QueryFirst(x => x.SourceAddress == "B001::1" || x.TargetAddress == "B001::1");
|
//var taskOutStationT = BaseDal.QueryFirst(x => x.SourceAddress == "B001::2" || x.TargetAddress == "B001::2");
|
//outStationStatus.Add(new OutStationStatus()
|
//{
|
// StationName = "04",
|
// StationEnable = stationOut.WorkstationO == "1" ? "0" : "1",
|
// IsDistributionTask = taskOutStationO == null ? "0" : "1",
|
// Spare1 = "00"
|
//});
|
//outStationStatus.Add(new OutStationStatus()
|
//{
|
// StationName = "03",
|
// StationEnable = stationOut.WorkstationT == "1" ? "0" : "1",
|
// IsDistributionTask = taskOutStationT == null ? "0" : "1",
|
// Spare1 = "00"
|
//});
|
#endregion
|
AGVStatusRespone status = GetAGVStatus();
|
HOSTAGVStatus AgvStatus = new HOSTAGVStatus()
|
{
|
RuntimeStatus = CapitalizeFirstLetter(status.RuntimeStatus),
|
AutoStatus = status.AutoStatus == "MaintenanceMode" ? "1" : "0",
|
};
|
if (status.RuntimeStatus == "Idle" && status.AutoStatus == "ControlMode")
|
{
|
AgvStatus.Ready = "1";
|
}
|
else
|
{
|
AgvStatus.Ready = "0";
|
}
|
DeviceStationStatusReport(AgvStatus, outStationStatus, inStationStatus, sSeqNo);
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host935DeviceStationStatusInvite").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
JobReady("1");
|
}
|
|
}
|
|
/// <summary>
|
/// 接收HOST重新分配货位 工序106
|
/// </summary>
|
/// <param name="message"></param>
|
public void RecreateGetLocation(string message)
|
{
|
try
|
{
|
DeleteHostLog(105);
|
var parseMessage = GetParse(message);
|
var lcationEnd = parseMessage.body.ToLocation;
|
switch (parseMessage.body.ret)
|
{
|
//OK
|
case "0":
|
GetLocation(parseMessage,true);
|
break;
|
//NG
|
case "1":
|
AddErrorMessage("2019", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
//无库位分配
|
case "2":
|
AddErrorMessage("2020", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
case "9":
|
AddErrorMessage("2021", "Host", StationParse(parseMessage.body.FromLocation));
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host106重新分配库位RecreateGetLocation").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
JobReady("1");
|
}
|
}
|
|
/// <summary>
|
/// HOST空出库响应 工序108
|
/// </summary>
|
/// <param name="message"></param>
|
public void EmptyOutBoundResponse(string message)
|
{
|
try
|
{
|
DeleteHostLog(107);
|
if (message != null)
|
{
|
switch (message)
|
{
|
case "0":
|
AGVStatusRespone Agvstatus = GetAGVStatus();
|
DeviceStateReport(GetAGVStatus(Agvstatus.RuntimeStatus));
|
Thread.Sleep(2000);
|
JobReady("1");
|
break;
|
case "1":
|
AddErrorMessage("2023", "Host", "");
|
break;
|
case "9":
|
AddErrorMessage("2024", "Host", "");
|
break;
|
default:
|
break;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host108空出库响应EmptyOutBoundResponse").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
/// <summary>
|
/// Host下发火警任务 987
|
/// </summary>
|
public void FireAlarm(string Location, string SeqNo)
|
{
|
try
|
{
|
Dt_Task taskNew = new Dt_Task();
|
var stock = SqlSugarHelper.DbWMS.Queryable<DtStockInfo>().Where(x => x.LocationCode == Location).First();
|
|
var location = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.SourceAddress == Location).First();
|
if (location != null)
|
{
|
FireAlarmReportResponse(SeqNo, "0", Location);
|
return;
|
}
|
var stationOne = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.TargetAddress == "B001::1").ToList();
|
var stationTwo = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.TargetAddress == "B001::2").ToList();
|
|
if (stationOne.Count > 0 && stationTwo.Count > 0)
|
{
|
if (stationOne.Count > stationTwo.Count)
|
{
|
taskNew = GetFireAlarm(Location, "B001::2", stock == null ? "F" + DateTime.Now.ToString("HHmmss") + new Random().Next(100, 1000) : stock.PalletCode, SeqNo);
|
}
|
else
|
{
|
taskNew = GetFireAlarm(Location, "B001::1", stock == null ? "F" + DateTime.Now.ToString("HHmmss") + new Random().Next(100, 1000) : stock.PalletCode, SeqNo);
|
}
|
FireAlarmReportResponse(SeqNo, "0", Location);
|
}
|
else
|
{
|
StationStatus stationOut = GetStationStatus("B001");
|
|
if (stationOut != null && stationOut.WorkstationO == "0" && stationOne.Count == 0)
|
{
|
taskNew = GetFireAlarm(Location, "B001::1", stock == null ? "F" + DateTime.Now.ToString("HHmmss") + new Random().Next(100, 1000) : stock.PalletCode, SeqNo);
|
}
|
else if (stationOut != null && stationOut.WorkstationT == "0" && stationTwo.Count == 0)
|
{
|
taskNew = GetFireAlarm(Location, "B001::2", stock == null ? "F" + DateTime.Now.ToString("HHmmss") + new Random().Next(100, 1000) : stock.PalletCode, SeqNo);
|
}
|
else
|
{
|
taskNew = GetFireAlarm(Location, "B001::2", stock == null ? "F" + DateTime.Now.ToString("HHmmss") + new Random().Next(100, 1000) : stock.PalletCode, SeqNo);
|
}
|
FireAlarmReportResponse(SeqNo, "0", Location);
|
}
|
BaseDal.AddData(taskNew);
|
InsertAGVTask(taskNew);
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("火警987FireAlarm").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
}
|
|
|
/// <summary>
|
/// 获取消防任务
|
/// </summary>
|
/// <param name="SourceAddress">起始地址</param>
|
/// <param name="TargetAddress">终点地址</param>
|
/// <param name="PalletCode">托盘号</param>
|
/// <param name="SeqNo">Host序列号</param>
|
/// <returns></returns>
|
public Dt_Task GetFireAlarm(string SourceAddress, string TargetAddress, string PalletCode, string SeqNo)
|
{
|
return new Dt_Task()
|
{
|
SourceAddress = SourceAddress,
|
TargetAddress = TargetAddress,
|
CurrentAddress = SourceAddress,
|
NextAddress = TargetAddress,
|
TaskType = (int)TaskFireAlarmTypeEnum.FireAlarmOut,
|
TaskState = (int)TaskFireAlarmStatusEnum.FireAlarmNew,
|
Remark = TargetAddress,
|
TaskNum = BaseDal.GetTaskNo().Result,
|
PalletCode = PalletCode == null ? "" : PalletCode,
|
Dispatchertime = DateTime.Now,
|
Grade = 1,
|
SeqNo = Convert.ToInt32(SeqNo),
|
CommandID = Convert.ToInt32(987),
|
};
|
}
|
|
/// <summary>
|
/// HOST获取设备状态 工序909
|
/// </summary>
|
public void DeviceStatusReportRequest()
|
{
|
try
|
{
|
DeleteHostLog(910);
|
AGVStatusRespone status = GetAGVStatus();
|
|
HOSTAGVStatus AgvStatus = new HOSTAGVStatus()
|
{
|
RuntimeStatus = CapitalizeFirstLetter(status.RuntimeStatus),
|
AutoStatus = status.AutoStatus == "MaintenanceMode" ? "1" : "0",
|
|
};
|
if (status.RuntimeStatus == "Idle" && status.AutoStatus == "ControlMode")
|
{
|
AgvStatus.Ready = "1";
|
}
|
else
|
{
|
AgvStatus.Ready = "0";
|
}
|
string axis = "000000";
|
|
DeviceStatusReportResponse(AgvStatus, axis, axis);
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("Host心跳").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
|
|
/// <summary>
|
/// WMS同步Host时间 工序301
|
/// </summary>
|
public void UpdateLocalTime(string Time,string SeqNo)
|
{
|
try
|
{
|
SYSTEMTIME newTime = new SYSTEMTIME
|
{
|
Year = Convert.ToUInt16(Time.Substring(0,4)),
|
Month = Convert.ToUInt16(Time.Substring(4, 2)),
|
Day = Convert.ToUInt16(Time.Substring(6, 2)),
|
Hour = Convert.ToUInt16(Time.Substring(8, 2)),
|
Minute = Convert.ToUInt16(Time.Substring(10, 2)),
|
Second = Convert.ToUInt16(Time.Substring(12, 2)),
|
Milliseconds = 0
|
};
|
if (SetLocalTime(ref newTime))
|
{
|
UpdateLocalTimeResponse("0", SeqNo);
|
Console.WriteLine("系统时间已成功修改。");
|
}
|
else
|
{
|
UpdateLocalTimeResponse("1", SeqNo);
|
Console.WriteLine("修改系统时间失败。请确保以管理员权限运行此程序。");
|
}
|
}
|
catch (Exception ex)
|
{
|
ErrorReport("2199", "A", "00");
|
LogFactory.GetLog("UpdateLocalTime时间同步").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(ex.Message)}{Environment.NewLine}{ex.StackTrace}", "");
|
}
|
|
}
|
#endregion
|
|
#region 全局方法
|
/// <summary>
|
/// 拼接报文
|
/// </summary>
|
/// <param name="Message"></param>
|
/// <returns></returns>
|
/// <exception cref="Exception"></exception>
|
public byte[] MakeStringToByteMsg(string Message)
|
{
|
try
|
{
|
byte[] byt = Encoding.UTF8.GetBytes(Message); // 使用 UTF-8 避免编码问题
|
|
string checksum = GetCheckSum(byt);
|
|
string str = Message + checksum;
|
|
byte[] buffer = Encoding.UTF8.GetBytes(str);
|
|
byte newFirstByte = 2; // 新的第一位数据
|
byte newLastByte = 3; // 新的最后一位数据
|
|
// 创建一个新数组,长度比原始数组多2
|
byte[] newArray = new byte[buffer.Length + 2];
|
|
// 将新的数据插入到新数组的第一位
|
newArray[0] = newFirstByte;
|
|
// 将新的数据插入到新数组的最后一位
|
newArray[newArray.Length - 1] = newLastByte;
|
|
// 复制原始数组的所有数据到新数组的中间部分
|
Array.Copy(buffer, 0, newArray, 1, buffer.Length);
|
|
return newArray;
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
}
|
public string GetListStringOutStation(List<OutStationStatus> outStationStatus)
|
{
|
return string.Join("", outStationStatus.Select(status => $"{status.StationName}{status.StationEnable}{status.IsDistributionTask}{status.Spare1}"));
|
}
|
public string GetListStringInStation(List<InStationStatus> inStationStatus)
|
{
|
return string.Join("", inStationStatus.Select(status => $"{status.StationName}{status.StationEnable}{status.IsDistributionTask}{status.IsHasPallte}{status.Spare1}{status.StationPallteCount}{status.PallteCode}{status.Spare2}"));
|
}
|
/// <summary>
|
/// 将对象值凭拼接
|
/// </summary>
|
/// <param name="obj"></param>
|
/// <returns></returns>
|
public static string GetFieldsAsString(object obj)
|
{
|
if (obj == null)
|
{
|
return "Object is null";
|
}
|
|
StringBuilder builder = new StringBuilder();
|
Type type = obj.GetType();
|
|
foreach (PropertyInfo property in type.GetProperties())
|
{
|
if (property.CanRead)
|
{
|
object value = property.GetValue(obj);
|
if (value != null)
|
{
|
builder.Append(value);
|
}
|
}
|
}
|
return builder.ToString();
|
}
|
/// <summary>
|
/// 获取CheckSum值
|
/// </summary>
|
/// <param name="data"></param>
|
/// <returns></returns>
|
/// <exception cref="Exception"></exception>
|
public string GetCheckSum(byte[] data)
|
{
|
int sum = 0;
|
try
|
{
|
for (int i = 0; i < data.Length; i++)
|
{
|
sum += data[i];
|
}
|
string str = sum.ToString();
|
return str.Substring(str.Length - 2);
|
}
|
catch (Exception ex)
|
{
|
throw new Exception(ex.Message);
|
}
|
}
|
|
public List<OutStationStatus> GetOutStationStatus(StationStatus stationOut)
|
{
|
List<OutStationStatus> outStationStatus = new List<OutStationStatus>();
|
var taskOutStationO = BaseDal.QueryFirst(x => x.SourceAddress == "B001::1" || x.TargetAddress == "B001::1");
|
var taskOutStationT = BaseDal.QueryFirst(x => x.SourceAddress == "B001::2" || x.TargetAddress == "B001::2");
|
outStationStatus.Add(new OutStationStatus()
|
{
|
StationName = "04",
|
StationEnable = stationOut.WorkstationO == "1" ? "0" : "1",
|
IsDistributionTask = taskOutStationO == null ? "0" : "1",
|
Spare1 = "00"
|
});
|
outStationStatus.Add(new OutStationStatus()
|
{
|
StationName = "03",
|
StationEnable = stationOut.WorkstationT == "1" ? "0" : "1",
|
IsDistributionTask = taskOutStationT == null ? "0" : "1",
|
Spare1 = "00"
|
});
|
return outStationStatus;
|
}
|
|
public List<InStationStatus> GetInStationStatus(StationStatus stationIn)
|
{
|
List<InStationStatus> inStationStatus = new List<InStationStatus>();
|
var taskOutStationO = BaseDal.QueryFirst(x => x.SourceAddress == "B002::1" || x.TargetAddress == "B002::1");
|
var taskOutStationT = BaseDal.QueryFirst(x => x.SourceAddress == "B002::2" || x.TargetAddress == "B002::2");
|
inStationStatus.Add(new InStationStatus()
|
{
|
StationName = "02",
|
StationEnable = stationIn.WorkstationO == "1" ? "0" : "1",
|
IsDistributionTask = taskOutStationO == null ? "0" : "1",
|
PallteCode = "0000000000",
|
});
|
inStationStatus.Add(new InStationStatus()
|
{
|
StationName = "01",
|
StationEnable = stationIn.WorkstationT == "1" ? "0" : "1",
|
IsDistributionTask = taskOutStationT == null ? "0" : "1",
|
PallteCode = "0000000000",
|
});
|
return inStationStatus;
|
}
|
#endregion
|
|
#region 私有方法
|
/// <summary>
|
/// 添加WMS任务
|
/// </summary>
|
/// <param name="parseMessage"></param>
|
/// <exception cref="Exception"></exception>
|
private void InsertWMSTask(ParseMessage parseMessage)
|
{
|
int taskType = 0;
|
int taskState = 0;
|
Dt_Task task = new Dt_Task();
|
if (parseMessage.body.JobType == "I")
|
{
|
Dt_StationManager Instation = _stationManagerRepository.QueryFirst(x => x.HostName == parseMessage.body.FromLocation.Substring(4, 2));
|
task.SourceAddress = StationParse(parseMessage.body.FromLocation);
|
task.TargetAddress = parseMessage.body.ToLocation;
|
task.CurrentAddress = StationParse(parseMessage.body.FromLocation);
|
task.NextAddress = parseMessage.body.ToLocation;
|
taskType = (int)TaskInboundTypeEnum.Inbound;
|
taskState = (int)TaskInStatusEnum.InNew;
|
task.Remark = parseMessage.body.FromLocation;
|
|
}
|
else if (parseMessage.body.JobType == "O")
|
{
|
task.SourceAddress = parseMessage.body.FromLocation;
|
task.TargetAddress = StationParse(parseMessage.body.ToLocation);
|
task.CurrentAddress = parseMessage.body.FromLocation;
|
task.NextAddress = StationParse(parseMessage.body.ToLocation);
|
taskType = (int)TaskOutboundTypeEnum.Outbound;
|
taskState = (int)TaskOutStatusEnum.OutNew;
|
task.Remark = parseMessage.body.ToLocation;
|
}
|
else if (parseMessage.body.JobType == "C")
|
{
|
task.SourceAddress = parseMessage.body.FromLocation;
|
task.TargetAddress = StationParse(parseMessage.body.ToLocation);
|
task.CurrentAddress = parseMessage.body.FromLocation;
|
task.NextAddress = StationParse(parseMessage.body.ToLocation);
|
taskType = (int)TaskOutboundTypeEnum.OutQuality;
|
taskState = (int)TaskOutStatusEnum.OutNew;
|
task.Remark = parseMessage.body.ToLocation;
|
}
|
else if (parseMessage.body.JobType == "S")
|
{
|
taskType = (int)TaskStationTypeEnum.StationToStation;
|
taskState = (int)TaskOutStatusEnum.OutNew;
|
task.SourceAddress = StationParse(parseMessage.body.FromLocation) ;
|
task.TargetAddress = StationParse(parseMessage.body.ToLocation);
|
task.CurrentAddress = StationParse(parseMessage.body.FromLocation);
|
task.NextAddress = StationParse(parseMessage.body.ToLocation);
|
task.Remark = parseMessage.body.FromLocation;
|
task.HostName = parseMessage.body.ToLocation;
|
}
|
else if (parseMessage.body.JobType == "R")
|
{
|
taskType = (int)TaskRelocationTypeEnum.Relocation;
|
taskState = (int)TaskRelocationStatusEnum.RelocationNew;
|
task.SourceAddress = parseMessage.body.FromLocation;
|
task.TargetAddress = parseMessage.body.ToLocation;
|
task.CurrentAddress = parseMessage.body.FromLocation;
|
task.NextAddress = parseMessage.body.ToLocation;
|
}
|
else
|
{
|
throw new Exception("未知库位");
|
}
|
|
|
task.TaskNum = BaseDal.GetTaskNo().Result;
|
task.PalletCode = parseMessage.body.TrayIdList.Substring(0, 10);
|
task.TaskType = taskType;
|
task.TaskState = taskState;
|
task.Dispatchertime = DateTime.Now;
|
task.Grade = 1;
|
task.SeqNo = Convert.ToInt32(parseMessage.nSeqNo);
|
task.CommandID = Convert.ToInt32(parseMessage.bCmdID);
|
BaseDal.AddData(task);
|
InsertAGVTask(task);
|
}
|
|
|
public void GetLocation(ParseMessage parseMessage,bool repeat=false)
|
{
|
|
switch (parseMessage.body.JobType)
|
{
|
case "I":
|
var locationIn = SqlSugarHelper.DbWMS.Queryable<DtLocationInfo>().Where(x => x.LocationCode == parseMessage.body.ToLocation).First();
|
if (locationIn == null)
|
{
|
ErrorReport("2102", "A", "00");
|
return;
|
}
|
if (locationIn.LocationStatus == (int)LocationEnum.Free)
|
{
|
var taskIn = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.PalletCode == parseMessage.body.TrayIdList.Substring(0, 10)).First();
|
if (taskIn != null)
|
{
|
_taskService.UpdateTask(StationParse(parseMessage.body.FromLocation), parseMessage.body.ToLocation, parseMessage.body.TrayIdList.Substring(0, 10));
|
}
|
else
|
{
|
InsertWMSTask(parseMessage);
|
}
|
Thread.Sleep(500);
|
JobReady("0");
|
}
|
else
|
{
|
RecreateGetLocation(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.JobType, parseMessage.body.TrayIdList.Substring(0, 10));
|
}
|
break;
|
case "O":
|
case "C":
|
var locationOut = SqlSugarHelper.DbWMS.Queryable<DtLocationInfo>().Where(x => x.LocationCode == parseMessage.body.FromLocation).First();
|
if (locationOut == null)
|
{
|
ErrorReport("2102", "A", "00");
|
return;
|
}
|
if (locationOut.LocationStatus == (int)LocationEnum.InStock)
|
{
|
var taskOut = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.PalletCode == parseMessage.body.TrayIdList.Substring(0, 10)).First();
|
if (taskOut != null)
|
{
|
_taskService.UpdateTask(locationOut.LocationCode, StationParse(parseMessage.body.ToLocation), parseMessage.body.TrayIdList.Substring(0, 10));
|
}
|
else
|
{
|
InsertWMSTask(parseMessage);
|
}
|
Thread.Sleep(500);
|
JobReady("0");
|
Thread.Sleep(500);
|
//104
|
DeviceReceiveJobResponse("0");
|
}
|
else
|
{
|
EmptyOutBound(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.TrayIdList.Substring(0, 10));
|
_taskService.AddStcokHty(parseMessage.body.TrayIdList.Substring(0, 10), parseMessage.body.FromLocation);
|
}
|
break;
|
case "S":
|
var taskS = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.PalletCode == parseMessage.body.TrayIdList.Substring(0, 10)).First();
|
if (taskS != null)
|
{
|
_taskService.UpdateTask(StationParse(parseMessage.body.FromLocation), StationParse(parseMessage.body.ToLocation), parseMessage.body.TrayIdList.Substring(0, 10));
|
}
|
else
|
{
|
InsertWMSTask(parseMessage);
|
}
|
Thread.Sleep(500);
|
JobReady("0");
|
|
break;
|
case "R":
|
var locationA = SqlSugarHelper.DbWMS.Queryable<DtLocationInfo>().Where(x => x.LocationCode == parseMessage.body.FromLocation).First();
|
var locationB = SqlSugarHelper.DbWMS.Queryable<DtLocationInfo>().Where(x => x.LocationCode == parseMessage.body.ToLocation).First();
|
if (locationA == null || locationB == null)
|
{
|
ErrorReport("2102", "A", "00");
|
return;
|
}
|
if (locationA.LocationStatus == (int)LocationEnum.InStock && locationB.LocationStatus == (int)LocationEnum.Free)
|
{
|
var taskR = SqlSugarHelper.DbWMS.Queryable<Dt_Task>().Where(x => x.PalletCode == parseMessage.body.TrayIdList.Substring(0, 10)).First();
|
if (taskR != null)
|
{
|
|
_taskService.UpdateTask(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.TrayIdList.Substring(0, 10));
|
}
|
else
|
{
|
InsertWMSTask(parseMessage);
|
}
|
Thread.Sleep(500);
|
JobReady("0");
|
}
|
else
|
{
|
RecreateGetLocation(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.JobType, parseMessage.body.TrayIdList.Substring(0, 10));
|
}
|
break;
|
default:
|
break;
|
}
|
}
|
/// <summary>
|
/// 添加AGV任务
|
/// </summary>
|
/// <param name="task">任务对象</param>
|
/// <returns></returns>
|
private int InsertAGVTask(Dt_Task task)
|
{
|
string SourceAddress = string.Empty;
|
string TargetAddress = string.Empty;
|
string AGVType = string.Empty;
|
if (task.TaskType == (int)TaskInboundTypeEnum.Inbound)
|
{
|
SourceAddress = task.SourceAddress;
|
AGVType = "2";
|
TargetAddress = InsertHyphenEveryTwoChars(task.TargetAddress);
|
}
|
else if (task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
|
{
|
SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress);
|
TargetAddress = task.TargetAddress;
|
AGVType = "4";
|
}
|
else if (task.TaskType == (int)TaskOutboundTypeEnum.OutQuality)
|
{
|
SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress);
|
TargetAddress = task.TargetAddress;
|
AGVType = "128";
|
}
|
else if (task.TaskType == (int)TaskRelocationTypeEnum.Relocation)
|
{
|
TargetAddress = InsertHyphenEveryTwoChars(task.TargetAddress);
|
SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress);
|
AGVType = "16";
|
}
|
else if (task.TaskType == (int)TaskStationTypeEnum.StationToStation)
|
{
|
TargetAddress = task.TargetAddress;
|
SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress);
|
AGVType = "8";
|
}
|
else if (task.TaskType == (int)TaskFireAlarmTypeEnum.FireAlarmOut)
|
{
|
TargetAddress = task.TargetAddress;
|
SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress);
|
AGVType = "1";
|
}
|
task_call task_Call = new task_call()
|
{
|
d_task_type = AGVType,
|
d_floor = "1",
|
d_involed1 = SourceAddress,
|
d_involed2 = TargetAddress,
|
d_involed5 = task.TaskNum.ToString(),
|
};
|
var x = SqlSugarHelper.DbAGV.Insertable(task_Call).ExecuteCommand();
|
LogFactory.GetLog("插入数据到AGV").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(x)}", "");
|
return x;
|
}
|
public ParseMessage GetParse(string x)
|
{
|
|
if (string.IsNullOrEmpty(x))
|
{
|
throw new ArgumentNullException(nameof(x), "Input string cannot be null or empty");
|
}
|
|
// 定义所有需要的字段长度和位置
|
var fieldDefinitions = new (int Start, int Length, string Name)[]
|
{
|
(0, 1, "bDir"),
|
(1, 10, "bObjID"),
|
(11, 1, "bReply"),
|
(12, 3, "bCmdID"),
|
(15, 5, "nSeqNo"),
|
(20, 1, "ret"),
|
(21, 16, "JobOrderID"),
|
(37, 1, "priority"),
|
(38, 6, "FromLocation"),
|
(44, 6, "ToLocation"),
|
(50, 1, "JobType"),
|
(51, 1, "TrayCnt"),
|
(52, x.Length - 52, "TrayIdList") // 可变长度字段
|
};
|
|
// 计算所需最小长度
|
int minLength = fieldDefinitions.Max(f => f.Start + f.Length);
|
|
if (x.Length < minLength)
|
{
|
// 如果字符串长度不足,可以选择记录警告或日志
|
// 这里我们继续处理,尽可能多地解析字段
|
}
|
|
// 辅助方法:安全的子字符串截取,长度不足时返回空字符串
|
string SafeSubstringOrDefault(string source, int start, int length, string fieldName)
|
{
|
if (start < 0 || start >= source.Length)
|
{
|
return ""; // 返回空字符串
|
}
|
|
if (length < 0)
|
{
|
return ""; // 返回空字符串
|
}
|
|
if (start + length > source.Length)
|
{
|
length = source.Length - start; // 调整长度以避免越界
|
}
|
|
return source.Substring(start, length);
|
}
|
|
// 构建结果对象
|
var result = new ParseMessage();
|
|
// 设置基本字段
|
result.bDir = SafeSubstringOrDefault(x, fieldDefinitions[0].Start, fieldDefinitions[0].Length, fieldDefinitions[0].Name);
|
result.bObjID = SafeSubstringOrDefault(x, fieldDefinitions[1].Start, fieldDefinitions[1].Length, fieldDefinitions[1].Name);
|
result.bReply = SafeSubstringOrDefault(x, fieldDefinitions[2].Start, fieldDefinitions[2].Length, fieldDefinitions[2].Name);
|
result.bCmdID = SafeSubstringOrDefault(x, fieldDefinitions[3].Start, fieldDefinitions[3].Length, fieldDefinitions[3].Name);
|
result.nSeqNo = SafeSubstringOrDefault(x, fieldDefinitions[4].Start, fieldDefinitions[4].Length, fieldDefinitions[4].Name);
|
|
// 设置body字段
|
result.body = new ReceiveBody
|
{
|
ret = SafeSubstringOrDefault(x, fieldDefinitions[5].Start, fieldDefinitions[5].Length, fieldDefinitions[5].Name),
|
JobOrderID = SafeSubstringOrDefault(x, fieldDefinitions[6].Start, fieldDefinitions[6].Length, fieldDefinitions[6].Name),
|
priority = SafeSubstringOrDefault(x, fieldDefinitions[7].Start, fieldDefinitions[7].Length, fieldDefinitions[7].Name),
|
FromLocation = SafeSubstringOrDefault(x, fieldDefinitions[8].Start, fieldDefinitions[8].Length, fieldDefinitions[8].Name),
|
ToLocation = SafeSubstringOrDefault(x, fieldDefinitions[9].Start, fieldDefinitions[9].Length, fieldDefinitions[9].Name),
|
JobType = SafeSubstringOrDefault(x, fieldDefinitions[10].Start, fieldDefinitions[10].Length, fieldDefinitions[10].Name),
|
TrayCnt = SafeSubstringOrDefault(x, fieldDefinitions[11].Start, fieldDefinitions[11].Length, fieldDefinitions[11].Name),
|
TrayIdList = SafeSubstringOrDefault(x, fieldDefinitions[12].Start, fieldDefinitions[12].Length, fieldDefinitions[12].Name)
|
};
|
|
return result;
|
}
|
|
public AGVStatusRespone GetAGVStatus()
|
{
|
string urlnew = url + "/ilns/AGV/getState";
|
var result = HttpsClient.PostAsync(urlnew, JsonConvert.DeserializeObject<Dictionary<string, object>>(new { getStatus = "1" }.ToJson())).Result;
|
|
return JsonConvert.DeserializeObject<AGVStatusRespone>(result.ToString());
|
}
|
|
public StationStatus GetStationStatus(string stationName)
|
{
|
string urlnew = url + "/ilns/ctrl/getState";
|
var result = HttpsClient.PostAsync(urlnew, JsonConvert.DeserializeObject<Dictionary<string, object>>(new { ctrlName = stationName }.ToJson())).Result;
|
return JsonConvert.DeserializeObject<StationStatus>(result.ToString());
|
}
|
public void ReportStationErrorMeaage(string StationName)
|
{
|
string urlnew = url + "/ilns/setctrlerr";
|
var result = HttpsClient.PostAsync(urlnew, JsonConvert.DeserializeObject<Dictionary<string, object>>(new { ctrlName = StationName }.ToJson())).Result;
|
}
|
public void ReportAgvErrorMeaage(string ErrorCode)
|
{
|
string urlnew = url + "/ilns/rpterr";
|
var result = HttpsClient.PostAsync(urlnew, JsonConvert.DeserializeObject<Dictionary<string, object>>(new { code = ErrorCode }.ToJson())).Result;
|
}
|
public void AddErrorMessage(string Code, string ReportName, string Location = "")
|
{
|
var errorDescription = SqlSugarHelper.DbWMS.Queryable<Dt_ErrorDescription>().Where(x => x.ErrorCode == Code).First();
|
if (errorDescription != null)
|
{
|
Dt_HostErrorMessage hostErrorMessage = new Dt_HostErrorMessage()
|
{
|
ErrorCode = Code,
|
ErrorMessage = errorDescription.ErrorMessgae,
|
AlarmSource = errorDescription.AlarmSource,
|
Grade = errorDescription.Grade,
|
ReportName = ReportName,
|
Creater = "System",
|
Location = Location == "" ? "" : Location,
|
CreateDate = DateTime.Now,
|
};
|
SqlSugarHelper.DbWMS.Insertable(hostErrorMessage).ExecuteCommand();
|
if (Location == "")
|
{
|
ReportAgvErrorMeaage(Code);
|
}
|
else
|
{
|
ReportStationErrorMeaage(Location);
|
}
|
|
}
|
else
|
{
|
//tode不存在异常Code
|
}
|
}
|
public void DeleteHostLog(int CommandID)
|
{
|
var hostLog = SqlSugarHelper.DbWMS.Queryable<Dt_HostLog>().Where(x => x.CommandID == CommandID).First();
|
if (hostLog != null)
|
{
|
SqlSugarHelper.DbWMS.Deleteable(hostLog).ExecuteCommand();
|
}
|
}
|
|
public string StationParse(string station)
|
{
|
var Station = SqlSugarHelper.DbWMS.Queryable<Dt_StationManager>().Where(x => x.HostName == station.Substring(4, 2)).First();
|
if(Station != null)
|
{
|
return Station.stationName;
|
}
|
else
|
{
|
return "";
|
}
|
}
|
|
public string CapitalizeFirstLetter(string s)
|
{
|
if (string.IsNullOrEmpty(s))
|
{
|
return "";
|
}
|
char firstChar = s[0];
|
return char.ToUpper(firstChar).ToString();
|
}
|
|
public string GetAGVStatus(string Status)
|
{
|
switch (Status)
|
{
|
case "Run":
|
return "R";
|
case "Idle":
|
return "I";
|
case "Trouble":
|
//故障
|
return "T";
|
case "Pause":
|
return "S";
|
case "Charge":
|
return "C";
|
case "PowerOn":
|
return "P";
|
case "PowerOFF":
|
return "O";
|
default: break;
|
}
|
return "T";
|
}
|
|
public string InsertHyphenEveryTwoChars(string input)
|
{
|
if (string.IsNullOrEmpty(input))
|
{
|
return input;
|
}
|
|
StringBuilder result = new StringBuilder();
|
|
for (int i = 0; i < input.Length; i += 2)
|
{
|
// 添加两个字符
|
result.Append(input.Substring(i, 2));
|
|
// 如果不是最后两个字符,添加一个连字符
|
if (i + 2 < input.Length)
|
{
|
result.Append('-');
|
}
|
}
|
|
return result.ToString();
|
}
|
|
#endregion
|
|
#region 修改本地计算机时间
|
// 定义 System 结构体
|
[StructLayout(LayoutKind.Sequential)]
|
public struct SYSTEMTIME
|
{
|
public ushort Year;
|
public ushort Month;
|
public ushort DayOfWeek;
|
public ushort Day;
|
public ushort Hour;
|
public ushort Minute;
|
public ushort Second;
|
public ushort Milliseconds;
|
}
|
|
// 导入 SetLocalTime 函数
|
[DllImport("kernel32.dll", SetLastError = true)]
|
public static extern bool SetLocalTime(ref SYSTEMTIME st);
|
#endregion
|
}
|
}
|