chore: initial commit
This commit is contained in:
428
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/AGV_BusinessLogic.cs
Normal file
428
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/AGV_BusinessLogic.cs
Normal file
@@ -0,0 +1,428 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ExternalDataSync;
|
||||
using MesServerWork;
|
||||
using MisDataSaveDate;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http;
|
||||
using MisDataSaveDate.MOM;
|
||||
using System.Data.SqlClient;
|
||||
using static MisDataSaveDate.Helper.ApiLogHelper;
|
||||
using MisDataSaveDate.Helper;
|
||||
using WebApi;
|
||||
using System.Security.Policy;
|
||||
using System.Data;
|
||||
using MisDataFunDll;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// AGV业务处理类
|
||||
/// </summary>
|
||||
public class AGV_BusinessLogic
|
||||
{
|
||||
static string agvBaseUrl = ConfigurationManager.AppSettings["AGV_BaseUrl"];
|
||||
|
||||
/// <summary>
|
||||
/// 处理AGV进入请求业务逻辑
|
||||
/// </summary>
|
||||
/// <param name="url">接口URL</param>
|
||||
/// <param name="jobj">AGV请求数据</param>
|
||||
/// <returns>处理结果</returns>
|
||||
public static string ProcessAGVEnterRequest(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = new AGV_Response();
|
||||
result.code = "0";
|
||||
result.message = "";
|
||||
result.reqCode = "";
|
||||
string errorMessage = "";
|
||||
|
||||
if (jobj == null)
|
||||
{
|
||||
result.code = "1";
|
||||
result.message = "参数格式不正确!";
|
||||
result.reqCode = "";
|
||||
string retString1 = JsonConvert.SerializeObject(result);
|
||||
SaveMesLog("AGV进入请求", "参数格式不正确!", MesLogType.ERROR);
|
||||
MyLog4Net.MyLogHelper.Info("AGV请求进入接口res:", retString1);
|
||||
return retString1;
|
||||
}
|
||||
|
||||
string str = jobj.ToString();
|
||||
//存储请求日志
|
||||
SaveLog_Interface_Request(url, 2, str, out int AID);
|
||||
|
||||
try
|
||||
{
|
||||
// 解析AGV请求内容
|
||||
AGV_EnterRequest enterRequest = JsonConvert.DeserializeObject<AGV_EnterRequest>(str);
|
||||
|
||||
// 必填字段校验
|
||||
if (string.IsNullOrWhiteSpace(enterRequest.reqCode))
|
||||
{
|
||||
throw new Exception("请求编号(reqCode)不能为空");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enterRequest.reqTime))
|
||||
{
|
||||
throw new Exception("请求时间戳(reqTime)不能为空");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enterRequest.currentPositionCode))
|
||||
{
|
||||
throw new Exception("当前位置编号(currentPositionCode)不能为空");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enterRequest.method))
|
||||
{
|
||||
throw new Exception("方法名(method)不能为空");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enterRequest.robotCode))
|
||||
{
|
||||
throw new Exception("AGV编号(robotCode)不能为空");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enterRequest.taskCode))
|
||||
{
|
||||
throw new Exception("任务编号(taskCode)不能为空");
|
||||
}
|
||||
|
||||
string method = enterRequest.method.Trim().ToLower();
|
||||
if (method != "apply" && method != "release" && method != "lower" && method != "raise")
|
||||
{
|
||||
throw new Exception($"不支持的method:{enterRequest.method}");
|
||||
}
|
||||
|
||||
//enterRequest.currentPositionCode = RemoveTrailingZero(enterRequest.currentPositionCode);
|
||||
|
||||
// 调用存储过程保存AGV请求数据
|
||||
var param = new SqlParameter[] {
|
||||
new SqlParameter("@reqCode", enterRequest.reqCode ?? ""),
|
||||
new SqlParameter("@reqTime", enterRequest.reqTime ?? ""),
|
||||
new SqlParameter("@cooX", enterRequest.cooX ?? ""),
|
||||
new SqlParameter("@cooY", enterRequest.cooY ?? ""),
|
||||
new SqlParameter("@currentPositionCode", enterRequest.currentPositionCode ?? ""),
|
||||
new SqlParameter("@data", ""),// enterRequest.data ??
|
||||
new SqlParameter("@mapCode", enterRequest.mapCode ?? ""),
|
||||
new SqlParameter("@mapDataCode", enterRequest.mapDataCode ?? ""),
|
||||
new SqlParameter("@stgBinCode", enterRequest.stgBinCode ?? ""),
|
||||
new SqlParameter("@method", method),
|
||||
new SqlParameter("@podCode", enterRequest.podCode ?? ""),
|
||||
new SqlParameter("@podDir", enterRequest.podDir ?? ""),
|
||||
new SqlParameter("@materialLot", enterRequest.materialLot ?? ""),
|
||||
new SqlParameter("@robotCode", enterRequest.robotCode ?? ""),
|
||||
new SqlParameter("@taskCode", enterRequest.taskCode ?? ""),
|
||||
new SqlParameter("@wbCode", enterRequest.wbCode ?? ""),
|
||||
new SqlParameter("@ctnrCode", enterRequest.ctnrCode ?? ""),
|
||||
new SqlParameter("@ctnrType", enterRequest.ctnrType ?? ""),
|
||||
new SqlParameter("@roadWayCode", enterRequest.roadWayCode ?? ""),
|
||||
new SqlParameter("@seq", enterRequest.seq ?? ""),
|
||||
new SqlParameter("@eqpCode", enterRequest.eqpCode ?? "")
|
||||
};
|
||||
|
||||
// 这里定义AGV返回的位置 - 从currentPositionCode获取并去掉尾部_1后缀
|
||||
string OpCode = "";
|
||||
try
|
||||
{
|
||||
// 从请求的currentPositionCode字段获取位置码
|
||||
string currentPositionCode = enterRequest.currentPositionCode?.ToString() ?? "";
|
||||
if (!string.IsNullOrEmpty(currentPositionCode))
|
||||
{
|
||||
// 去掉尾部的_1后缀,保留前面的库位号
|
||||
int lastUnderscoreIndex = currentPositionCode.LastIndexOf('_');
|
||||
if (lastUnderscoreIndex > 0)
|
||||
{
|
||||
OpCode = currentPositionCode.Substring(0, lastUnderscoreIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果没有下划线,直接使用原值
|
||||
OpCode = currentPositionCode;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果从currentPositionCode获取不到,使用wbCode作为备用
|
||||
if (string.IsNullOrEmpty(OpCode))
|
||||
{
|
||||
OpCode = enterRequest.wbCode?.ToString() ?? "";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 解析失败时使用wbCode作为备用
|
||||
OpCode = enterRequest.wbCode?.ToString() ?? "";
|
||||
SaveMesLog("AGV进入请求", $"解析currentPositionCode失败,使用wbCode作为备用:{ex.Message}", MesLogType.WARNING);
|
||||
}
|
||||
|
||||
// 跟新Moby表 AGV进入离开、下降举升状态
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, method, "1");
|
||||
|
||||
// 执行存储过程
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("AGV_光栅请求记录_增加", ref param, out errorMessage);
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case "apply":
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "inReq", enterRequest.reqCode);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "inTask", enterRequest.taskCode);
|
||||
MisDataFun.Rrunning_AGV_Arrive(OpCode); // 磨合AGV到达
|
||||
MIS_BASE.WritePLC(301, OpCode, true); // 请求进入
|
||||
SaveMesLog(OpCode, $"AGV请求进入成功:工位{OpCode}", MesLogType.INFO);
|
||||
break;
|
||||
case "release": // 离开在收到后反馈回去 发给PLC
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "outReq", enterRequest.reqCode);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "outTask", enterRequest.taskCode);
|
||||
MisDataFun.Rrunning_AGV_Leave(OpCode); // 磨合AGV离开
|
||||
// 读取一下上一个请求进入的工件编号~~~ 然后传过去 找对应的
|
||||
//bool agvOutResult = PassAgvInOut(OpCode, "", "release"); // 通知AGV可以离开
|
||||
//if (!agvOutResult)
|
||||
//{
|
||||
// errorMessage = $"AGV离开通知失败:工位{OpCode}";
|
||||
// SaveMesLog("AGV进入请求", errorMessage, "error");
|
||||
//}
|
||||
SaveMesLog(OpCode, $"AGV离开通知成功:工位{OpCode}", MesLogType.INFO);
|
||||
MIS_BASE.WritePLC(301, OpCode, false); // 请求进入
|
||||
// AGV已离开 - 通知PLC
|
||||
MIS_BASE.WritePLC(303, OpCode, true);
|
||||
MIS_BASE.WritePLC(302, OpCode, false); // 托盘到位 器具放置完毕 请求扫描器具码
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "AllowAGVLeave", "1");
|
||||
break;
|
||||
case "lower":
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "lowerReq", enterRequest.reqCode);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "lowerTask", enterRequest.taskCode);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "当前状态", "AGV请求下降");
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "备注", $"lowerReq={enterRequest.reqCode};lowerTask={enterRequest.taskCode}");
|
||||
MIS_BASE.WritePLC(500, OpCode, true); // AGV请求下降
|
||||
SaveMesLog(OpCode, $"AGV请求下降成功:工位{OpCode}", MesLogType.INFO);
|
||||
break;
|
||||
case "raise":
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "raiseReq", enterRequest.reqCode);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "raiseTask", enterRequest.taskCode);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "当前状态", "AGV请求举升");
|
||||
MisDataFun.Location_MIS_MOBY_Insert(OpCode, "备注", $"raiseReq={enterRequest.reqCode};raiseTask={enterRequest.taskCode}");
|
||||
MIS_BASE.WritePLC(501, OpCode, true); // AGV请求举升
|
||||
SaveMesLog(OpCode, $"AGV请求举升成功:工位{OpCode}", MesLogType.INFO);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
result.code = "500";
|
||||
result.message = "AGV请求处理失败";
|
||||
result.reqCode = enterRequest.reqCode;
|
||||
SaveMesLog("AGV进入请求", errorMessage, MesLogType.ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = "0";
|
||||
result.message = "";
|
||||
result.reqCode = enterRequest.reqCode;
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
// 记录错误日志
|
||||
SaveMesLog("AGV进入请求", err.Message, MesLogType.ERROR);
|
||||
|
||||
result.code = "1";
|
||||
result.message = err.Message;
|
||||
|
||||
// 尝试从请求中获取reqCode
|
||||
try
|
||||
{
|
||||
AGV_EnterRequest tempRequest = JsonConvert.DeserializeObject<AGV_EnterRequest>(str);
|
||||
result.reqCode = tempRequest?.reqCode ?? "";
|
||||
}
|
||||
catch
|
||||
{
|
||||
result.reqCode = "";
|
||||
}
|
||||
}
|
||||
|
||||
string retString = JsonConvert.SerializeObject(result);
|
||||
// 存储响应日志
|
||||
SaveLog_Interface_Response(retString, AID);
|
||||
MyLog4Net.MyLogHelper.Info("AGV请求进入接口res:", retString);
|
||||
return retString;
|
||||
}
|
||||
|
||||
public static string RemoveTrailingZero(string input)
|
||||
{
|
||||
if (input != null && input.Contains("-0") && input.Length >= 3)
|
||||
{
|
||||
int dashIndex = input.LastIndexOf("-0");
|
||||
if (dashIndex > 0 && dashIndex == input.Length - 3) // 确保是最后的-0x格式
|
||||
{
|
||||
return input.Remove(dashIndex + 1, 1); // 去掉"-0"中的0
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送AGV任务继续执行请求(允许进入、离开、下降或举升)
|
||||
/// </summary>
|
||||
/// <param name="opName">工位号</param>
|
||||
/// <param name="engineID">工件编号</param>
|
||||
/// <param name="type">任务类型</param>
|
||||
/// <returns>操作是否成功</returns>
|
||||
public static bool PassAgvInOut(string opName, string engineID, string type)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 其实没有用 engineID 这玩意正常本工位获取不到
|
||||
|
||||
// 调用存储过程获取AGV任务数据
|
||||
var param = new SqlParameter[] {
|
||||
new SqlParameter("@opName", opName),
|
||||
new SqlParameter("@engineID", engineID),
|
||||
new SqlParameter("@type", type)
|
||||
};
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("AGV_允许进入离开_查询", ref param, out DataTable dtResult, out string errMessage);
|
||||
|
||||
if (dtResult == null || dtResult.Rows.Count == 0)
|
||||
{
|
||||
SaveMesLog(opName, $"获取AGV任务数据失败:工位号={opName}, 工件编号={engineID}, 任务类型={type}, 错误信息={errMessage}", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 从数据库获取请求编号和任务号
|
||||
string reqCode = dtResult.Rows[0]["reqCode"].ToString();
|
||||
string taskCode = dtResult.Rows[0]["taskCode"].ToString();
|
||||
|
||||
// 构造AGV反馈请求对象
|
||||
AGV_FeedbackRequest agvFeedbackRequest = new AGV_FeedbackRequest()
|
||||
{
|
||||
reqCode = reqCode,
|
||||
taskCode = taskCode
|
||||
};
|
||||
|
||||
// 获取AGV接口地址并发送请求
|
||||
string interfaceUrl = agvBaseUrl.TrimEnd('/') + "/rcms/services/rest/hikRpcService/continueTask";
|
||||
string jsonStr = JsonConvert.SerializeObject(agvFeedbackRequest);
|
||||
|
||||
//存储请求日志
|
||||
SaveLog_Interface_Request(interfaceUrl, 1, jsonStr, out int AID);
|
||||
|
||||
string resultStr = "";
|
||||
try
|
||||
{
|
||||
resultStr = Post.Post_Auto(interfaceUrl, jsonStr);
|
||||
}
|
||||
catch (Exception httpEx)
|
||||
{
|
||||
SaveMesLog(opName, $"AGV接口HTTP请求异常:工位号={opName}, 工件编号={engineID}, 任务类型={type}, 异常信息={httpEx.Message}", MesLogType.ERROR);
|
||||
// 存储响应日志
|
||||
SaveLog_Interface_Response($"HTTP请求异常:{httpEx.Message}", AID);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 存储响应日志
|
||||
SaveLog_Interface_Response(resultStr, AID);
|
||||
|
||||
// 解析响应结果
|
||||
if (string.IsNullOrWhiteSpace(resultStr))
|
||||
{
|
||||
SaveMesLog(opName, "AGV接口返回空响应", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否为Post.Post_Auto返回的错误格式
|
||||
try
|
||||
{
|
||||
JObject tempResult = JsonConvert.DeserializeObject<JObject>(resultStr);
|
||||
if (tempResult != null && tempResult["code"] != null && tempResult["code"].ToString() == "500")
|
||||
{
|
||||
string errorMsg = tempResult["message"]?.ToString() ?? "HTTP请求异常";
|
||||
SaveMesLog(opName, $"AGV接口HTTP异常:工位号={opName}, 工件编号={engineID}, 任务类型={type}, 错误信息={errorMsg}", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果不是标准JSON格式,继续后续处理
|
||||
}
|
||||
|
||||
AGV_Response result = JsonConvert.DeserializeObject<AGV_Response>(resultStr);
|
||||
if (result == null)
|
||||
{
|
||||
SaveMesLog(opName, "AGV接口返回数据格式错误", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查AGV返回码
|
||||
string code = result.code?.ToString();
|
||||
if (code != "0")
|
||||
{
|
||||
string message = result.message?.ToString() ?? "未知错误";
|
||||
SaveMesLog(opName, $"允许AGV光栅请求失败:工位号={opName}, 工件编号={engineID}, 任务类型={type}, code={code}, message={message}", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 请求成功后调用存储过程更新送料状态
|
||||
var updateParam = new SqlParameter[] {
|
||||
new SqlParameter("@opName", opName),
|
||||
new SqlParameter("@engineID", engineID),
|
||||
new SqlParameter("@reqCode", reqCode),
|
||||
new SqlParameter("@taskCode", taskCode)
|
||||
};
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("AGV_光栅请求记录_允许", ref updateParam, out string updateErrMessage);
|
||||
|
||||
if (!string.IsNullOrEmpty(updateErrMessage))
|
||||
{
|
||||
SaveMesLog(opName, $"允许AGV光栅请求失败:工位号={opName}, 工件编号={engineID}, 任务类型={type}, 异常信息={updateErrMessage}", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 根据任务类型进行后续操作
|
||||
if (type == "apply")
|
||||
{
|
||||
// AGV已进入
|
||||
MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVEnter", "1");
|
||||
}
|
||||
else if (type == "release")
|
||||
{
|
||||
// AGV已离开 - 通知PLC
|
||||
MIS_BASE.WritePLC(301, opName, false); // 请求进入
|
||||
MIS_BASE.WritePLC(303, opName, true);
|
||||
MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVLeave", "1");
|
||||
}
|
||||
else if (type == "lower")
|
||||
{
|
||||
// AGV允许下降
|
||||
MIS_BASE.WritePLC(500, opName, false); // AGV请求下降
|
||||
MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVLower", "1");
|
||||
MisDataFun.Location_MIS_MOBY_Insert(opName, "当前状态", "允许AGV下降");
|
||||
}
|
||||
else if (type == "raise")
|
||||
{
|
||||
// AGV允许举升
|
||||
MIS_BASE.WritePLC(501, opName, false); // AGV请求举升
|
||||
MisDataFun.Location_MIS_MOBY_Insert(opName, "AllowAGVRaise", "1");
|
||||
MisDataFun.Location_MIS_MOBY_Insert(opName, "当前状态", "允许AGV举升");
|
||||
}
|
||||
|
||||
SaveMesLog(opName, $"允许AGV光栅请求成功:工件编号={engineID}, 请求编号={reqCode}, 任务号={taskCode}, 工位号={opName}, 任务类型={type}", MesLogType.INFO);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SaveMesLog(opName, $"允许AGV光栅请求失败:工位号={opName}, 工件编号={engineID}, 任务类型={type}, 异常信息={ex.Message}", MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
164
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/AGV_Models.cs
Normal file
164
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/AGV_Models.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// AGV进入请求实体类
|
||||
/// </summary>
|
||||
public class AGV_EnterRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求编号,每个请求都要一个唯一编号,同一个请求重复提交,使用同一编号
|
||||
/// </summary>
|
||||
public string reqCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求时间戳,格式: "yyyy-MM-dd HH:mm:ss"
|
||||
/// </summary>
|
||||
public string reqTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地码 X 坐标(mm):任务完成时有值
|
||||
/// </summary>
|
||||
public string cooX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地码 Y 坐标(mm):任务完成时有值
|
||||
/// </summary>
|
||||
public string cooY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前位置编号
|
||||
/// </summary>
|
||||
public string currentPositionCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义字段,不超过2000个字符
|
||||
/// </summary>
|
||||
public object data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地图编号
|
||||
/// </summary>
|
||||
public string mapCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 地码编号:任务完成时有值
|
||||
/// </summary>
|
||||
public string mapDataCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仓位编号:叉车与CTU任务时有值
|
||||
/// </summary>
|
||||
public string stgBinCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 方法名, apply: 申请进入;release:申请离开
|
||||
/// </summary>
|
||||
public string method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货架编号:背货架时有值
|
||||
/// </summary>
|
||||
public string podCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// "180","0","90","-90" 分别对应地图的"左","右","上","下":任务完成时有值
|
||||
/// </summary>
|
||||
public string podDir { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物料编号
|
||||
/// </summary>
|
||||
public string materialLot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV编号(同 agvCode)
|
||||
/// </summary>
|
||||
public string robotCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前任务单号
|
||||
/// </summary>
|
||||
public string taskCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工作位,与RCS-2000端配置的位置名称一致。任务完成时有值,与生成任务单接口中的wbCode一致
|
||||
/// </summary>
|
||||
public string wbCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 容器编号
|
||||
/// </summary>
|
||||
public string ctnrCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 容器类型
|
||||
/// </summary>
|
||||
public string ctnrType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 巷道编号
|
||||
/// </summary>
|
||||
public string roadWayCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 巷道内顺序号,巷道尾是0,到巷道头依次递增1
|
||||
/// </summary>
|
||||
public string seq { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备编号,如梳齿式工作站、输送线等,一般使用于CTU场景。系统根据仓位定位到关联的设备编号
|
||||
/// </summary>
|
||||
public string eqpCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AGV请求反馈实体类
|
||||
/// </summary>
|
||||
public class AGV_FeedbackRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求编号
|
||||
/// </summary>
|
||||
public string reqCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务单号
|
||||
/// </summary>
|
||||
public string taskCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AGV接口通用响应类
|
||||
/// </summary>
|
||||
public class AGV_Response
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回码 "0"表示成功
|
||||
/// </summary>
|
||||
public string code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回消息
|
||||
/// </summary>
|
||||
public string message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求编号
|
||||
/// </summary>
|
||||
public string reqCode { get; set; }
|
||||
|
||||
public AGV_Response()
|
||||
{
|
||||
code = "0";
|
||||
message = "成功";
|
||||
reqCode = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using MisDataSaveDate;
|
||||
using System.Web.Http;
|
||||
using static MisDataSaveDate.Helper.ApiLogHelper;
|
||||
using MisDataSaveDate.Helper;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// 西开 AGV 业务处理类
|
||||
/// 处理 AGV -> MES 的接收请求
|
||||
/// </summary>
|
||||
public class ZZAGV_BusinessLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理状态更新请求(到达/离开)
|
||||
/// </summary>
|
||||
/// <param name="url">接口URL</param>
|
||||
/// <param name="jobj">请求数据</param>
|
||||
/// <returns>处理结果 JSON 字符串</returns>
|
||||
public static string ProcessStatusUpdate(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = ZZAGV_Response.Success();
|
||||
string str = jobj?.ToString() ?? "";
|
||||
|
||||
// 存储请求日志
|
||||
SaveLog_Interface_Request(url, 2, str, out int AID);
|
||||
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
|
||||
ZZAGV_StatusUpdateRequest request = JsonConvert.DeserializeObject<ZZAGV_StatusUpdateRequest>(str);
|
||||
|
||||
// 参数校验
|
||||
if (string.IsNullOrWhiteSpace(request.position))
|
||||
{
|
||||
throw new Exception("工位编号(position)不能为空");
|
||||
}
|
||||
|
||||
string typeDesc = request.type == 1 ? "到达" : (request.type == 2 ? "离开" : "未知");
|
||||
SaveMesLog("ZZAGV_StatusUpdate", $"AGV状态更新:工位={request.position}, 类型={typeDesc}, AGV={request.agvid}, 物料={request.materialCode}", MesLogType.INFO);
|
||||
|
||||
// TODO: 后续业务逻辑在此添加
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = ZZAGV_Response.Fail(1, ex.Message);
|
||||
SaveMesLog("ZZAGV_StatusUpdate", $"处理异常:{ex.Message}", MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string retString = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(retString, AID);
|
||||
return retString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理动作完成请求(举升/下降)
|
||||
/// </summary>
|
||||
/// <param name="url">接口URL</param>
|
||||
/// <param name="jobj">请求数据</param>
|
||||
/// <returns>处理结果 JSON 字符串</returns>
|
||||
public static string ProcessActionComplete(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = ZZAGV_Response.Success();
|
||||
string str = jobj?.ToString() ?? "";
|
||||
|
||||
// 存储请求日志
|
||||
SaveLog_Interface_Request(url, 2, str, out int AID);
|
||||
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
|
||||
ZZAGV_ActionCompleteRequest request = JsonConvert.DeserializeObject<ZZAGV_ActionCompleteRequest>(str);
|
||||
|
||||
// 参数校验
|
||||
if (string.IsNullOrWhiteSpace(request.position))
|
||||
{
|
||||
throw new Exception("工位编号(position)不能为空");
|
||||
}
|
||||
|
||||
string typeDesc = request.type == 1 ? "举升完成" : (request.type == 2 ? "下降完成" : "未知");
|
||||
SaveMesLog("ZZAGV_ActionComplete", $"AGV动作完成:工位={request.position}, 类型={typeDesc}", MesLogType.INFO);
|
||||
|
||||
// TODO: 后续业务逻辑在此添加
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = ZZAGV_Response.Fail(1, ex.Message);
|
||||
SaveMesLog("ZZAGV_ActionComplete", $"处理异常:{ex.Message}", MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string retString = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(retString, AID);
|
||||
return retString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理故障/报警推送请求
|
||||
/// </summary>
|
||||
/// <param name="url">接口URL</param>
|
||||
/// <param name="jobj">请求数据</param>
|
||||
/// <returns>处理结果 JSON 字符串</returns>
|
||||
public static string ProcessAlarmPush(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = ZZAGV_Response.Success();
|
||||
string str = jobj?.ToString() ?? "";
|
||||
|
||||
// 存储请求日志
|
||||
SaveLog_Interface_Request(url, 2, str, out int AID);
|
||||
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
|
||||
ZZAGV_AlarmPushRequest request = JsonConvert.DeserializeObject<ZZAGV_AlarmPushRequest>(str);
|
||||
|
||||
string typeDesc = request.type == 1 ? "AGV故障" : (request.type == 2 ? "区域故障" : "未知");
|
||||
SaveMesLog("ZZAGV_AlarmPush", $"AGV故障推送:类型={typeDesc}, AGV={request.agvNo}, 故障码={request.errorCode}, 信息={request.errorMsg}", MesLogType.WARNING);
|
||||
|
||||
// TODO: 后续业务逻辑在此添加
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = ZZAGV_Response.Fail(1, ex.Message);
|
||||
SaveMesLog("ZZAGV_AlarmPush", $"处理异常:{ex.Message}", MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string retString = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(retString, AID);
|
||||
return retString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理任务执行结果请求
|
||||
/// </summary>
|
||||
/// <param name="url">接口URL</param>
|
||||
/// <param name="jobj">请求数据</param>
|
||||
/// <returns>处理结果 JSON 字符串</returns>
|
||||
public static string ProcessTaskResult(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = ZZAGV_Response.Success();
|
||||
string str = jobj?.ToString() ?? "";
|
||||
|
||||
// 存储请求日志
|
||||
SaveLog_Interface_Request(url, 2, str, out int AID);
|
||||
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
|
||||
ZZAGV_TaskResultRequest request = JsonConvert.DeserializeObject<ZZAGV_TaskResultRequest>(str);
|
||||
|
||||
// 参数校验
|
||||
if (string.IsNullOrWhiteSpace(request.requestTaskId))
|
||||
{
|
||||
throw new Exception("任务ID(requestTaskId)不能为空");
|
||||
}
|
||||
|
||||
string statusDesc = request.status == "success" ? "成功" : "失败";
|
||||
SaveMesLog("ZZAGV_TaskResult", $"AGV任务结果:任务ID={request.requestTaskId}, 状态={statusDesc}, AGV={request.agvNo}, 消息={request.message}", MesLogType.INFO);
|
||||
|
||||
// TODO: 后续业务逻辑在此添加
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = ZZAGV_Response.Fail(1, ex.Message);
|
||||
SaveMesLog("ZZAGV_TaskResult", $"处理异常:{ex.Message}", MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string retString = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(retString, AID);
|
||||
return retString;
|
||||
}
|
||||
}
|
||||
}
|
||||
221
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/ZZAGV_Models.cs
Normal file
221
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/ZZAGV_Models.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
#region AGV -> MES 接收请求模型
|
||||
|
||||
/// <summary>
|
||||
/// 状态更新请求(到达/离开)
|
||||
/// AGV 到达或离开工位时通知 MES
|
||||
/// </summary>
|
||||
public class ZZAGV_StatusUpdateRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 工位编号
|
||||
/// </summary>
|
||||
public string position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型:1-到达,2-离开
|
||||
/// </summary>
|
||||
public int type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 物料编码/产品编码
|
||||
/// </summary>
|
||||
public string materialCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV车号
|
||||
/// </summary>
|
||||
public string agvid { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动作完成请求(举升/下降)
|
||||
/// AGV 完成托盘举升或下降动作后通知 MES
|
||||
/// </summary>
|
||||
public class ZZAGV_ActionCompleteRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 工位编号
|
||||
/// </summary>
|
||||
public string position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型:1-举升完成,2-下降完成
|
||||
/// </summary>
|
||||
public int type { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 故障/报警推送请求
|
||||
/// AGV 上报故障或区域故障
|
||||
/// </summary>
|
||||
public class ZZAGV_AlarmPushRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// AGV车号
|
||||
/// </summary>
|
||||
public string agvNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障代码
|
||||
/// </summary>
|
||||
public string errorCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障信息
|
||||
/// </summary>
|
||||
public string errorMsg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 故障类型:1-AGV故障,2-区域故障
|
||||
/// </summary>
|
||||
public int type { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务执行结果请求
|
||||
/// AGV 告知 MES 任务是否执行成功
|
||||
/// </summary>
|
||||
public class ZZAGV_TaskResultRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务唯一ID(与下发任务时的 requestTaskId 对应)
|
||||
/// </summary>
|
||||
public string requestTaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行状态:success-成功,fail-失败
|
||||
/// </summary>
|
||||
public string status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AGV车号
|
||||
/// </summary>
|
||||
public string agvNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 失败原因(成功时为空)
|
||||
/// </summary>
|
||||
public string message { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MES -> AGV 发送请求模型
|
||||
|
||||
/// <summary>
|
||||
/// 下发任务请求
|
||||
/// MES 给 AGV 下发搬运任务
|
||||
/// </summary>
|
||||
public class ZZAGV_AddTaskRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务唯一ID(由 MES 生成)
|
||||
/// </summary>
|
||||
public string requestTaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 抬货点/取货位置
|
||||
/// </summary>
|
||||
public string startPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 卸货点/目标位置
|
||||
/// </summary>
|
||||
public string endPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 产品编码/物料编码
|
||||
/// </summary>
|
||||
public string materialCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 放行请求
|
||||
/// MES 告知 AGV 可以离开当前位置
|
||||
/// </summary>
|
||||
public class ZZAGV_AllowLeaveRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求ID
|
||||
/// </summary>
|
||||
public string requestId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前位置编号
|
||||
/// </summary>
|
||||
public string position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 放行标志(固定为1)
|
||||
/// </summary>
|
||||
public int allowLeave { get; set; } = 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 通用响应模型
|
||||
|
||||
/// <summary>
|
||||
/// 西开 AGV 接口通用响应
|
||||
/// </summary>
|
||||
public class ZZAGV_Response
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回码:0-成功,其他-失败
|
||||
/// </summary>
|
||||
public int code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回描述信息
|
||||
/// </summary>
|
||||
public string desc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public bool success { get; set; }
|
||||
|
||||
public ZZAGV_Response()
|
||||
{
|
||||
code = 0;
|
||||
desc = "成功";
|
||||
success = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置成功响应
|
||||
/// </summary>
|
||||
public static ZZAGV_Response Success(string desc = "成功")
|
||||
{
|
||||
return new ZZAGV_Response
|
||||
{
|
||||
code = 0,
|
||||
desc = desc,
|
||||
success = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置失败响应
|
||||
/// </summary>
|
||||
public static ZZAGV_Response Fail(int code, string desc)
|
||||
{
|
||||
return new ZZAGV_Response
|
||||
{
|
||||
code = code,
|
||||
desc = desc,
|
||||
success = false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user