chore: initial commit

This commit is contained in:
XingCheng3
2026-05-29 09:34:04 +08:00
commit 78ae9dcd2e
683 changed files with 68110 additions and 0 deletions

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

View 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 = "";
}
}
}

View File

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

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