Files
2026-05-29 09:34:04 +08:00

429 lines
20 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}
}
}