429 lines
20 KiB
C#
429 lines
20 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|