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; namespace WIDESEA_StorageSocketServices { public class SocketClientService : ISocketClientServices { System.Net.Sockets.Socket socket; const byte STX = 2; const byte ETX = 3; private readonly ILogger _logger; private readonly LogFactory LogFactory = new LogFactory(); //private readonly IDt_TaskService _taskService; private readonly IDt_StationManagerRepository _stationManagerRepository; private readonly IDt_TaskRepository BaseDal; Connection connection = AppSettings.Configuration.GetSection("Connection").Get(); string url = AppSettings.Configuration["AGVIP"]; private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IStockInfoRepository _stockInfoRepository; private readonly IDt_Task_HtyRepository _task_HtyRepository; private readonly IMapper _mapper; private readonly ILocationInfoRepository _locationRepository; private readonly IDt_TaskService _taskService; private readonly IDt_HostLogRepository _hostLogRepository; private bool _IsOnline=false; public SocketClientService(IDt_TaskService TaskService, IDt_TaskRepository TaskRepository, IDt_StationManagerRepository stationManagerRepository, ILogger logger, ILocationInfoRepository locationInfoRepository,IDt_HostLogRepository hostLogRepository) { BaseDal = TaskRepository; _stationManagerRepository = stationManagerRepository; _logger = logger; _taskService = TaskService; _locationRepository = locationInfoRepository; _hostLogRepository = hostLogRepository; #region //if (App.RootServices != null) //{ // IDt_TaskRepository? BaseDal = App.RootServices.CreateScope().ServiceProvider.GetService(typeof(IDt_TaskRepository)) as IDt_TaskRepository; // IDt_TaskService? _taskService = App.RootServices.CreateScope().ServiceProvider.GetService(typeof(IDt_TaskService)) as IDt_TaskService; // ILocationInfoRepository? _locationRepository = App.RootServices.CreateScope().ServiceProvider.GetService(typeof(ILocationInfoRepository)) as ILocationInfoRepository; // IDt_StationManagerRepository? _stationManagerRepository = App.RootServices.CreateScope().ServiceProvider.GetService(typeof(IDt_StationManagerRepository)) as IDt_StationManagerRepository; //} #endregion } public void ConnectServer(string IP, int Port) { try { // 检查是否已连接,避免重复创建 if (socket != null && socket.Connected) { ConsoleHelper.WriteErrorLine($"Socket已处于连接状态"); return; } //创建负责通信的socket socket = new 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连接成功"); _IsOnline = true; RequestCommunication(); DeviceStateReport("I"); //开启一个新的线程不停的接收服务端发来的信息 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; } void Receive() { 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); 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 { LogFactory.GetLog("Socket接收数据").Error(true, "校验失败"); } } else { LogFactory.GetLog("Socket接收数据").Error(true, $"无效报文格式:{JsonConvert.SerializeObject(Y)}"); } } catch { _IsOnline = false; HandleDisconnection(); } } } 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; default: break; } } private void HandleDisconnection() { int attempts = 5; 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); } public void clientSend(byte[] buffer) { var Y = Encoding.UTF8.GetString(buffer); LogFactory.GetLog("Socket发送数据").Info(true, Y); socket.Send(buffer); } 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; /// /// 作业任务ID 预留 /// public const string JobOrderID = "0000000000000000"; /// /// 优先级 预留 /// public const string priority = "1"; /// /// 重入库 /// public const string Restocking = "2100"; public const string EmptyOutBoundconst = "2101"; /// /// 托盘个数 预留 /// public const string TrayCnt = "1"; /// /// 设备编号 /// public const string DeviceID = "0013130010"; /// /// 发送不需要回复 /// public const string SendNotReply = "1" + DeviceID + "0"; /// /// 发送需要回复 /// public const string SendandReply = "1" + DeviceID + "1"; /// /// 出库站台启用已分配任务 /// public const string OutBoundStationEnableDistribution = "1000"; /// /// 出库站台启用未分配任务 /// public const string OutBoundStationEnableUndistributed = "1100"; /// /// 出库站台禁用 /// public const string OutBoundStationDisabled = "0000"; /// /// 入库站台个数 /// public const string InBoundStationCount = "1"; /// /// 入库站台状态 /// public const string InBoundStationStatus = "1010001"; /// /// 预留 /// public const string Spare1 = "0000000000000000000000000000000000000000000000000000000000000000000000"; /// /// 出库站台预留 /// public const string OutStationSpare2 = "000000000000"; /// /// 预留 /// public const string Spare3 = "000"; /// /// 托盘号 /// public const string Spare4 = "0000000000"; #endregion #region WMS下发HOST方法 /// /// 设备请求入库 工序101 /// /// 托盘号 /// 入库站台 public void DeviceRequestInbound(HOSTAGVStatus Agvstatus, List 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) { throw new Exception(ex.Message); } } /// /// 请求通讯 工序925 /// /// 托盘号 /// 入库站台 public void RequestCommunication() { try { string str = SendandReply + "925" + BaseDal.GetSeqNo().Result.ToString("D5"); clientSend(MakeStringToByteMsg(str)); } catch (Exception ex) { throw new Exception(ex.Message); } } /// /// 不允许下发任务 工序915 /// /// 命令 /// public void JobReady(string Command) { try { string str = SendNotReply + "915" + BaseDal.GetSeqNo().Result.ToString("D5") + Command; clientSend(MakeStringToByteMsg(str)); } catch (Exception ex) { throw new Exception(ex.Message); } } /// /// 设备状态上报 工序913 /// /// 状态\、R运行 /// public void DeviceStateReport(string Status) { try { string str = SendNotReply + "913" + BaseDal.GetSeqNo().Result.ToString("D5") + Status; clientSend(MakeStringToByteMsg(str)); } catch (Exception ex) { throw new Exception(ex.Message); } } /// /// 设备状态上报 工序917 /// /// 状态\、R运行 /// public void DeviceAutoStatusReport(string Status) { try { string str = SendNotReply + "917" + BaseDal.GetSeqNo().Result.ToString("D5") + Status; clientSend(MakeStringToByteMsg(str)); } catch (Exception ex) { throw new Exception(ex.Message); } } /// /// /// 作业开始或结束 工序905 /// /// 状态 L指AGV将托盘叉到货叉上、U指AGV将托盘放到库位上 /// 起点 /// 终点 /// 任务类型 I入库、O出库、S站台到站台、R移库 /// 托盘号 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) { throw new Exception(ex.Message); } } /// /// 托盘动作上报 工序907 /// /// 状态 L指AGV将托盘叉到货叉上、U指AGV将托盘放到库位上 /// 起点 /// 终点 /// 任务类型 I入库、O出库、S站台到站台、R移库 /// 托盘号 /// 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) { throw new Exception(ex.Message); } } /// /// 作业完成上报 工序901 /// /// 起点 /// 终点 /// 任务类型 I入库、O出库、S站台到站台、R移库 /// 托盘号 /// 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) { throw new Exception(ex.Message); } } /// /// 设备站台状态上报 工序936 /// /// 起点 /// 终点 /// 任务类型 I入库、O出库、S站台到站台、R移库 /// 托盘号 /// public void DeviceStationStatusReport(HOSTAGVStatus Agvstatus, List outStations, List 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) { throw new Exception(ex.Message); } } /// /// /// 重新获取货位信息 工序105 /// /// 起点 /// 终点 /// 任务类型 I入库、O出库、S站台到站台、R移库 /// 托盘号 public void RecreateGetLocation(string FormLocation, string ToLocation, string TaskType, string PallteCode) { try { 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) { throw new Exception(ex.Message); } } /// /// /// 异常上报 工序985 /// /// 起点 /// 终点 /// 00表示AGV错误、01-08表示站台错误、99表示作业接收前数据错误 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) { throw new Exception(ex.Message); } } /// /// 接收HOST工序103回馈响应 工序104 /// /// 0表示OK接收作业、1表示拒绝、9表示作业任务验证有误 /// public void DeviceReceiveJobResponse(string Statues) { try { string str = SendNotReply + "104" + BaseDal.GetSeqNo().Result.ToString("D5") + Statues; clientSend(MakeStringToByteMsg(str)); } catch (Exception ex) { throw new Exception(ex.Message); } } /// /// /// 空出库 工序107 /// /// 起点 /// 终点 /// 任务类型 I入库、O出库、S站台到站台、R移库 /// 托盘号 public void EmptyOutBound(string FormLocation, string ToLocation, string PallteCode) { try { 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) { throw new Exception(ex.Message); } } /// /// 回复HOST909工序 工序910 /// /// public void DeviceStatusReportResponse(HOSTAGVStatus AgvStatus, string X, string Y) { string str = SendNotReply + "910" + BaseDal.GetSeqNo().Result.ToString("D5") + GetFieldsAsString(AgvStatus) + X + Y; clientSend(MakeStringToByteMsg(str)); } #endregion #region WMS接收HOST回传方法 /// /// 接收HOST 响应请求 工序102 回复工序101 /// /// public void ReceiveCommandResponse(string message) { var parseMessage = GetParse(message); var lcationEnd = parseMessage.body.ToLocation; switch (parseMessage.body.ret) { //OK case "0": //var location = _locationRepository.QueryFirst(x => x.LocationCode == lcationEnd); var location = SqlSugarHelper.DbWMS.Queryable().Where(x => x.LocationCode == parseMessage.body.ToLocation).First(); if (location == null) { return; } if (location.LocationStatus == (int)LocationEnum.Free) { var task = InsertWMSTask(parseMessage); Thread.Sleep(500); InsertAGVTask(task); location.LocationStatus = 1; //SqlSugarHelper.DbWMS.Insertable(task).ExecuteCommand(); SqlSugarHelper.DbWMS.Updateable(location).ExecuteCommand(); BaseDal.AddData(task); //915 JobReady("0"); return; } else { ErrorReport(Restocking, "A", "00"); Thread.Sleep(500); RecreateGetLocation(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.JobType, parseMessage.body.TrayIdList.Substring(0, 10)); //todo货位有货重复入库 return; } //NG case "1": break; //无库位分配 case "2": break; //站台到站台,出库站台未准备好 case "3": break; //非常温工程 case "4": break; case "9": break; default: break; } LogFactory.GetLog("Host102回复WMS101").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(parseMessage)}{Environment.NewLine}", ""); } /// /// 接收HOST响应AGV作业开始或启动 工序906 回复工序905 /// public void AGVJobStartOrEndResponse(string status, string message) { switch (message) { //OK case "0": if (status == "E") { DeviceStateReport("I"); Thread.Sleep(3000); JobReady("1"); } break; //NG case "1": //调用AGV暂停接口 break; case "9": break; default: break; } LogFactory.GetLog("Host906回复WMS905").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(status)}{Environment.NewLine}{JsonConvert.SerializeObject(message)}{Environment.NewLine}", ""); } /// /// 数据报告响应 工序902 回复工序901 /// public void DataReportResponse(string message) { LogFactory.GetLog("Host902回复WMS901").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(message)}{Environment.NewLine}", ""); #region //Dt_Task task = BaseDal.QueryFirst(x => (x.TaskState == (int)TaskOutStatusEnum.AGV_OutFinish || x.TaskState == (int)TaskRelocationStatusEnum.AGV_RelocationFinish || x.TaskState == (int)TaskInStatusEnum.AGV_InFinish) && x.Roadway != "PDA"); //if (task != null) //{ // switch (task.TaskType) // { // case 200: // //入库 // if (message == "0") // { // JobStartOrEnd("E", task.Remark, task.TargetAddress, "O", task.PalletCode); // } // break; // case 100: // //出库 // if (message == "0") // { // JobStartOrEnd("E", task.SourceAddress, task.Remark, "O", task.PalletCode); // } // break; // case 300: // if (message == "0") // { // JobStartOrEnd("E", task.SourceAddress, task.TargetAddress, "O", task.PalletCode); // } // _taskService.CompleteRelocationboundTask(task); // break; // case 400: // if (message == "0") // { // JobStartOrEnd("E", task.Remark, task.HostName, "O", task.PalletCode); // } // break; // default: // break; // } //} #endregion } /// /// HOST下发出库任务 工序103 /// /// public void HOSTOutBoundTask(string message) { try { var parseMessage = GetParse(message); switch (parseMessage.body.ret) { //OK case "0": var location = SqlSugarHelper.DbWMS.Queryable().Where(x => x.LocationCode == parseMessage.body.FromLocation).First(); if (location == null) { return; } if (location.LocationStatus == (int)LocationEnum.InStock) { Dt_Task task = InsertWMSTask(parseMessage); //BaseDal.AddData(task); location.LocationStatus = 1; SqlSugarHelper.DbWMS.Insertable(task).ExecuteCommand(); SqlSugarHelper.DbWMS.Updateable(location).ExecuteCommand(); InsertAGVTask(task); //Thread.Sleep(500); //915 JobReady("0"); Thread.Sleep(500); //104 DeviceReceiveJobResponse("0"); } else { ErrorReport(EmptyOutBoundconst, "A", "00"); Thread.Sleep(500); EmptyOutBound(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.TrayIdList.Substring(0, 10)); return; } break; default: break; } LogFactory.GetLog("Host103").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(parseMessage)}{Environment.NewLine}", ""); } catch (Exception ex) { DeviceReceiveJobResponse("1"); } } /// /// HOST设备状态获取 工序935 /// /// public void DeviceStationStatusInvite(string sSeqNo) { try { //回复936 StationStatus stationIn = GetStationStatus("B002"); StationStatus stationOut = GetStationStatus("B001"); List outStationStatus = GetOutStationStatus(stationOut); List 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", //Ready = status.AutoStatus == "MaintenanceMode" ? "0" : "1", }; if (status.RuntimeStatus == "Idle" && status.AutoStatus == "ControlMode") { AgvStatus.Ready = "1"; } else { AgvStatus.Ready = "0"; } DeviceStationStatusReport(AgvStatus, outStationStatus, inStationStatus, sSeqNo); } catch (Exception) { DeviceReceiveJobResponse("1"); } LogFactory.GetLog("Host935").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(sSeqNo)}{Environment.NewLine}", ""); } /// /// 接收HOST重新分配货位 工序106 /// /// public void RecreateGetLocation(string message) { try { var parseMessage = GetParse(message); var lcationEnd = parseMessage.body.ToLocation; switch (parseMessage.body.ret) { //OK case "0": var location = SqlSugarHelper.DbWMS.Queryable().Where(x => x.LocationCode == parseMessage.body.ToLocation).First(); if (location == null) { ErrorReport("2102", "A", "00"); Thread.Sleep(500); RecreateGetLocation(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.JobType, parseMessage.body.TrayIdList.Substring(0, 10)); return; } if (location.LocationStatus == (int)LocationEnum.Free) { var task = SqlSugarHelper.DbWMS.Queryable().Where(x => x.PalletCode == parseMessage.body.TrayIdList.Substring(0, 10)).First(); if (task == null) { location.LocationStatus = (int)LocationEnum.Lock; var tasknew = InsertWMSTask(parseMessage); InsertAGVTask(tasknew); BaseDal.AddData(tasknew); SqlSugarHelper.DbWMS.Updateable(location); Thread.Sleep(500); //915 JobReady("0"); } else { var Agvtask = SqlSugarHelper.DbAGV.Queryable().Where(x => x.d_involed5 == task.TaskNum.ToString()).First(); location.LocationStatus = (int)LocationEnum.Lock; task.TargetAddress = lcationEnd; Agvtask.d_involed2 = lcationEnd; SqlSugarHelper.DbWMS.Updateable(task); SqlSugarHelper.DbWMS.Updateable(location); SqlSugarHelper.DbAGV.Updateable(Agvtask); Thread.Sleep(500); //915 JobReady("0"); } return; } else { ErrorReport(Restocking, "A", "00"); Thread.Sleep(500); RecreateGetLocation(parseMessage.body.FromLocation, parseMessage.body.ToLocation, parseMessage.body.JobType, parseMessage.body.TrayIdList.Substring(0, 10)); return; } //NG case "1": break; //无库位分配 case "2": break; case "9": break; default: break; } LogFactory.GetLog("Host106重新分配库位").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(parseMessage)}{Environment.NewLine}", ""); } catch (Exception) { DeviceReceiveJobResponse("1"); } } /// /// HOST空出库响应 工序108 /// /// public void EmptyOutBoundResponse(string message) { if (message != null && message == "0") { DeviceStateReport("I"); Thread.Sleep(2000); JobReady("1"); } LogFactory.GetLog("Host108空出库响应").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(message)}{Environment.NewLine}", ""); } /// /// HOST获取设备状态 工序909 /// public void DeviceStatusReportRequest() { 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); LogFactory.GetLog("Host心跳").InfoFormat(true, $"请求参数:{JsonConvert.SerializeObject(AgvStatus)}{Environment.NewLine}{JsonConvert.SerializeObject(status)}{Environment.NewLine}", ""); } #endregion #region 全局方法 /// /// 拼接报文 /// /// /// /// 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); //var parseMessage = GetParse(str); LogFactory.GetLog("Socket发送报文").Info(true, str); return newArray; } catch (Exception ex) { throw new Exception(ex.Message); } } public string GetListStringOutStation(List outStationStatus) { return string.Join("", outStationStatus.Select(status => $"{status.StationName}{status.StationEnable}{status.IsDistributionTask}{status.Spare1}")); } public string GetListStringInStation(List inStationStatus) { return string.Join("", inStationStatus.Select(status => $"{status.StationName}{status.StationEnable}{status.IsDistributionTask}{status.IsHasPallte}{status.Spare1}{status.StationPallteCount}{status.PallteCode}{status.Spare2}")); } /// /// 将对象值凭拼接 /// /// /// 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(); } /// /// 获取CheckSum值 /// /// /// /// 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 GetOutStationStatus(StationStatus stationOut) { List outStationStatus = new List(); 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 GetInStationStatus(StationStatus stationIn) { List inStationStatus = new List(); 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; } public ParseMessage SubString(string Y) { const string STX = "0x02"; const string ETX = "0x03"; // 检查是否以 STX 开头、ETX 结尾 if (Y.Substring(0, 4) == STX && Y.Substring(Y.Length - 4) == ETX) { string str = Y.Substring(4, Y.Length - 8); byte[] message = Encoding.UTF8.GetBytes(str); int newLength = message.Length - 2; if (newLength < 0) { throw new ArgumentException("数组长度不足,无法去掉最后两位。"); } byte[] newArray = new byte[newLength]; Array.Copy(message, 0, newArray, 0, newLength); string calculatedChecksum = GetCheckSum(newArray); string receivedChecksum = str.Substring(str.Length - 2); 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), //Body = x.Substring(21), }; return parseMessage; } else { Console.WriteLine("校验失败!"); return null; } } else { Console.WriteLine("无效报文格式!"); return null; } } #endregion #region 定义对象 #endregion #region 私有方法 private Dt_Task 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 = Instation.stationName; task.TargetAddress = parseMessage.body.ToLocation; task.CurrentAddress = Instation.stationName; 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; Dt_StationManager Instation = _stationManagerRepository.QueryFirst(x => x.HostName == parseMessage.body.ToLocation.Substring(4, 2)); task.TargetAddress = Instation.stationName; task.CurrentAddress = parseMessage.body.FromLocation; task.NextAddress = Instation.stationName; taskType = (int)TaskOutboundTypeEnum.Outbound; taskState = (int)TaskOutStatusEnum.OutNew; task.Remark = parseMessage.body.ToLocation; } else if (parseMessage.body.JobType == "S") { Dt_StationManager stationone = _stationManagerRepository.QueryFirst(x => x.HostName == parseMessage.body.FromLocation.Substring(4, 2)); Dt_StationManager stationtwo = _stationManagerRepository.QueryFirst(x => x.HostName == parseMessage.body.ToLocation.Substring(4, 2)); taskType = (int)TaskStationTypeEnum.StationToStation; taskState = (int)TaskOutStatusEnum.OutNew; task.SourceAddress = stationone.stationName; task.TargetAddress = stationtwo.stationName; task.CurrentAddress = stationone.stationName; task.NextAddress = stationtwo.stationName; task.Remark = parseMessage.body.FromLocation; task.HostName = parseMessage.body.ToLocation; 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); return task; } /// /// 添加AGV任务 /// /// 任务对象 /// private int InsertAGVTask(Dt_Task task) { string SourceAddress = string.Empty; string TargetAddress = string.Empty; if (task.TaskType == (int)TaskInboundTypeEnum.Inbound) { SourceAddress = task.SourceAddress; TargetAddress = InsertHyphenEveryTwoChars(task.TargetAddress); } else if (task.TaskType == (int)TaskOutboundTypeEnum.Outbound) { SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress); TargetAddress = task.TargetAddress; } else if (task.TaskType == (int)TaskRelocationTypeEnum.Relocation) { TargetAddress = InsertHyphenEveryTwoChars(task.TargetAddress); SourceAddress = InsertHyphenEveryTwoChars(task.SourceAddress); } else if (task.TaskType == (int)TaskStationTypeEnum.StationToStation) { TargetAddress = task.TargetAddress; SourceAddress = task.SourceAddress; } task_call task_Call = new task_call() { d_task_type = task.TaskType == (int)TaskTypeEnum.Inbound ? "1" : "2", d_floor = "1", d_involed1 = SourceAddress, d_involed2 = TargetAddress, d_involed5 = task.TaskNum.ToString(), }; return SqlSugarHelper.DbAGV.Insertable(task_Call).ExecuteCommand(); } public ParseMessage GetParse(string x) { return 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), body = new ReceiveBody { ret = x.Substring(20, 1), JobOrderID = x.Substring(21, 16), priority = x.Substring(37, 1), FromLocation = x.Substring(38, 6), ToLocation = x.Substring(44, 6), JobType = x.Substring(50, 1), TrayCnt = x.Substring(51, 1), TrayIdList = x.Substring(52) }, }; } public AGVStatusRespone GetAGVStatus() { string urlnew = url + "/ilns/AGV/getState"; var result = HttpsClient.PostAsync(urlnew, JsonConvert.DeserializeObject>(new { getStatus = "1" }.ToJson())).Result; return JsonConvert.DeserializeObject(result.ToString()); } public StationStatus GetStationStatus(string stationName) { string urlnew = url + "/ilns/ctrl/getState"; var result = HttpsClient.PostAsync(urlnew, JsonConvert.DeserializeObject>(new { ctrlName = "B001" }.ToJson())).Result; return JsonConvert.DeserializeObject(result.ToString()); } public string CapitalizeFirstLetter(string s) { if (string.IsNullOrEmpty(s)) { return ""; } char firstChar = s[0]; return char.ToUpper(firstChar).ToString(); } 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 } }