using System.Diagnostics;
|
using System.Text;
|
using Microsoft.Data.SqlClient;
|
using Newtonsoft.Json;
|
using WIDESEA_Core.Enums;
|
using WIDESEAWCS_Common.AGVEnum;
|
using WIDESEAWCS_Common.TaskEnum;
|
using WIDESEAWCS_Core;
|
using WIDESEAWCS_Core.Helper;
|
using WIDESEAWCS_Core.Tool;
|
using WIDESEAWCS_DTO.TaskInfo;
|
using WIDESEAWCS_ISystemRepository;
|
using WIDESEAWCS_ITaskInfoRepository;
|
using WIDESEAWCS_Model.Models;
|
using WIDESEAWCS_QuartzJob;
|
|
namespace WIDESEAWCS_Tasks
|
{
|
public class SendTaskAGV
|
{
|
private static int _readSendAGVTaskSignalso = 0;
|
private static bool isTrue1 = false;
|
private static string name1 = "";
|
public static string url = AppSettings.Configuration["AGVTaskGeneration"];
|
public static void SendAGVTask1(ITaskRepository _taskRepository, IDt_StationinfoRepository _stationinfoRepository)
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
Dt_Task task = _taskRepository.QueryData(x => x.TaskState == (int)TaskInStatusEnum.InNew).OrderBy(r => r.CreateDate).FirstOrDefault(); //.ThenByDescending(r => r.Grade)
|
if (task != null)
|
{
|
TaskGenerationDto taskGenerationDto = new TaskGenerationDto();
|
{
|
taskGenerationDto.taskid = task.TaskNum.ToString();
|
taskGenerationDto.taskType = task.TaskType.ToString();
|
taskGenerationDto.floor = task.Floor.ToString();
|
taskGenerationDto.param1 = task.SourceAddress.ToString();
|
taskGenerationDto.param2 = task.TargetAddress.ToString();
|
taskGenerationDto.param3 = "";
|
taskGenerationDto.param4 = "";
|
taskGenerationDto.param5 = "";
|
taskGenerationDto.param6 = "";
|
taskGenerationDto.param7 = "";
|
taskGenerationDto.param8 = "";
|
taskGenerationDto.param9 = "";
|
}
|
var ResultData = HttpHelper.Post(url, taskGenerationDto.ToJson(), headers: new Dictionary<string, string>());
|
var res = JsonConvert.DeserializeObject<WebResponseContent>(ResultData);
|
if (res.code == 200)
|
{
|
WriteLog.Info("任务下发成功").Write($"任务号{task.TaskNum}", "任务下发成功");
|
int nextStatus = task.TaskState.GetNextNotCompletedStatus<TaskInStatusEnum>();
|
task.TaskState = nextStatus;
|
task.Dispatchertime = DateTime.Now;
|
_taskRepository.UpdateData(task);
|
}
|
else
|
{
|
WriteLog.Info("任务下发失败").Write($"任务号{task.TaskNum},信息{res.Message}", "任务下发失败");
|
//_unitOfWorkManage.RollbackTran();
|
content = WebResponseContent.Instance.Error($"{res.Message}");
|
}
|
}
|
Thread.Sleep(100);
|
Dt_Task dt_Task = _taskRepository.QueryData(x => x.TaskState == (int)TaskInStatusEnum.AGV_Queue).OrderBy(r => r.CreateDate).FirstOrDefault();
|
if (dt_Task != null)
|
{
|
var station = _stationinfoRepository.QueryFirst(x => x.StationCode == dt_Task.SourceAddress);
|
// 查找两个可用的空缓存架
|
var freeStations = _stationinfoRepository
|
.QueryData(x => x.Location_state == LocationStatusEnum.Free.ObjToInt() && x.Enable && x.Remark == station.Remark && x.Area == station.Area)// && x.Stationtype == station.Stationtype
|
.Take(2) // 只取前两个
|
.ToList();
|
|
int floor = 0;
|
if (station.Area.Contains("A区"))
|
{
|
floor = 32;
|
}
|
else
|
{
|
floor = 128;
|
}
|
if (freeStations.Count < 2)
|
{
|
throw new Exception("未找到两个可用的空缓存架");
|
}
|
// 检查这两个缓存架是否被任务占用
|
var stationCodes = freeStations.Select(s => s.StationCode).ToList();
|
freeStations[0].Location_state = LocationStatusEnum.Lock.ObjToInt();
|
_stationinfoRepository.UpdateData(freeStations[0]);
|
freeStations[1].Location_state = LocationStatusEnum.Lock.ObjToInt();
|
_stationinfoRepository.UpdateData(freeStations[1]);
|
//stationCodes.
|
var tasks = _taskRepository.QueryData(x => stationCodes.Contains(x.SourceAddress) || stationCodes.Contains(x.TargetAddress)).ToList();
|
if (tasks.Any())
|
{
|
throw new Exception("缓存架已有任务");
|
}
|
dt_Task.TargetAddress = string.Join("||", freeStations.Select(s => s.StationCode));
|
dt_Task.NextAddress = string.Join("||", freeStations.Select(s => s.StationCode));
|
dt_Task.TaskState = (int)TaskInStatusEnum.InNew;
|
dt_Task.TaskType = floor;
|
_taskRepository.UpdateData(dt_Task);
|
}
|
}
|
catch (Exception ex)
|
{
|
|
}
|
|
}
|
|
public static void SendAGVTask(AGV agv, ITaskRepository _taskRepository)
|
{
|
|
// 连接字符串 - 根据你的服务器信息修改
|
string connectionString = "Data Source=.;Initial Catalog=WIDESEAWCS_GanFengLiYeNew;User ID=sa;Password=sa123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
|
List<Dt_Task> dt_Tasks = _taskRepository.QueryData(x => x.TaskState == (int)TaskInStatusEnum.InNew);
|
foreach (Dt_Task task in dt_Tasks)
|
{
|
// 要插入的SQL语句
|
string insertSql = "INSERT INTO Dt_Stationinfo (StationCode, Location_state,Area,Enable,LastUpdateTime,Remark) VALUES (@StationCode, @Location_state,@Area,@Enable,@LastUpdateTime,@Remark)";
|
|
try
|
{
|
using (SqlConnection connection = new SqlConnection(connectionString))
|
{
|
connection.Open();
|
|
using (SqlCommand command = new SqlCommand(insertSql, connection))
|
{
|
// 添加参数防止SQL注入
|
command.Parameters.AddWithValue("StationCode", task.TaskNum);
|
command.Parameters.AddWithValue("Location_state", task.TaskNum);
|
command.Parameters.AddWithValue("Area", task.Roadway);
|
command.Parameters.AddWithValue("Enable", task.TaskNum);
|
command.Parameters.AddWithValue("LastUpdateTime", DateTime.Now);
|
command.Parameters.AddWithValue("Remark", task.Roadway);
|
command.Parameters.AddWithValue("Creater", "WCS");
|
command.Parameters.AddWithValue("CreateDate", DateTime.Now);
|
|
int rowsAffected = command.ExecuteNonQuery();
|
Console.WriteLine($"成功插入 {rowsAffected} 行数据");
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine($"发生错误: {ex.Message}");
|
}
|
}
|
|
// 检查AGV是否为空
|
if (agv == null)
|
{
|
return;
|
}
|
|
// 获取任务交互和重置交互的设备地址
|
var taskInteractiveR = agv.DeviceProDTOs.FirstOrDefault(r => r.DeviceProParamName == TaskDBName.taskInteractiveR.ToString())?.DeviceProAddress;
|
var taskInteractiveW1 = agv.DeviceProDTOs.FirstOrDefault(r => r.DeviceProParamName == TaskDBName.taskInteractiveW.ToString())?.DeviceProAddress;
|
var resetTaskW = agv.DeviceProDTOs.FirstOrDefault(r => r.DeviceProParamName == TaskDBName.resetTaskInteractiveW.ToString())?.DeviceProAddress;
|
var resetTaskInteractiveR = agv.DeviceProDTOs.FirstOrDefault(r => r.DeviceProParamName == TaskDBName.resetTaskInteractiveR.ToString())?.DeviceProAddress;
|
var taskID = agv.DeviceProDTOs.FirstOrDefault(r => r.DeviceProParamName == TaskDBName.taskID.ToString())?.DeviceProAddress;
|
|
// 如果地址未找到,直接返回
|
if (taskInteractiveR is null || taskInteractiveW1 is null || resetTaskW is null || resetTaskInteractiveR is null || taskID is null)
|
{
|
return;
|
}
|
|
try
|
{
|
// 读取任务交互和重置交互的状态
|
int taskInteractive = agv.Communicator.Read<Int16>(taskInteractiveR); // 1表示收到
|
int taskInteractiveW = agv.Communicator.Read<Int16>(taskInteractiveW1); // 0初始/1下发/2取消/3更改
|
int resetTaskInteractiveW = agv.Communicator.Read<Int16>(resetTaskW);
|
int resetTaskInteractiver = agv.Communicator.Read<Int16>(resetTaskInteractiveR);
|
|
// 处理任务交互W和重置交互W不为0的情况
|
if (isTrue1 && name1 == agv.DeviceName)
|
{
|
if (taskInteractiveW != 0 || resetTaskInteractiveW != 0 || taskInteractive != 0)
|
{
|
agv.Communicator.Write<UInt16>(resetTaskW, 1);
|
Task.Delay(2000).Wait();
|
resetTaskInteractiveW = agv.Communicator.Read<Int16>(resetTaskW);
|
|
if (resetTaskInteractiveW == 1)
|
{
|
agv.Communicator.Write<UInt16>(resetTaskW, 0);
|
agv.Communicator.Write<UInt16>(taskInteractiveW1, 0);
|
Task.Delay(2000).Wait();
|
}
|
return;
|
}
|
isTrue1 = false;
|
name1 = "";
|
}
|
|
// 如果重置交互R为1,则重置任务交互W
|
if (resetTaskInteractiver == 1)
|
{
|
agv.Communicator.Write<UInt16>(taskInteractiveW1, 0);
|
for (int i = 0; i < 5; i++)
|
{
|
Task.Delay(300).Wait(); // 用Task.Delay代替Thread.Sleep,以避免线程阻塞
|
int agvNumber = agv.Communicator.Read<Int16>(taskInteractiveW1);
|
if (agvNumber != 0)
|
{
|
agv.Communicator.Write<UInt16>(taskInteractiveW1, 0);
|
}
|
else
|
{
|
break;
|
}
|
}
|
}
|
|
// 如果AGV没有任务且任务交互W为0
|
if (taskInteractive == 0 && taskInteractiveW == 0)
|
{
|
// 查询新任务
|
Dt_Task agvTask = _taskRepository.QueryData(r => r.TaskState == (int)TaskInStatusEnum.InNew && r.Roadway == agv.DeviceName && r.TaskType == (int)TaskOutboundTypeEnum.Outbound)
|
.OrderBy(r => r.CreateDate).ThenByDescending(r => r.Grade).FirstOrDefault();
|
|
if (agvTask != null)
|
{
|
// 写入任务信息
|
string rel = TaskWrite(agv, agvTask, AGVJobEnum.newTaskEnum);
|
Task.Delay(1000).Wait();
|
|
// 检查任务ID是否写入正确
|
string taskId = agv.Communicator.Read<string>(taskID);
|
string numberPart = taskId.Split('-')[1];
|
if (numberPart != agvTask.TaskNum.ToString())
|
{
|
throw new Exception($"给AGV写入任务失败,任务号{agvTask.TaskNum}");
|
}
|
|
// 如果任务信息写入成功
|
if (string.IsNullOrEmpty(rel))
|
{
|
// 写入任务确认信号1
|
agv.Communicator.Write<UInt16>(taskInteractiveW1, 1);
|
Task.Delay(1000).Wait();
|
|
// 读取AGV的确认信号
|
int readTask1Ok = agv.Communicator.Read<Int16>(taskInteractiveR);
|
if (readTask1Ok == 1)
|
{
|
// 写入WCS的确认信号0
|
agv.Communicator.Write<UInt16>(taskInteractiveW1, 0);
|
Task.Delay(2000).Wait();
|
|
// 再次读取AGV的确认信号
|
int readTask0Ok = agv.Communicator.Read<Int16>(taskInteractiveR);
|
if (readTask0Ok == 0)
|
{
|
// 更新任务状态并保存
|
int nextStatus = agvTask.TaskState.GetNextNotCompletedStatus<TaskInStatusEnum>();
|
agvTask.TaskState = nextStatus;
|
agvTask.Dispatchertime = DateTime.Now;
|
_taskRepository.UpdateData(agvTask);
|
|
// 上传AGV运行数据(注释掉的代码)
|
// SendMESTask.SendMesTask(agvTask, 0);
|
}
|
else
|
{
|
throw new Exception($"给AGV写入任务确认0失败,任务号{agvTask.TaskNum}");
|
}
|
}
|
else if (readTask1Ok == 11)
|
{
|
// 处理任务异常情况
|
agv.Communicator.Write<UInt16>(taskInteractiveW1, 0);
|
Task.Delay(2000).Wait();
|
int readTask0Error = agv.Communicator.Read<int>(taskInteractiveR);
|
|
if (readTask0Error == 0)
|
{
|
// 更新任务状态为异常并保存
|
int nextStatus = agvTask.TaskState.GetNextNotCompletedStatus<TaskOutStatusEnum>();
|
agvTask.TaskState = nextStatus;
|
agvTask.Dispatchertime = DateTime.Now;
|
_taskRepository.UpdateData(agvTask);
|
}
|
else
|
{
|
throw new Exception($"给AGV写入任务异常确认0失败,任务号{agvTask.TaskNum}");
|
}
|
}
|
else
|
{
|
throw new Exception($"给AGV写入任务确认1失败,任务号{agvTask.TaskNum}");
|
}
|
}
|
else
|
{
|
throw new Exception($"给AGV写入任务失败,任务号{agvTask.TaskNum} {rel}");
|
}
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
// 记录异常信息(注释掉的代码)
|
// StackTrace sta = new StackTrace(ex, true);
|
// StackFrame sf = sta.GetFrame(0);
|
// WriteLog.Info("SendAGVTask").Write(ex.Message + " 行号 " + sf.GetFileLineNumber(), "SendAGVTask");
|
}
|
finally
|
{
|
// 记录日志(注释掉的代码)
|
// WriteLog.Info("SendAGVTask").Write(agv.PLCName + "\t" + DateTime.Now, "SendAGVTask");
|
|
// 重置信号量
|
Interlocked.Exchange(ref _readSendAGVTaskSignalso, 0);
|
}
|
}
|
|
|
public static string TaskWrite(AGV client, Dt_Task agvTask, AGVJobEnum jobEnum)
|
{
|
List<byte> sendData = new List<byte>();
|
string tmp = "KH-" + agvTask.TaskNum.ToString();
|
List<byte> taskID = Encoding.Default.GetBytes(tmp).ToList();//任务ID
|
taskID.Insert(0, 30);
|
taskID.Insert(1, Convert.ToByte(tmp.Length));
|
|
for (int i = 0; i < 30 - tmp.Length; i++)
|
{
|
taskID.Add(0);
|
}
|
sendData.AddRange(taskID);
|
|
List<byte> taskStart = Encoding.Default.GetBytes(agvTask.SourceAddress).ToList();
|
taskStart.Insert(0, 20);
|
taskStart.Insert(1, Convert.ToByte(agvTask.SourceAddress.Length));
|
|
for (int i = 0; i < 20 - agvTask.SourceAddress.Length; i++)
|
{
|
taskStart.Add(0);
|
}
|
sendData.AddRange(taskStart);
|
|
List<byte> taskEnd = Encoding.Default.GetBytes(agvTask.TargetAddress).ToList();
|
taskEnd.Insert(0, 20);
|
taskEnd.Insert(1, Convert.ToByte(agvTask.TargetAddress.Length));
|
|
for (int i = 0; i < 20 - agvTask.TargetAddress.Length; i++)
|
{
|
taskEnd.Add(0);
|
}
|
sendData.AddRange(taskEnd);
|
|
byte[] taskType = BitConverter.GetBytes((ushort)1).ToArray();
|
Array.Reverse(taskType);
|
sendData.AddRange(taskType);
|
|
List<byte> containerType = Encoding.Default.GetBytes(agvTask.Barcode).ToList();
|
containerType.Insert(0, 30);
|
containerType.Insert(1, Convert.ToByte(agvTask.Barcode.Length));
|
|
for (int i = 0; i < 30 - agvTask.Barcode.Length; i++)
|
{
|
containerType.Add(0);
|
}
|
sendData.AddRange(containerType);
|
|
byte[] taskPriority = BitConverter.GetBytes((ushort)1).ToArray();
|
Array.Reverse(taskPriority);
|
sendData.AddRange(taskPriority);
|
|
byte[] taskFlag = BitConverter.GetBytes((ushort)jobEnum).ToArray();
|
Array.Reverse(taskFlag);
|
sendData.AddRange(taskFlag);
|
|
var operateResult = client.Communicator.Write("DB1000.0", sendData.ToArray());
|
if (!operateResult)
|
return "AGV发送任务失败";
|
//WriteLog.Info("AGV发送任务").Write("任务号" + agvTask.agv_tasknum + "AGV编号" + client.PLCName + DateTime.Now, "AGV发送任务");
|
|
return "";
|
}
|
}
|
}
|