feat: 增加LG/TCS-AGV接口并完善物料校验与Function逻辑
This commit is contained in:
@@ -212,8 +212,14 @@
|
||||
<Compile Include="WebAPI\Other\DewPointData.cs" />
|
||||
<Compile Include="WebAPI\WEB\WEB_BusinessLogic.cs" />
|
||||
<Compile Include="WebAPI\WEB\WEB_Models.cs" />
|
||||
<Compile Include="WebAPI\WEB\LGWEB_BusinessLogic.cs" />
|
||||
<Compile Include="WebAPI\WEB\LGWEB_Models.cs" />
|
||||
<Compile Include="WebAPI\AGV\AGV_BusinessLogic.cs" />
|
||||
<Compile Include="WebAPI\AGV\AGV_Models.cs" />
|
||||
<Compile Include="WebAPI\AGV\LGAGV_BusinessLogic.cs" />
|
||||
<Compile Include="WebAPI\AGV\LGAGV_Models.cs" />
|
||||
<Compile Include="WebAPI\AGV\TCSAGV_BusinessLogic.cs" />
|
||||
<Compile Include="WebAPI\AGV\TCSAGV_Models.cs" />
|
||||
<Compile Include="WebAPI\Controller\WEBController.cs" />
|
||||
<Compile Include="WebAPI\FactoryMES\Analysis508Msg.cs" />
|
||||
<Compile Include="WebAPI\FactoryMES\CALL_Inerface_DataHandle.cs" />
|
||||
@@ -519,4 +525,4 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\WinSCP.6.5.3\build\WinSCP.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WinSCP.6.5.3\build\WinSCP.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Web.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using MisDataSaveDate.Helper;
|
||||
using static MisDataSaveDate.Helper.ApiLogHelper;
|
||||
using WebApi;
|
||||
using MesServerWork;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// 临工AGV接口业务处理。
|
||||
/// </summary>
|
||||
public class LGAGV_BusinessLogic
|
||||
{
|
||||
private const string DirectionMesToAgv = "MES_TO_AGV";
|
||||
private const string DirectionAgvToMes = "AGV_TO_MES";
|
||||
|
||||
/// <summary>
|
||||
/// MES调用临工AGV两点任务接口。
|
||||
/// </summary>
|
||||
public static LGAGV_CallResult CallAddTask(LGAGV_AddTaskRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("AGV任务参数不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.requestTaskId))
|
||||
{
|
||||
throw new Exception("任务ID(requestTaskId)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.startPosition))
|
||||
{
|
||||
throw new Exception("起点位置(startPosition)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.endPosition))
|
||||
{
|
||||
throw new Exception("终点位置(endPosition)不能为空");
|
||||
}
|
||||
|
||||
return PostToAgv("AddTaskFromMes", "/api/mes/AddTaskFromMes", request,
|
||||
request.requestTaskId, null, request.endPosition, null, request.materialCode, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MES调用临工AGV三点任务接口。
|
||||
/// </summary>
|
||||
public static LGAGV_CallResult CallAddTask2(LGAGV_AddTask2Request request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("AGV任务参数不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.requestTaskId))
|
||||
{
|
||||
throw new Exception("任务ID(requestTaskId)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.startPosition))
|
||||
{
|
||||
throw new Exception("起点位置(startPosition)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.midPosition))
|
||||
{
|
||||
throw new Exception("中间位置(midPosition)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.endPosition))
|
||||
{
|
||||
throw new Exception("终点位置(endPosition)不能为空");
|
||||
}
|
||||
|
||||
return PostToAgv("AddTaskFromMes2", "/api/mes/AddTaskFromMes2", request,
|
||||
request.requestTaskId, null, request.endPosition, null, request.materialCode, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MES调用临工AGV放行接口。
|
||||
/// </summary>
|
||||
public static LGAGV_CallResult CallAllowLeave(LGAGV_AllowLeaveRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("放行参数不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.requestId))
|
||||
{
|
||||
throw new Exception("请求ID(requestId)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.position))
|
||||
{
|
||||
throw new Exception("位置(position)不能为空");
|
||||
}
|
||||
|
||||
request.allowLeave = 1;
|
||||
return PostToAgv("AllowLeave", "/api/mes/AllowLeave", request,
|
||||
null, request.requestId, request.position, null, null, request.agvNo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理临工AGV到达/离开回调。
|
||||
/// </summary>
|
||||
public static string ProcessStatusUpdate(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = LGAGV_Response.Success();
|
||||
string requestText = jobj?.ToString() ?? "";
|
||||
SaveLog_Interface_Request(url, 2, requestText, out int aid);
|
||||
|
||||
LGAGV_StatusUpdateRequest request = null;
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
|
||||
request = JsonConvert.DeserializeObject<LGAGV_StatusUpdateRequest>(requestText);
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("请求参数格式不正确");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.requestId))
|
||||
{
|
||||
throw new Exception("请求ID(requestId)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.position))
|
||||
{
|
||||
throw new Exception("位置(position)不能为空");
|
||||
}
|
||||
if (request.type != 1 && request.type != 2)
|
||||
{
|
||||
throw new Exception("类型(type)只支持1到达、2离开");
|
||||
}
|
||||
|
||||
string procedureName = request.type == 1 ? "LG_AGV_库位Moby_AGV到达" : "LG_AGV_库位Moby_AGV离开";
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@requestId", request.requestId ?? ""),
|
||||
new SqlParameter("@position", request.position ?? ""),
|
||||
new SqlParameter("@materialCode", request.materialCode ?? ""),
|
||||
new SqlParameter("@agvNo", request.agvNo ?? "")
|
||||
};
|
||||
ExecuteResultProcedure(procedureName, ref param);
|
||||
WriteOp10PlcStatus(request);
|
||||
|
||||
SaveInterfaceRecord("StatusUpdate", DirectionAgvToMes, request.position, request.position,
|
||||
null, request.requestId, request.position, request.type, request.materialCode, request.agvNo,
|
||||
"", requestText, "", 1, "");
|
||||
|
||||
string typeDesc = request.type == 1 ? "到达" : "离开";
|
||||
SaveMesLog("LGAGV_StatusUpdate", $"临工AGV{typeDesc}:位置={request.position}, requestId={request.requestId}, AGV={request.agvNo}", MesLogType.INFO);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = LGAGV_Response.Fail(ex.Message);
|
||||
SaveInterfaceRecord("StatusUpdate", DirectionAgvToMes, request?.position, request?.position,
|
||||
null, request?.requestId, request?.position, request?.type, request?.materialCode, request?.agvNo,
|
||||
"", requestText, "", 2, ex.Message);
|
||||
SaveMesLog("LGAGV_StatusUpdate", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string responseText = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return responseText;
|
||||
}
|
||||
|
||||
private static void WriteOp10PlcStatus(LGAGV_StatusUpdateRequest request)
|
||||
{
|
||||
if (request == null || string.IsNullOrWhiteSpace(request.position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string position = request.position.Trim();
|
||||
int tagTypeCodeID = 0;
|
||||
if (request.type == 1 && position.StartsWith("OP10-1-", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
tagTypeCodeID = 28;
|
||||
}
|
||||
else if (request.type == 1 && position.StartsWith("OP10-2-", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
tagTypeCodeID = 29;
|
||||
}
|
||||
else if (request.type == 2 && position.StartsWith("OP10-2-", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
tagTypeCodeID = 30;
|
||||
}
|
||||
|
||||
if (tagTypeCodeID == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool writeResult = MIS_BASE.WritePLC(tagTypeCodeID, "AC1101", true);
|
||||
string actionDesc = request.type == 1 ? "到达" : "离开";
|
||||
if (writeResult)
|
||||
{
|
||||
SaveMesLog("LGAGV_StatusUpdate", $"OP10 AGV{actionDesc}回写PLC成功:点位={position}, TagTypeCodeID={tagTypeCodeID}", MesLogType.INFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveMesLog("LGAGV_StatusUpdate", $"OP10 AGV{actionDesc}回写PLC失败:点位={position}, TagTypeCodeID={tagTypeCodeID}", MesLogType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理临工AGV任务结果回调。
|
||||
/// </summary>
|
||||
public static string ProcessTaskResult(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = LGAGV_Response.Success();
|
||||
string requestText = jobj?.ToString() ?? "";
|
||||
SaveLog_Interface_Request(url, 2, requestText, out int aid);
|
||||
|
||||
LGAGV_TaskResultRequest request = null;
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
|
||||
request = JsonConvert.DeserializeObject<LGAGV_TaskResultRequest>(requestText);
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("请求参数格式不正确");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.requestTaskId))
|
||||
{
|
||||
throw new Exception("任务ID(requestTaskId)不能为空");
|
||||
}
|
||||
|
||||
bool isSuccess = IsAgvSuccess(request.status);
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@requestTaskId", request.requestTaskId ?? ""),
|
||||
new SqlParameter("@status", request.status ?? ""),
|
||||
new SqlParameter("@agvNo", request.agvNo ?? ""),
|
||||
new SqlParameter("@message", request.message ?? ""),
|
||||
new SqlParameter("@materialCode", request.materialCode ?? "")
|
||||
};
|
||||
ExecuteResultProcedure("LG_AGV_库位Moby_任务结果", ref param);
|
||||
|
||||
SaveInterfaceRecord("TaskResult", DirectionAgvToMes, null, null,
|
||||
request.requestTaskId, null, null, null, request.materialCode, request.agvNo, request.status,
|
||||
requestText, "", isSuccess ? 1 : 2, request.message ?? "");
|
||||
|
||||
SaveMesLog("LGAGV_TaskResult", $"临工AGV任务结果:requestTaskId={request.requestTaskId}, status={request.status}, AGV={request.agvNo}, message={request.message}", MesLogType.INFO);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = LGAGV_Response.Fail(ex.Message);
|
||||
SaveInterfaceRecord("TaskResult", DirectionAgvToMes, null, null,
|
||||
request?.requestTaskId, null, null, null, request?.materialCode, request?.agvNo, request?.status,
|
||||
requestText, "", 2, ex.Message);
|
||||
SaveMesLog("LGAGV_TaskResult", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string responseText = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return responseText;
|
||||
}
|
||||
|
||||
public static void SaveInterfaceRecord(string interfaceName, string direction, string positionCode, string workStation,
|
||||
string requestTaskId, string requestId, string position, int? type, string materialCode, string agvNo, string status,
|
||||
string requestText, string responseText, int isSuccess, string errorMessage)
|
||||
{
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@库位号", positionCode ?? ""),
|
||||
new SqlParameter("@工位号", workStation ?? ""),
|
||||
new SqlParameter("@接口名称", interfaceName ?? ""),
|
||||
new SqlParameter("@接口方向", direction ?? ""),
|
||||
new SqlParameter("@requestTaskId", requestTaskId ?? ""),
|
||||
new SqlParameter("@requestId", requestId ?? ""),
|
||||
new SqlParameter("@position", position ?? ""),
|
||||
new SqlParameter("@type", type.HasValue ? (object)type.Value : DBNull.Value),
|
||||
new SqlParameter("@materialCode", materialCode ?? ""),
|
||||
new SqlParameter("@agvNo", agvNo ?? ""),
|
||||
new SqlParameter("@status", status ?? ""),
|
||||
new SqlParameter("@message", errorMessage ?? ""),
|
||||
new SqlParameter("@请求报文", requestText ?? ""),
|
||||
new SqlParameter("@响应报文", responseText ?? ""),
|
||||
new SqlParameter("@是否成功", isSuccess),
|
||||
new SqlParameter("@错误信息", errorMessage ?? "")
|
||||
};
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("LG_AGV_接口记录_增加", ref param, out string errMessage);
|
||||
if (!string.IsNullOrEmpty(errMessage))
|
||||
{
|
||||
SaveMesLog("LGAGV_InterfaceRecord", errMessage, MesLogType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsAgvSuccess(string codeOrStatus)
|
||||
{
|
||||
string value = (codeOrStatus ?? "").Trim().ToLower();
|
||||
return value == "0" || value == "200" || value == "true" || value == "success" || value == "成功";
|
||||
}
|
||||
|
||||
private static LGAGV_CallResult PostToAgv(string interfaceName, string path, object request,
|
||||
string requestTaskId, string requestId, string position, int? type, string materialCode, string agvNo)
|
||||
{
|
||||
string baseUrl = ConfigurationManager.AppSettings["LGAGV_BaseUrl"];
|
||||
if (string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
throw new Exception("未配置 LGAGV_BaseUrl");
|
||||
}
|
||||
|
||||
string interfaceUrl = baseUrl.TrimEnd('/') + path;
|
||||
string requestText = JsonConvert.SerializeObject(request);
|
||||
SaveLog_Interface_Request("LGAGV_" + interfaceName, 1, requestText, out int aid);
|
||||
|
||||
string responseText = Post.Post_Auto(interfaceUrl, requestText);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
|
||||
JObject response = ParseResponse(responseText);
|
||||
string codeText = response["code"]?.ToString() ?? response["result"]?.ToString() ?? "";
|
||||
string message = response["desc"]?.ToString() ?? response["message"]?.ToString() ?? response["msg"]?.ToString() ?? "";
|
||||
bool success = IsAgvSuccess(codeText);
|
||||
if (response["success"] != null)
|
||||
{
|
||||
if (bool.TryParse(response["success"].ToString(), out bool successValue))
|
||||
{
|
||||
success = successValue;
|
||||
}
|
||||
}
|
||||
|
||||
SaveInterfaceRecord(interfaceName, DirectionMesToAgv, position, position, requestTaskId, requestId, position,
|
||||
type, materialCode, agvNo, codeText, requestText, responseText, success ? 1 : 2, success ? "" : message);
|
||||
|
||||
if (success)
|
||||
{
|
||||
SaveMesLog("LGAGV_" + interfaceName, $"临工AGV接口调用成功:{interfaceName}, position={position}, requestTaskId={requestTaskId}", MesLogType.INFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveMesLog("LGAGV_" + interfaceName, $"临工AGV接口调用失败:{interfaceName}, code={codeText}, message={message}", MesLogType.ERROR);
|
||||
}
|
||||
|
||||
return new LGAGV_CallResult
|
||||
{
|
||||
Success = success,
|
||||
Code = ToInt(codeText, success ? 0 : 500),
|
||||
Message = message,
|
||||
InterfaceUrl = interfaceUrl,
|
||||
RequestText = requestText,
|
||||
ResponseText = responseText,
|
||||
Response = response
|
||||
};
|
||||
}
|
||||
|
||||
private static JObject ParseResponse(string responseText)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(responseText))
|
||||
{
|
||||
return new JObject
|
||||
{
|
||||
{ "code", 500 },
|
||||
{ "message", "AGV返回空响应" },
|
||||
{ "success", false }
|
||||
};
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return JObject.Parse(responseText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new JObject
|
||||
{
|
||||
{ "code", 500 },
|
||||
{ "message", "AGV返回非JSON响应:" + ex.Message },
|
||||
{ "raw", responseText },
|
||||
{ "success", false }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static int ToInt(string value, int defaultValue)
|
||||
{
|
||||
if (int.TryParse(value, out int intValue))
|
||||
{
|
||||
return intValue;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static void ExecuteResultProcedure(string procedureName, ref SqlParameter[] param)
|
||||
{
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure(procedureName, ref param, out DataTable dt, out string errMessage);
|
||||
if (!string.IsNullOrEmpty(errMessage))
|
||||
{
|
||||
throw new Exception(errMessage);
|
||||
}
|
||||
if (dt != null && dt.Rows.Count > 0 && dt.Columns.Contains("result") && dt.Rows[0]["result"].ToString() != "1")
|
||||
{
|
||||
string msg = dt.Columns.Contains("msg") ? dt.Rows[0]["msg"].ToString() : "存储过程执行失败";
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_Models.cs
Normal file
106
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_Models.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// 临工AGV两点任务请求。
|
||||
/// </summary>
|
||||
public class LGAGV_AddTaskRequest
|
||||
{
|
||||
public string requestTaskId { get; set; }
|
||||
public string startPosition { get; set; }
|
||||
public string endPosition { get; set; }
|
||||
public string materialCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV三点任务请求。
|
||||
/// </summary>
|
||||
public class LGAGV_AddTask2Request
|
||||
{
|
||||
public string requestTaskId { get; set; }
|
||||
public string startPosition { get; set; }
|
||||
public string midPosition { get; set; }
|
||||
public string endPosition { get; set; }
|
||||
public string materialCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV放行请求。
|
||||
/// </summary>
|
||||
public class LGAGV_AllowLeaveRequest
|
||||
{
|
||||
public string requestId { get; set; }
|
||||
public string position { get; set; }
|
||||
public string agvNo { get; set; }
|
||||
public int allowLeave { get; set; } = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV到达/离开回调。
|
||||
/// </summary>
|
||||
public class LGAGV_StatusUpdateRequest
|
||||
{
|
||||
public string requestId { get; set; }
|
||||
public string position { get; set; }
|
||||
public int type { get; set; }
|
||||
public string materialCode { get; set; }
|
||||
public string agvNo { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV任务执行结果回调。
|
||||
/// </summary>
|
||||
public class LGAGV_TaskResultRequest
|
||||
{
|
||||
public string requestTaskId { get; set; }
|
||||
public string status { get; set; }
|
||||
public string agvNo { get; set; }
|
||||
public string message { get; set; }
|
||||
public string materialCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回给临工AGV的通用响应。
|
||||
/// </summary>
|
||||
public class LGAGV_Response
|
||||
{
|
||||
public int code { get; set; }
|
||||
public string desc { get; set; }
|
||||
public bool success { get; set; }
|
||||
|
||||
public static LGAGV_Response Success(string desc = "成功")
|
||||
{
|
||||
return new LGAGV_Response
|
||||
{
|
||||
code = 0,
|
||||
desc = desc,
|
||||
success = true
|
||||
};
|
||||
}
|
||||
|
||||
public static LGAGV_Response Fail(string desc)
|
||||
{
|
||||
return new LGAGV_Response
|
||||
{
|
||||
code = 1,
|
||||
desc = desc,
|
||||
success = false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MES调用临工AGV接口后的内部结果。
|
||||
/// </summary>
|
||||
public class LGAGV_CallResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string InterfaceUrl { get; set; }
|
||||
public string RequestText { get; set; }
|
||||
public string ResponseText { get; set; }
|
||||
public JObject Response { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,836 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using MesServerWork;
|
||||
using MisDataSaveDate.Helper;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static MisDataSaveDate.Helper.ApiLogHelper;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// TCS插拔任务业务处理。PLC自动任务与Web人工任务共用此入口。
|
||||
/// </summary>
|
||||
public class TCSAGV_BusinessLogic
|
||||
{
|
||||
private const string TaskTypeCombined = "nav_action_program";
|
||||
private const string TaskTypeProgram = "program";
|
||||
|
||||
public static TCSAGV_CallResult DispatchStationTask(string stationCode, string actionType,
|
||||
string portCombination, string source, string operatorCode, string parentExternalCode, bool notifyPlc)
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
TCSAGV_PointConfig point = ReadPointConfig(stationCode);
|
||||
string normalizedAction = NormalizeAction(actionType);
|
||||
string productModel = "";
|
||||
string combination;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(portCombination))
|
||||
{
|
||||
productModel = ReadCurrentProductModel(point.StationCode);
|
||||
combination = ReadModelActionCombination(point.LineCode, productModel, normalizedAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
combination = NormalizePortCombination(portCombination);
|
||||
}
|
||||
|
||||
JArray parameters = new JArray
|
||||
{
|
||||
new JObject { { "workStation", point.WorkStation } }
|
||||
};
|
||||
if (combination.Contains("XSD"))
|
||||
{
|
||||
parameters.Add(new JObject
|
||||
{
|
||||
{ "programName", normalizedAction == "插" ? point.InsertXsdProgram : point.PullXsdProgram }
|
||||
});
|
||||
}
|
||||
if (combination.Contains("XSE"))
|
||||
{
|
||||
parameters.Add(new JObject
|
||||
{
|
||||
{ "programName", normalizedAction == "插" ? point.InsertXseProgram : point.PullXseProgram }
|
||||
});
|
||||
}
|
||||
|
||||
string externalCode = CreateExternalCode(normalizedAction == "插" ? "PLUG" : "PULL");
|
||||
return CreateAndSendTask(config, point, externalCode, parentExternalCode, normalizedAction, "",
|
||||
productModel, combination, TaskTypeCombined, parameters.ToString(Formatting.None), source,
|
||||
operatorCode, notifyPlc);
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult DispatchSingleStep(string stationCode, string programName,
|
||||
string operatorCode, string parentExternalCode)
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
TCSAGV_PointConfig point = ReadPointConfig(stationCode);
|
||||
EnsureRobotAtPoint(config, point);
|
||||
string normalizedProgram = (programName ?? "").Trim();
|
||||
if (!IsConfiguredProgram(point, normalizedProgram))
|
||||
{
|
||||
throw new Exception("所选programName不属于该工位配置");
|
||||
}
|
||||
|
||||
string action = normalizedProgram.Contains("拔") ? "拔-单步" : "插-单步";
|
||||
JArray parameters = new JArray
|
||||
{
|
||||
new JObject { { "programName", normalizedProgram } }
|
||||
};
|
||||
return CreateAndSendTask(config, point, CreateExternalCode("STEP"), parentExternalCode,
|
||||
action, normalizedProgram, "", normalizedProgram.Contains("XSD") ? "XSD" : "XSE",
|
||||
TaskTypeProgram, parameters.ToString(Formatting.None),
|
||||
"MANUAL", operatorCode, false);
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult RetryTask(string externalCode, string operatorCode)
|
||||
{
|
||||
DataRow original = ReadTask(externalCode);
|
||||
if (!IsFailureStatus(ToInt(original["任务状态"], -1)))
|
||||
{
|
||||
throw new Exception("仅任务错误状态允许整单重发");
|
||||
}
|
||||
if (ToBool(original["处理状态"]))
|
||||
{
|
||||
throw new Exception("失败任务已处理,不能再次重发");
|
||||
}
|
||||
if (!ToBool(original["已复位"]))
|
||||
{
|
||||
throw new Exception("请先复位移动机器人再重发任务");
|
||||
}
|
||||
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
TCSAGV_PointConfig point = ReadPointConfig(Convert.ToString(original["MES工位号"]));
|
||||
string action = Convert.ToString(original["任务动作"]);
|
||||
string programName = Convert.ToString(original["ProgramName"]);
|
||||
string productModel = Convert.ToString(original["产品型号"]);
|
||||
string combination = Convert.ToString(original["动作组合"]);
|
||||
string taskType = Convert.ToString(original["任务类型"]);
|
||||
string param = Convert.ToString(original["参数"]);
|
||||
|
||||
return CreateAndSendTask(config, point, CreateExternalCode("RETRY"), externalCode,
|
||||
action, programName, productModel, combination, taskType, param, "RETRY", operatorCode, false);
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult CancelTask(string externalCode, string operatorCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(externalCode))
|
||||
{
|
||||
throw new Exception("外部任务编号不能为空");
|
||||
}
|
||||
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
TCSAGV_CallResult result = GetFromTcs(config, "cancelExternalBusinessTask",
|
||||
"/api/cancelExternalBusinessTask", new Dictionary<string, string> { { "externalCode", externalCode } });
|
||||
if (result.Success)
|
||||
{
|
||||
SetLocalTaskStatus(externalCode, 3, "已取消", "");
|
||||
}
|
||||
SaveOperation(externalCode, "", "取消任务", operatorCode, result.RequestText,
|
||||
result.ResponseText, result.Success, result.Message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult StopPendingTasks(string externalCode, string operatorCode)
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
TCSAGV_CallResult result = GetFromTcs(config, "stopExternalBusinessTask",
|
||||
"/api/stopExternalBusinessTask", null);
|
||||
if (result.Success && !string.IsNullOrWhiteSpace(externalCode))
|
||||
{
|
||||
DataRow task = ReadTask(externalCode);
|
||||
if (ToInt(task["任务状态"], -1) == 0)
|
||||
{
|
||||
SetLocalTaskStatus(externalCode, 3, "已停止", "停止全部未开始任务");
|
||||
}
|
||||
}
|
||||
SaveOperation(externalCode, "", "停止未开始任务", operatorCode, result.RequestText,
|
||||
result.ResponseText, result.Success, result.Message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult ResetRobot(string externalCode, string ip, string operatorCode)
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
string robotIp = string.IsNullOrWhiteSpace(ip) ? config.McrIp : ip.Trim();
|
||||
if (string.IsNullOrWhiteSpace(robotIp))
|
||||
{
|
||||
throw new Exception("未配置AGV IP");
|
||||
}
|
||||
|
||||
TCSAGV_CallResult result = GetFromTcs(config, "reset", "/api/reset",
|
||||
new Dictionary<string, string> { { "ip", robotIp } });
|
||||
if (result.Success && !string.IsNullOrWhiteSpace(externalCode))
|
||||
{
|
||||
try
|
||||
{
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode.Trim())
|
||||
};
|
||||
EnsureBusinessSuccess(ExecuteProcedure("XD_TCS_AGV_任务_复位标记", parameters));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SaveOperation(externalCode, "", "移动机器人复位", operatorCode, result.RequestText,
|
||||
result.ResponseText, false, "TCS复位成功,但MES复位标记失败:" + ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
SaveOperation(externalCode, "", "移动机器人复位", operatorCode, result.RequestText,
|
||||
result.ResponseText, result.Success, result.Message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult StopNow(string externalCode, string ip, string operatorCode)
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
string robotIp = string.IsNullOrWhiteSpace(ip) ? config.McrIp : ip.Trim();
|
||||
if (string.IsNullOrWhiteSpace(robotIp))
|
||||
{
|
||||
throw new Exception("未配置AGV IP");
|
||||
}
|
||||
|
||||
TCSAGV_CallResult result = GetFromTcs(config, "stopNow", "/api/stopNow",
|
||||
new Dictionary<string, string> { { "ip", robotIp } });
|
||||
if (result.Success && !string.IsNullOrWhiteSpace(externalCode))
|
||||
{
|
||||
SetLocalTaskStatus(externalCode, 4, "任务错误", "人工紧急停止");
|
||||
}
|
||||
SaveOperation(externalCode, "", "紧急停止", operatorCode, result.RequestText,
|
||||
result.ResponseText, result.Success, result.Message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult SyncTaskStatus(string externalCode, string operatorCode)
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
TCSAGV_CallResult result = GetFromTcs(config, "getExternalBusinessTaskStatus",
|
||||
"/api/getExternalBusinessTaskStatus", new Dictionary<string, string> { { "externalCode", externalCode } });
|
||||
if (result.Success)
|
||||
{
|
||||
JObject task = FirstResultObject(result.Response);
|
||||
if (task != null && task["status"] != null)
|
||||
{
|
||||
int status = ToInt(task["status"], -1);
|
||||
if (status >= 0 && status <= 5)
|
||||
{
|
||||
UpdateTaskStatus(externalCode, status,
|
||||
Convert.ToString(task["ip"] ?? ""), Convert.ToString(task["type"] ?? ""),
|
||||
Convert.ToString(task["beginTime"] ?? ""), Convert.ToString(task["endTime"] ?? ""),
|
||||
Convert.ToString(task["remark"] ?? ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
SaveOperation(externalCode, "", "同步任务状态", operatorCode, result.RequestText,
|
||||
result.ResponseText, result.Success, result.Message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TCSAGV_CallResult QueryRobotInfo()
|
||||
{
|
||||
TCSAGV_Config config = ReadConfig(true);
|
||||
return QueryRobotInfo(config);
|
||||
}
|
||||
|
||||
private static TCSAGV_CallResult QueryRobotInfo(TCSAGV_Config config)
|
||||
{
|
||||
Dictionary<string, string> query = new Dictionary<string, string>
|
||||
{
|
||||
{ "mcrGroup", config.McrGroup }
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(config.McrIp))
|
||||
{
|
||||
query.Add("mcrIp", config.McrIp);
|
||||
}
|
||||
return GetFromTcs(config, "getMcrInfo", "/api/getMcrInfo", query);
|
||||
}
|
||||
|
||||
public static void HandleFailure(string externalCode, string operatorCode, string remark, bool notifyPlc)
|
||||
{
|
||||
DataRow task = ReadTask(externalCode);
|
||||
if (!IsFailureStatus(ToInt(task["任务状态"], -1)))
|
||||
{
|
||||
throw new Exception("仅任务错误状态允许人工处理");
|
||||
}
|
||||
if (!ToBool(task["已复位"]))
|
||||
{
|
||||
throw new Exception("请先复位移动机器人再完成人工处理");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(remark))
|
||||
{
|
||||
throw new Exception("处理说明不能为空");
|
||||
}
|
||||
|
||||
if (notifyPlc)
|
||||
{
|
||||
WritePlcCompletion(task);
|
||||
}
|
||||
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode ?? ""),
|
||||
new SqlParameter("@处理人", operatorCode ?? ""),
|
||||
new SqlParameter("@处理说明", remark ?? "")
|
||||
};
|
||||
EnsureBusinessSuccess(ExecuteProcedure("XD_TCS_AGV_任务_人工处理", parameters));
|
||||
SaveOperation(externalCode, Convert.ToString(task["MES工位号"]), "失败任务人工处理",
|
||||
operatorCode, "", "", true, remark);
|
||||
}
|
||||
|
||||
public static string ProcessTaskStatus(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
string requestText = jobj == null ? "" : jobj.ToString(Formatting.None);
|
||||
SaveLog_Interface_Request(url, 2, requestText, out int aid);
|
||||
TCSAGV_ApiResponse response;
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
TCSAGV_TaskStatusPushRequest request = jobj.ToObject<TCSAGV_TaskStatusPushRequest>();
|
||||
if (request == null || string.IsNullOrWhiteSpace(request.externalCode))
|
||||
{
|
||||
throw new Exception("外部任务编号不能为空");
|
||||
}
|
||||
int status = ToInt(request.status, -1);
|
||||
if (status < 0 || status > 5)
|
||||
{
|
||||
throw new Exception("任务状态必须为0至5");
|
||||
}
|
||||
|
||||
UpdateTaskStatus(request.externalCode, status, request.ip, request.type,
|
||||
request.beginTime, request.endTime, request.remark);
|
||||
response = TCSAGV_ApiResponse.Ok("接收成功", "接收成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
response = TCSAGV_ApiResponse.Fail(ex.Message);
|
||||
SaveMesLog("TCS任务状态推送", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string responseText = JsonConvert.SerializeObject(response);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return responseText;
|
||||
}
|
||||
|
||||
public static string ProcessPositionPush(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
string requestText = jobj == null ? "" : jobj.ToString(Formatting.None);
|
||||
SaveLog_Interface_Request(url, 2, requestText, out int aid);
|
||||
TCSAGV_ApiResponse response;
|
||||
try
|
||||
{
|
||||
if (jobj == null)
|
||||
{
|
||||
throw new Exception("请求参数不能为空");
|
||||
}
|
||||
TCSAGV_PositionPushRequest request = jobj.ToObject<TCSAGV_PositionPushRequest>();
|
||||
if (request == null || string.IsNullOrWhiteSpace(request.ip))
|
||||
{
|
||||
throw new Exception("机器人IP不能为空");
|
||||
}
|
||||
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@机器人IP", request.ip ?? ""),
|
||||
new SqlParameter("@当前站点", request.currentPos ?? ""),
|
||||
new SqlParameter("@目标站点", request.objectivePos ?? ""),
|
||||
new SqlParameter("@原始报文", requestText)
|
||||
};
|
||||
ExecuteProcedure("XD_TCS_AGV_位置_更新", parameters);
|
||||
response = TCSAGV_ApiResponse.Ok("接收成功", "接收成功");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
response = TCSAGV_ApiResponse.Fail(ex.Message);
|
||||
SaveMesLog("TCS位置推送", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string responseText = JsonConvert.SerializeObject(response);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return responseText;
|
||||
}
|
||||
|
||||
private static TCSAGV_CallResult CreateAndSendTask(TCSAGV_Config config, TCSAGV_PointConfig point,
|
||||
string externalCode, string parentExternalCode, string action, string programName,
|
||||
string productModel, string combination, string taskType, string param, string source,
|
||||
string operatorCode, bool notifyPlc)
|
||||
{
|
||||
TCSAGV_TaskRequest request = new TCSAGV_TaskRequest
|
||||
{
|
||||
externalCode = externalCode,
|
||||
type = taskType,
|
||||
priority = config.DefaultPriority,
|
||||
param = param,
|
||||
mcrgroup = config.McrGroup,
|
||||
mcrip = config.McrIp,
|
||||
operatoruserid = config.OperatorUserId
|
||||
};
|
||||
|
||||
SqlParameter[] createParameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode),
|
||||
new SqlParameter("@原任务编号", parentExternalCode ?? ""),
|
||||
new SqlParameter("@MES工位号", point.StationCode),
|
||||
new SqlParameter("@任务动作", action),
|
||||
new SqlParameter("@产品型号", productModel ?? ""),
|
||||
new SqlParameter("@动作组合", combination ?? ""),
|
||||
new SqlParameter("@ProgramName", programName ?? ""),
|
||||
new SqlParameter("@任务类型", taskType),
|
||||
new SqlParameter("@参数", param),
|
||||
new SqlParameter("@优先级", config.DefaultPriority),
|
||||
new SqlParameter("@机器人组", config.McrGroup ?? ""),
|
||||
new SqlParameter("@机器人IP", config.McrIp ?? ""),
|
||||
new SqlParameter("@来源", source ?? ""),
|
||||
new SqlParameter("@操作人", operatorCode ?? ""),
|
||||
new SqlParameter("@是否通知PLC", notifyPlc)
|
||||
};
|
||||
EnsureBusinessSuccess(ExecuteProcedure("XD_TCS_AGV_任务_创建", createParameters));
|
||||
|
||||
TCSAGV_CallResult result;
|
||||
try
|
||||
{
|
||||
result = PostToTcs(config, "createExternalBusinessTask", "/api/createExternalBusinessTask", request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UpdateDispatchResult(externalCode, JsonConvert.SerializeObject(request), "", false, ex.Message);
|
||||
SaveOperation(externalCode, point.StationCode, "下发" + action + "任务", operatorCode,
|
||||
JsonConvert.SerializeObject(request), "", false, ex.Message);
|
||||
throw;
|
||||
}
|
||||
|
||||
UpdateDispatchResult(externalCode, result.RequestText, result.ResponseText, result.Success,
|
||||
result.Success ? "" : result.Message);
|
||||
SaveOperation(externalCode, point.StationCode, "下发" + action + "任务", operatorCode,
|
||||
result.RequestText, result.ResponseText, result.Success, result.Message);
|
||||
result.ExternalCode = externalCode;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void UpdateTaskStatus(string externalCode, int status, string ip, string type,
|
||||
string beginTime, string endTime, string remark)
|
||||
{
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode ?? ""),
|
||||
new SqlParameter("@任务状态", status),
|
||||
new SqlParameter("@机器人IP", ip ?? ""),
|
||||
new SqlParameter("@任务类型", type ?? ""),
|
||||
new SqlParameter("@开始时间", beginTime ?? ""),
|
||||
new SqlParameter("@结束时间", endTime ?? ""),
|
||||
new SqlParameter("@备注", remark ?? "")
|
||||
};
|
||||
DataTable result = ExecuteProcedure("XD_TCS_AGV_任务_状态更新", parameters);
|
||||
EnsureBusinessSuccess(result);
|
||||
|
||||
if (status == 2 && result.Rows.Count > 0 && ToBool(result.Rows[0]["是否通知PLC"])
|
||||
&& !ToBool(result.Rows[0]["PLC已通知"]))
|
||||
{
|
||||
DataRow task = ReadTask(externalCode);
|
||||
WritePlcCompletion(task);
|
||||
SqlParameter[] notified = { new SqlParameter("@外部任务编号", externalCode) };
|
||||
ExecuteProcedure("XD_TCS_AGV_任务_PLC通知完成", notified);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsFailureStatus(int status)
|
||||
{
|
||||
return status == 4 || status == 5;
|
||||
}
|
||||
|
||||
private static void WritePlcCompletion(DataRow task)
|
||||
{
|
||||
string stationCode = Convert.ToString(task["MES工位号"]);
|
||||
string action = Convert.ToString(task["任务动作"]);
|
||||
int tagCode = action.StartsWith("插", StringComparison.Ordinal) ? 400
|
||||
: action.StartsWith("拔", StringComparison.Ordinal) ? 401 : 0;
|
||||
if (tagCode == 0)
|
||||
{
|
||||
throw new Exception("任务动作无法确定PLC完成码");
|
||||
}
|
||||
if (!MIS_BASE.WritePLC(tagCode, stationCode, true))
|
||||
{
|
||||
throw new Exception("任务完成但PLC完成信号写入失败");
|
||||
}
|
||||
SaveMesLog(stationCode, "TCS任务完成,已写入PLC功能码" + tagCode, MesLogType.INFO);
|
||||
}
|
||||
|
||||
private static TCSAGV_Config ReadConfig(bool requireEnabled)
|
||||
{
|
||||
DataTable table = ExecuteProcedure("XD_TCS_AGV_配置_获取", new SqlParameter[0]);
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("未配置TCS参数");
|
||||
}
|
||||
DataRow row = table.Rows[0];
|
||||
TCSAGV_Config config = new TCSAGV_Config
|
||||
{
|
||||
BaseUrl = Convert.ToString(row["TCS_BaseUrl"]),
|
||||
Enabled = Convert.ToString(row["TCS_Enabled"]) == "1",
|
||||
McrGroup = Convert.ToString(row["McrGroup"]),
|
||||
McrIp = Convert.ToString(row["McrIp"]),
|
||||
OperatorUserId = Convert.ToString(row["TCS_OperatorUserId"]),
|
||||
DefaultPriority = ToInt(row["DefaultPriority"], 1),
|
||||
HttpTimeoutSeconds = ToInt(row["HttpTimeoutSeconds"], 15)
|
||||
};
|
||||
if (string.IsNullOrWhiteSpace(config.BaseUrl))
|
||||
{
|
||||
throw new Exception("未配置TCS服务地址");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(config.OperatorUserId))
|
||||
{
|
||||
throw new Exception("未配置TCS任务状态推送标识");
|
||||
}
|
||||
if (requireEnabled && !config.Enabled)
|
||||
{
|
||||
throw new Exception("TCS真实下发开关未启用,请先确认现场地址和AGV IP");
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private static TCSAGV_PointConfig ReadPointConfig(string stationCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(stationCode))
|
||||
{
|
||||
throw new Exception("MES工位号不能为空");
|
||||
}
|
||||
SqlParameter[] parameters = { new SqlParameter("@MES工位号", stationCode.Trim()) };
|
||||
DataTable table = ExecuteProcedure("XD_TCS_AGV_点位配置_查询", parameters);
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("MES工位未配置TCS站点和programName");
|
||||
}
|
||||
DataRow row = table.Rows[0];
|
||||
return new TCSAGV_PointConfig
|
||||
{
|
||||
LineCode = Convert.ToString(row["产线代码"]),
|
||||
StationCode = Convert.ToString(row["MES工位号"]),
|
||||
PositionName = Convert.ToString(row["现场位置"]),
|
||||
WorkStation = Convert.ToString(row["WorkStation"]),
|
||||
InsertXsdProgram = Convert.ToString(row["插XSDProgramName"]),
|
||||
InsertXseProgram = Convert.ToString(row["插XSEProgramName"]),
|
||||
PullXsdProgram = Convert.ToString(row["拔XSDProgramName"]),
|
||||
PullXseProgram = Convert.ToString(row["拔XSEProgramName"])
|
||||
};
|
||||
}
|
||||
|
||||
private static string ReadCurrentProductModel(string stationCode)
|
||||
{
|
||||
SqlParameter[] parameters = { new SqlParameter("@MES工位号", stationCode) };
|
||||
DataTable table = ExecuteProcedure("XD_TCS_AGV_库位产品_查询", parameters);
|
||||
string productModel = table.Rows.Count == 0 ? "" : Convert.ToString(table.Rows[0]["产品型号"]);
|
||||
if (string.IsNullOrWhiteSpace(productModel))
|
||||
{
|
||||
throw new Exception("工位" + stationCode + "未获取到当前产品型号");
|
||||
}
|
||||
return productModel.Trim();
|
||||
}
|
||||
|
||||
private static string ReadModelActionCombination(string lineCode, string productModel, string action)
|
||||
{
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@产线代码", lineCode),
|
||||
new SqlParameter("@产品型号", productModel),
|
||||
new SqlParameter("@任务动作", action)
|
||||
};
|
||||
DataTable table = ExecuteProcedure("XD_TCS_AGV_型号动作映射_查询", parameters);
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("产品型号" + productModel + "未配置" + action + "动作组合");
|
||||
}
|
||||
return Convert.ToString(table.Rows[0]["动作组合"]);
|
||||
}
|
||||
|
||||
private static DataRow ReadTask(string externalCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(externalCode))
|
||||
{
|
||||
throw new Exception("外部任务编号不能为空");
|
||||
}
|
||||
SqlParameter[] parameters = { new SqlParameter("@外部任务编号", externalCode.Trim()) };
|
||||
DataTable table = ExecuteProcedure("XD_TCS_AGV_任务_获取", parameters);
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("外部任务不存在");
|
||||
}
|
||||
return table.Rows[0];
|
||||
}
|
||||
|
||||
private static void EnsureRobotAtPoint(TCSAGV_Config config, TCSAGV_PointConfig point)
|
||||
{
|
||||
TCSAGV_CallResult result = QueryRobotInfo(config);
|
||||
if (!result.Success)
|
||||
{
|
||||
throw new Exception("查询AGV实时位置失败:" + result.Message);
|
||||
}
|
||||
JObject robot = FirstResultObject(result.Response);
|
||||
if (robot == null)
|
||||
{
|
||||
throw new Exception("未查询到AGV状态,不能执行单步任务");
|
||||
}
|
||||
if (ToInt(robot["status"], -1) == 4)
|
||||
{
|
||||
throw new Exception("AGV当前未连接,不能执行单步任务");
|
||||
}
|
||||
string currentPosition = Convert.ToString(robot["currentPos"]);
|
||||
if (string.IsNullOrWhiteSpace(currentPosition))
|
||||
{
|
||||
throw new Exception("未获取到AGV当前位置,不能执行单步任务");
|
||||
}
|
||||
if (!string.Equals(currentPosition, point.WorkStation, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new Exception("AGV当前位置" + currentPosition + "与所选站点" + point.WorkStation + "不一致");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateDispatchResult(string externalCode, string requestText, string responseText,
|
||||
bool success, string errorMessage)
|
||||
{
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode ?? ""),
|
||||
new SqlParameter("@请求报文", requestText ?? ""),
|
||||
new SqlParameter("@响应报文", responseText ?? ""),
|
||||
new SqlParameter("@是否成功", success),
|
||||
new SqlParameter("@错误信息", errorMessage ?? "")
|
||||
};
|
||||
ExecuteProcedure("XD_TCS_AGV_任务_下发结果更新", parameters);
|
||||
}
|
||||
|
||||
private static void SetLocalTaskStatus(string externalCode, int status, string statusText, string errorMessage)
|
||||
{
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode ?? ""),
|
||||
new SqlParameter("@任务状态", status),
|
||||
new SqlParameter("@状态说明", statusText ?? ""),
|
||||
new SqlParameter("@错误信息", errorMessage ?? "")
|
||||
};
|
||||
ExecuteProcedure("XD_TCS_AGV_任务_本地状态设置", parameters);
|
||||
}
|
||||
|
||||
private static void SaveOperation(string externalCode, string stationCode, string operationType,
|
||||
string operatorCode, string requestText, string responseText, bool success, string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
SqlParameter[] parameters =
|
||||
{
|
||||
new SqlParameter("@外部任务编号", externalCode ?? ""),
|
||||
new SqlParameter("@MES工位号", stationCode ?? ""),
|
||||
new SqlParameter("@操作类型", operationType ?? ""),
|
||||
new SqlParameter("@操作人", operatorCode ?? ""),
|
||||
new SqlParameter("@请求报文", requestText ?? ""),
|
||||
new SqlParameter("@响应报文", responseText ?? ""),
|
||||
new SqlParameter("@是否成功", success),
|
||||
new SqlParameter("@操作结果", message ?? "")
|
||||
};
|
||||
ExecuteProcedure("XD_TCS_AGV_操作记录_增加", parameters);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SaveMesLog("TCS操作记录", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private static TCSAGV_CallResult PostToTcs(TCSAGV_Config config, string interfaceName,
|
||||
string path, object request)
|
||||
{
|
||||
string url = config.BaseUrl.TrimEnd('/') + path;
|
||||
string requestText = JsonConvert.SerializeObject(request);
|
||||
SaveLog_Interface_Request("TCS_" + interfaceName, 1, requestText, out int aid);
|
||||
string responseText;
|
||||
using (HttpClient client = CreateHttpClient(config))
|
||||
using (StringContent content = new StringContent(requestText, Encoding.UTF8, "application/json"))
|
||||
{
|
||||
HttpResponseMessage response = client.PostAsync(url, content).GetAwaiter().GetResult();
|
||||
responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
if (string.IsNullOrWhiteSpace(responseText) && !response.IsSuccessStatusCode)
|
||||
{
|
||||
responseText = "HTTP " + (int)response.StatusCode;
|
||||
}
|
||||
}
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return ParseCallResult(requestText, responseText);
|
||||
}
|
||||
|
||||
private static TCSAGV_CallResult GetFromTcs(TCSAGV_Config config, string interfaceName,
|
||||
string path, IDictionary<string, string> query)
|
||||
{
|
||||
StringBuilder url = new StringBuilder(config.BaseUrl.TrimEnd('/') + path);
|
||||
JObject request = new JObject();
|
||||
if (query != null && query.Count > 0)
|
||||
{
|
||||
url.Append('?');
|
||||
bool first = true;
|
||||
foreach (KeyValuePair<string, string> item in query)
|
||||
{
|
||||
if (!first) url.Append('&');
|
||||
first = false;
|
||||
url.Append(HttpUtility.UrlEncode(item.Key));
|
||||
url.Append('=');
|
||||
url.Append(HttpUtility.UrlEncode(item.Value ?? ""));
|
||||
request[item.Key] = item.Value ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
string requestText = request.ToString(Formatting.None);
|
||||
bool skipInterfaceLog = string.Equals(interfaceName, "getMcrInfo",
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
int aid = 0;
|
||||
if (!skipInterfaceLog)
|
||||
{
|
||||
SaveLog_Interface_Request("TCS_" + interfaceName, 1, requestText, out aid);
|
||||
}
|
||||
string responseText;
|
||||
using (HttpClient client = CreateHttpClient(config))
|
||||
{
|
||||
HttpResponseMessage response = client.GetAsync(url.ToString()).GetAwaiter().GetResult();
|
||||
responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
if (string.IsNullOrWhiteSpace(responseText) && !response.IsSuccessStatusCode)
|
||||
{
|
||||
responseText = "HTTP " + (int)response.StatusCode;
|
||||
}
|
||||
}
|
||||
if (!skipInterfaceLog)
|
||||
{
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
}
|
||||
return ParseCallResult(requestText, responseText);
|
||||
}
|
||||
|
||||
private static HttpClient CreateHttpClient(TCSAGV_Config config)
|
||||
{
|
||||
return new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(config.HttpTimeoutSeconds > 0 ? config.HttpTimeoutSeconds : 15)
|
||||
};
|
||||
}
|
||||
|
||||
private static TCSAGV_CallResult ParseCallResult(string requestText, string responseText)
|
||||
{
|
||||
JObject response;
|
||||
try
|
||||
{
|
||||
response = JObject.Parse(responseText ?? "");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new TCSAGV_CallResult
|
||||
{
|
||||
Success = false,
|
||||
Code = 500,
|
||||
Message = "TCS返回非JSON响应:" + ex.Message,
|
||||
RequestText = requestText,
|
||||
ResponseText = responseText,
|
||||
Response = null
|
||||
};
|
||||
}
|
||||
|
||||
bool successFlag = false;
|
||||
bool hasSuccessFlag = response["success"] != null;
|
||||
if (hasSuccessFlag)
|
||||
{
|
||||
bool.TryParse(Convert.ToString(response["success"]), out successFlag);
|
||||
}
|
||||
int code = ToInt(response["code"], successFlag ? 200 : 500);
|
||||
bool success = hasSuccessFlag ? successFlag && code == 200 : code == 200;
|
||||
string message = Convert.ToString(response["message"] ?? response["msg"] ?? response["result"] ?? "");
|
||||
return new TCSAGV_CallResult
|
||||
{
|
||||
Success = success,
|
||||
Code = code,
|
||||
Message = message,
|
||||
RequestText = requestText,
|
||||
ResponseText = responseText,
|
||||
Response = response
|
||||
};
|
||||
}
|
||||
|
||||
private static JObject FirstResultObject(JObject response)
|
||||
{
|
||||
if (response == null || response["result"] == null) return null;
|
||||
JToken result = response["result"];
|
||||
if (result.Type == JTokenType.Array)
|
||||
{
|
||||
JArray array = (JArray)result;
|
||||
return array.Count > 0 ? array[0] as JObject : null;
|
||||
}
|
||||
return result as JObject;
|
||||
}
|
||||
|
||||
private static DataTable ExecuteProcedure(string procedureName, SqlParameter[] parameters)
|
||||
{
|
||||
SqlParameter[] procedureParameters = parameters ?? new SqlParameter[0];
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure(procedureName, ref procedureParameters,
|
||||
out DataTable table, out string errorMessage);
|
||||
if (!string.IsNullOrWhiteSpace(errorMessage))
|
||||
{
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
return table ?? new DataTable();
|
||||
}
|
||||
|
||||
private static void EnsureBusinessSuccess(DataTable table)
|
||||
{
|
||||
if (table == null || table.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("数据库未返回业务结果");
|
||||
}
|
||||
if (ToInt(table.Rows[0]["result"], 0) != 1)
|
||||
{
|
||||
string message = table.Columns.Contains("msg") ? Convert.ToString(table.Rows[0]["msg"]) : "业务操作失败";
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
private static string NormalizeAction(string actionType)
|
||||
{
|
||||
string value = (actionType ?? "").Trim();
|
||||
if (value == "插" || value.Equals("plug", StringComparison.OrdinalIgnoreCase)) return "插";
|
||||
if (value == "拔" || value.Equals("pull", StringComparison.OrdinalIgnoreCase)) return "拔";
|
||||
throw new Exception("任务动作只支持插或拔");
|
||||
}
|
||||
|
||||
private static string NormalizePortCombination(string portCombination)
|
||||
{
|
||||
string value = (portCombination ?? "").Trim().ToUpperInvariant();
|
||||
if (value == "XSD" || value == "XSE" || value == "XSD+XSE") return value;
|
||||
throw new Exception("动作组合只支持XSD、XSE或XSD+XSE");
|
||||
}
|
||||
|
||||
private static bool IsConfiguredProgram(TCSAGV_PointConfig point, string programName)
|
||||
{
|
||||
return programName == point.InsertXsdProgram || programName == point.InsertXseProgram
|
||||
|| programName == point.PullXsdProgram || programName == point.PullXseProgram;
|
||||
}
|
||||
|
||||
private static string CreateExternalCode(string prefix)
|
||||
{
|
||||
return "XD_" + prefix + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_"
|
||||
+ Guid.NewGuid().ToString("N").Substring(0, 6).ToUpperInvariant();
|
||||
}
|
||||
|
||||
private static int ToInt(object value, int defaultValue)
|
||||
{
|
||||
int result;
|
||||
return int.TryParse(Convert.ToString(value), out result) ? result : defaultValue;
|
||||
}
|
||||
|
||||
private static bool ToBool(object value)
|
||||
{
|
||||
string text = Convert.ToString(value);
|
||||
return text == "1" || text.Equals("true", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
133
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_Models.cs
Normal file
133
Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_Models.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
public class TCSAGV_TaskRequest
|
||||
{
|
||||
public string externalCode { get; set; }
|
||||
public string type { get; set; }
|
||||
public int priority { get; set; }
|
||||
public string param { get; set; }
|
||||
public string mcrgroup { get; set; }
|
||||
public string mcrip { get; set; }
|
||||
public string operatoruserid { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_TaskStatusPushRequest
|
||||
{
|
||||
public string externalCode { get; set; }
|
||||
public string status { get; set; }
|
||||
public string ip { get; set; }
|
||||
public string type { get; set; }
|
||||
public string beginTime { get; set; }
|
||||
public string endTime { get; set; }
|
||||
public string remark { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_PositionPushRequest
|
||||
{
|
||||
public string ip { get; set; }
|
||||
public string currentPos { get; set; }
|
||||
public string objectivePos { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_StationDispatchRequest
|
||||
{
|
||||
public string stationCode { get; set; }
|
||||
public string actionType { get; set; }
|
||||
public string portCombination { get; set; }
|
||||
public string operatorCode { get; set; }
|
||||
public string parentExternalCode { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_StepDispatchRequest
|
||||
{
|
||||
public string stationCode { get; set; }
|
||||
public string programName { get; set; }
|
||||
public string operatorCode { get; set; }
|
||||
public string parentExternalCode { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_TaskOperationRequest
|
||||
{
|
||||
public string externalCode { get; set; }
|
||||
public string operatorCode { get; set; }
|
||||
public string remark { get; set; }
|
||||
public bool notifyPlc { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_RobotOperationRequest
|
||||
{
|
||||
public string externalCode { get; set; }
|
||||
public string ip { get; set; }
|
||||
public string operatorCode { get; set; }
|
||||
public string remark { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_Config
|
||||
{
|
||||
public string BaseUrl { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string McrGroup { get; set; }
|
||||
public string McrIp { get; set; }
|
||||
public string OperatorUserId { get; set; }
|
||||
public int DefaultPriority { get; set; }
|
||||
public int HttpTimeoutSeconds { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_PointConfig
|
||||
{
|
||||
public string LineCode { get; set; }
|
||||
public string StationCode { get; set; }
|
||||
public string PositionName { get; set; }
|
||||
public string WorkStation { get; set; }
|
||||
public string InsertXsdProgram { get; set; }
|
||||
public string InsertXseProgram { get; set; }
|
||||
public string PullXsdProgram { get; set; }
|
||||
public string PullXseProgram { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_CallResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string ExternalCode { get; set; }
|
||||
public string RequestText { get; set; }
|
||||
public string ResponseText { get; set; }
|
||||
public JObject Response { get; set; }
|
||||
}
|
||||
|
||||
public class TCSAGV_ApiResponse
|
||||
{
|
||||
public bool success { get; set; }
|
||||
public int code { get; set; }
|
||||
public string message { get; set; }
|
||||
public object data { get; set; }
|
||||
public long timestamp { get; set; }
|
||||
|
||||
public static TCSAGV_ApiResponse Ok(string message, object data = null)
|
||||
{
|
||||
return new TCSAGV_ApiResponse
|
||||
{
|
||||
success = true,
|
||||
code = 200,
|
||||
message = message,
|
||||
data = data,
|
||||
timestamp = System.DateTimeOffset.Now.ToUnixTimeMilliseconds()
|
||||
};
|
||||
}
|
||||
|
||||
public static TCSAGV_ApiResponse Fail(string message)
|
||||
{
|
||||
return new TCSAGV_ApiResponse
|
||||
{
|
||||
success = false,
|
||||
code = 500,
|
||||
message = message,
|
||||
data = null,
|
||||
timestamp = System.DateTimeOffset.Now.ToUnixTimeMilliseconds()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,5 +40,202 @@ namespace MisDataSaveDate
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV到达/离开状态回调接口。
|
||||
/// </summary>
|
||||
/// <param name="jobj">临工AGV状态回调数据</param>
|
||||
/// <returns>处理结果</returns>
|
||||
[HttpPost]
|
||||
[Route("agv/lgagv/statusUpdate")]
|
||||
public HttpResponseMessage LGAGV_StatusUpdate([FromBody] JObject jobj)
|
||||
{
|
||||
return new HttpResponseMessage
|
||||
{
|
||||
Content = new StringContent(LGAGV_BusinessLogic.ProcessStatusUpdate(headUrl + System.Reflection.MethodBase.GetCurrentMethod().Name, jobj), Encoding.GetEncoding("UTF-8"), "application/json")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV任务结果回调接口。
|
||||
/// </summary>
|
||||
/// <param name="jobj">临工AGV任务结果数据</param>
|
||||
/// <returns>处理结果</returns>
|
||||
[HttpPost]
|
||||
[Route("agv/lgagv/taskResult")]
|
||||
public HttpResponseMessage LGAGV_TaskResult([FromBody] JObject jobj)
|
||||
{
|
||||
return new HttpResponseMessage
|
||||
{
|
||||
Content = new StringContent(LGAGV_BusinessLogic.ProcessTaskResult(headUrl + System.Reflection.MethodBase.GetCurrentMethod().Name, jobj), Encoding.GetEncoding("UTF-8"), "application/json")
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("api/reportExternalBusinessTaskStatus")]
|
||||
public HttpResponseMessage TCS_ReportExternalBusinessTaskStatus([FromBody] JObject jobj)
|
||||
{
|
||||
return JsonResponse(TCSAGV_BusinessLogic.ProcessTaskStatus("api/reportExternalBusinessTaskStatus", jobj));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("api/mcrInfoLocation")]
|
||||
public HttpResponseMessage TCS_McrInfoLocation([FromBody] JObject jobj)
|
||||
{
|
||||
return JsonResponse(TCSAGV_BusinessLogic.ProcessPositionPush("api/mcrInfoLocation", jobj));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/dispatchStation")]
|
||||
public HttpResponseMessage TCS_DispatchStation([FromBody] TCSAGV_StationDispatchRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
if (string.IsNullOrWhiteSpace(request.portCombination)) throw new Exception("请选择动作组合");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.DispatchStationTask(
|
||||
request.stationCode, request.actionType, request.portCombination, "MANUAL", request.operatorCode,
|
||||
request.parentExternalCode, false);
|
||||
return result.Success
|
||||
? TCSAGV_ApiResponse.Ok("任务下发成功", result)
|
||||
: TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/dispatchStep")]
|
||||
public HttpResponseMessage TCS_DispatchStep([FromBody] TCSAGV_StepDispatchRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.DispatchSingleStep(
|
||||
request.stationCode, request.programName, request.operatorCode, request.parentExternalCode);
|
||||
return result.Success
|
||||
? TCSAGV_ApiResponse.Ok("单步任务下发成功", result)
|
||||
: TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/retry")]
|
||||
public HttpResponseMessage TCS_Retry([FromBody] TCSAGV_TaskOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.RetryTask(request.externalCode, request.operatorCode);
|
||||
return result.Success
|
||||
? TCSAGV_ApiResponse.Ok("整单重发成功", result)
|
||||
: TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/cancel")]
|
||||
public HttpResponseMessage TCS_Cancel([FromBody] TCSAGV_TaskOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.CancelTask(request.externalCode, request.operatorCode);
|
||||
return result.Success ? TCSAGV_ApiResponse.Ok("任务取消成功", result) : TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/stopPending")]
|
||||
public HttpResponseMessage TCS_StopPending([FromBody] TCSAGV_TaskOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
string externalCode = request == null ? "" : request.externalCode;
|
||||
string operatorCode = request == null ? "" : request.operatorCode;
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.StopPendingTasks(externalCode, operatorCode);
|
||||
return result.Success ? TCSAGV_ApiResponse.Ok("未开始任务已停止", result) : TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/reset")]
|
||||
public HttpResponseMessage TCS_Reset([FromBody] TCSAGV_RobotOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.ResetRobot(
|
||||
request.externalCode, request.ip, request.operatorCode);
|
||||
return result.Success ? TCSAGV_ApiResponse.Ok("移动机器人复位成功", result) : TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/stopNow")]
|
||||
public HttpResponseMessage TCS_StopNow([FromBody] TCSAGV_RobotOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.StopNow(
|
||||
request.externalCode, request.ip, request.operatorCode);
|
||||
return result.Success ? TCSAGV_ApiResponse.Ok("移动机器人已紧急停止", result) : TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/syncTask")]
|
||||
public HttpResponseMessage TCS_SyncTask([FromBody] TCSAGV_TaskOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.SyncTaskStatus(request.externalCode, request.operatorCode);
|
||||
return result.Success ? TCSAGV_ApiResponse.Ok("任务状态同步成功", result) : TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("agv/tcs/queryRobot")]
|
||||
public HttpResponseMessage TCS_QueryRobot()
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
TCSAGV_CallResult result = TCSAGV_BusinessLogic.QueryRobotInfo();
|
||||
return result.Success ? TCSAGV_ApiResponse.Ok("机器人状态查询成功", result.Response) : TCSAGV_ApiResponse.Fail(result.Message);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("agv/tcs/handleFailure")]
|
||||
public HttpResponseMessage TCS_HandleFailure([FromBody] TCSAGV_TaskOperationRequest request)
|
||||
{
|
||||
return ExecuteTcs(() =>
|
||||
{
|
||||
if (request == null) throw new Exception("请求参数不能为空");
|
||||
TCSAGV_BusinessLogic.HandleFailure(request.externalCode, request.operatorCode, request.remark, request.notifyPlc);
|
||||
return TCSAGV_ApiResponse.Ok("失败任务已人工处理");
|
||||
});
|
||||
}
|
||||
|
||||
private static HttpResponseMessage ExecuteTcs(Func<TCSAGV_ApiResponse> action)
|
||||
{
|
||||
TCSAGV_ApiResponse response;
|
||||
try
|
||||
{
|
||||
response = action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
response = TCSAGV_ApiResponse.Fail(ex.Message);
|
||||
}
|
||||
return JsonResponse(JsonConvert.SerializeObject(response));
|
||||
}
|
||||
|
||||
private static HttpResponseMessage JsonResponse(string json)
|
||||
{
|
||||
return new HttpResponseMessage
|
||||
{
|
||||
Content = new StringContent(json, Encoding.GetEncoding("UTF-8"), "application/json")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,36 @@ namespace MisDataSaveDate
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV网页按钮调度接口。
|
||||
/// </summary>
|
||||
/// <param name="jobj">调度请求数据</param>
|
||||
/// <returns>处理结果</returns>
|
||||
[HttpPost]
|
||||
[Route("web/LGAGV_Dispatch")]
|
||||
public HttpResponseMessage LGAGV_Dispatch([FromBody] JObject jobj)
|
||||
{
|
||||
return new HttpResponseMessage
|
||||
{
|
||||
Content = new StringContent(LGWEB_BusinessLogic.WEB_DispatchAGV(headUrl + System.Reflection.MethodBase.GetCurrentMethod().Name, jobj), Encoding.GetEncoding("UTF-8"), "application/json")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV网页按钮放行接口。
|
||||
/// </summary>
|
||||
/// <param name="jobj">放行请求数据</param>
|
||||
/// <returns>处理结果</returns>
|
||||
[HttpPost]
|
||||
[Route("web/LGAGV_AllowLeave")]
|
||||
public HttpResponseMessage LGAGV_AllowLeave([FromBody] JObject jobj)
|
||||
{
|
||||
return new HttpResponseMessage
|
||||
{
|
||||
Content = new StringContent(LGWEB_BusinessLogic.WEB_AllowLeave(headUrl + System.Reflection.MethodBase.GetCurrentMethod().Name, jobj), Encoding.GetEncoding("UTF-8"), "application/json")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量读取PLC点位值接口
|
||||
/// 前端传递TagTypeCodeID数组和工位号,返回对应点位的值
|
||||
@@ -131,4 +161,4 @@ namespace MisDataSaveDate
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using DataLinkMesWork;
|
||||
using DataLinkMesWork;
|
||||
using MesServerWork;
|
||||
using MisDataFunDll;
|
||||
using MisDataSaveDate.MOM;
|
||||
@@ -24,6 +24,17 @@ namespace WebApi
|
||||
{
|
||||
public class CALL_Inerface_DataHandle
|
||||
{
|
||||
private static bool TryCheckProcessReportAllowed(string opName, string engineID, string orderForm, string reqType)
|
||||
{
|
||||
DataTable isSendDT = MisDataFun.IOT_ReqData_UpLoad_IsSend(opName, orderForm, reqType, engineID);
|
||||
if (isSendDT.Rows[0]["result"].ToString() != "1")
|
||||
{
|
||||
SaveMesLog($"工序{reqType}", isSendDT.Rows[0]["msg"].ToString(), MesLogType.ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开工(工序)
|
||||
/// </summary>
|
||||
@@ -32,19 +43,17 @@ namespace WebApi
|
||||
/// <param name="OrderForm"></param>
|
||||
public static void CALL_Inerface_JobStart(string OpName, string EngineID, string OrderForm)
|
||||
{
|
||||
DataTable IsSendDT = MisDataFun.IOT_ReqData_UpLoad_IsSend(OpName, OrderForm, "完工");
|
||||
if (IsSendDT.Rows[0]["result"].ToString() != "1")
|
||||
if (!TryCheckProcessReportAllowed(OpName, EngineID, OrderForm, "开工"))
|
||||
{
|
||||
SaveMesLog("工序完工", IsSendDT.Rows[0]["msg"].ToString(), MesLogType.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
//查询工单ID、任务ID、工序ID
|
||||
var param = new SqlParameter[] {
|
||||
new SqlParameter("@订单号",OrderForm),
|
||||
new SqlParameter("@工序号",OpName),
|
||||
new SqlParameter("@工件编号",EngineID)
|
||||
};
|
||||
new SqlParameter("@订单号",OrderForm),
|
||||
new SqlParameter("@工序号",OpName),
|
||||
new SqlParameter("@工件编号",EngineID)
|
||||
};
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_JobStart", ref param, out DataTable dt, out string errorMessage);
|
||||
|
||||
if (dt.Rows.Count > 0)
|
||||
@@ -101,19 +110,17 @@ namespace WebApi
|
||||
/// <param name="OrderForm"></param>
|
||||
public static void CALL_Inerface_JobFinished(string OpName, string EngineID, string OrderForm)
|
||||
{
|
||||
DataTable IsSendDT = MisDataFun.IOT_ReqData_UpLoad_IsSend(OpName, OrderForm, "完工");
|
||||
if (IsSendDT.Rows[0]["result"].ToString() != "1")
|
||||
if (!TryCheckProcessReportAllowed(OpName, EngineID, OrderForm, "完工"))
|
||||
{
|
||||
SaveMesLog("工序完工", IsSendDT.Rows[0]["msg"].ToString(), MesLogType.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
//查询工单ID、任务ID、工序ID
|
||||
var param = new SqlParameter[] {
|
||||
new SqlParameter("@订单号",OrderForm),
|
||||
new SqlParameter("@工序号",OpName),
|
||||
new SqlParameter("@工件编号",EngineID)
|
||||
};
|
||||
new SqlParameter("@订单号",OrderForm),
|
||||
new SqlParameter("@工序号",OpName),
|
||||
new SqlParameter("@工件编号",EngineID)
|
||||
};
|
||||
//DataAccess.ExecuteStoredProcedure("CallWebApi_FactoryMes_JobFinished", ref param, out DataSet ds);
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("CallWebApi_FactoryMes_JobFinished", ref param, out DataSet ds, out string errorMessage);
|
||||
//a.[订单ID],[任务ID],[工序ID],[工序名称],1 as 完工数量,@开工时间 as 开工时间,@结束时间 as 结束时间,@节拍 as 节拍,@操作时间 as 最后修改时间
|
||||
@@ -283,6 +290,7 @@ namespace WebApi
|
||||
orderID = dt.Rows[0]["订单ID"].ToString();
|
||||
taskID = dt.Rows[0]["任务ID"].ToString();
|
||||
}
|
||||
|
||||
// 非工厂下发的订单产品,不上传报警
|
||||
if (string.IsNullOrEmpty(orderID) || string.IsNullOrEmpty(taskID)) return;
|
||||
|
||||
@@ -567,6 +575,15 @@ namespace WebApi
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物料转序
|
||||
/// </summary>
|
||||
/// <param name="startPositionCode">起始位置编号</param>
|
||||
/// <param name="endPositionCode">终点位置编号</param>
|
||||
/// <param name="dataid">派工任务id</param>
|
||||
/// <param name="moveTaskType">搬运类型:1:搬运容器,2:搬运货架</param>
|
||||
/// <param name="vehicleStatus">载具类型:0-空;1-满</param>
|
||||
/// <returns>返回调用结果 JObject,包含 code 和 message</returns>
|
||||
/// <summary>
|
||||
/// 物料转序
|
||||
/// </summary>
|
||||
@@ -940,3 +957,4 @@ namespace WebApi
|
||||
//#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Web.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using MisDataSaveDate.Helper;
|
||||
using static MisDataSaveDate.Helper.ApiLogHelper;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// 临工AGV网页按钮业务处理。
|
||||
/// </summary>
|
||||
public class LGWEB_BusinessLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// 网页按钮下发临工AGV搬运任务。
|
||||
/// </summary>
|
||||
public static string WEB_DispatchAGV(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = new MsgResHeader<object>
|
||||
{
|
||||
code = 200,
|
||||
message = "",
|
||||
Data = null
|
||||
};
|
||||
|
||||
if (jobj == null)
|
||||
{
|
||||
result.code = 500;
|
||||
result.message = "参数格式不正确!";
|
||||
return JsonConvert.SerializeObject(result);
|
||||
}
|
||||
|
||||
string requestText = jobj.ToString();
|
||||
SaveLog_Interface_Request(url, 2, requestText, out int aid);
|
||||
|
||||
try
|
||||
{
|
||||
LGWEB_DispatchRequest request = JsonConvert.DeserializeObject<LGWEB_DispatchRequest>(requestText);
|
||||
LGWEB_DispatchResult dispatchResult = DispatchAGV(request);
|
||||
|
||||
result.code = dispatchResult.Success ? 200 : 500;
|
||||
result.message = dispatchResult.Message;
|
||||
result.Data = dispatchResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.code = 500;
|
||||
result.message = ex.Message;
|
||||
SaveMesLog("LGWEB_DispatchAGV", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string responseText = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return responseText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下发临工AGV搬运任务,供 WebAPI 和 Function 直接复用。
|
||||
/// </summary>
|
||||
public static LGWEB_DispatchResult DispatchAGV(LGWEB_DispatchRequest request, string defaultTriggerMode = "WEB", bool requireProductPoint = false)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("请求参数格式不正确");
|
||||
}
|
||||
|
||||
if (IsPointToPointDispatch(request))
|
||||
{
|
||||
return DispatchPointToPoint(request, defaultTriggerMode);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.routeCode))
|
||||
{
|
||||
throw new Exception("路线编码(routeCode)不能为空");
|
||||
}
|
||||
|
||||
LGWEB_RouteInfo route = GetRouteInfo(request);
|
||||
if (requireProductPoint && route.ProductPointMatched != "1")
|
||||
{
|
||||
throw new Exception($"未匹配产品点位配置:routeCode={request.routeCode}, 产品型号代码={request.productModelCode}, 产品型号={request.productModel}, 动作={request.actionCode}, 过程点={request.processPointType}, 工位={request.workStation}");
|
||||
}
|
||||
|
||||
string startPosition = string.IsNullOrWhiteSpace(request.startPosition) ? route.StartPosition : request.startPosition;
|
||||
string midPosition = string.IsNullOrWhiteSpace(request.midPosition) ? route.MidPosition : request.midPosition;
|
||||
string endPosition = route.ActualEndPosition;
|
||||
string requestTaskId = string.IsNullOrWhiteSpace(request.requestTaskId) ? Guid.NewGuid().ToString() : request.requestTaskId;
|
||||
string materialCode = FirstText(request.materialCode, request.productCode, request.containerNo);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(startPosition))
|
||||
{
|
||||
throw new Exception("起点位置不能为空,请检查路线配置或请求参数");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(endPosition))
|
||||
{
|
||||
throw new Exception("终点位置不能为空,请检查路线配置");
|
||||
}
|
||||
|
||||
LGAGV_CallResult agvResult;
|
||||
if (string.Equals(route.InterfaceName, "AddTaskFromMes2", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
agvResult = LGAGV_BusinessLogic.CallAddTask2(new LGAGV_AddTask2Request
|
||||
{
|
||||
requestTaskId = requestTaskId,
|
||||
startPosition = startPosition,
|
||||
midPosition = midPosition,
|
||||
endPosition = endPosition,
|
||||
materialCode = materialCode
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
agvResult = LGAGV_BusinessLogic.CallAddTask(new LGAGV_AddTaskRequest
|
||||
{
|
||||
requestTaskId = requestTaskId,
|
||||
startPosition = startPosition,
|
||||
endPosition = endPosition,
|
||||
materialCode = materialCode
|
||||
});
|
||||
}
|
||||
|
||||
SaveDispatchResult(request, route, requestTaskId, startPosition, midPosition, endPosition, materialCode, agvResult, defaultTriggerMode);
|
||||
|
||||
return new LGWEB_DispatchResult
|
||||
{
|
||||
Success = agvResult.Success,
|
||||
Message = agvResult.Success ? "AGV调度成功" : $"AGV调度失败:{agvResult.Message}",
|
||||
DispatchMode = "ROUTE",
|
||||
RequestTaskId = requestTaskId,
|
||||
RouteCode = request.routeCode,
|
||||
StartPosition = startPosition,
|
||||
MidPosition = midPosition,
|
||||
EndPosition = endPosition,
|
||||
OriginalEndPosition = route.OriginalEndPosition,
|
||||
ProductPointMatched = route.ProductPointMatched,
|
||||
ProcessPointType = route.ProcessPointType,
|
||||
RouteMessage = route.RouteMessage,
|
||||
AgvResponse = agvResult.Response
|
||||
};
|
||||
}
|
||||
|
||||
private static LGWEB_DispatchResult DispatchPointToPoint(LGWEB_DispatchRequest request, string defaultTriggerMode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.startPosition))
|
||||
{
|
||||
throw new Exception("点到点模式起点位置(startPosition)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.endPosition))
|
||||
{
|
||||
throw new Exception("点到点模式终点位置(endPosition)不能为空");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(request.midPosition))
|
||||
{
|
||||
throw new Exception("点到点模式不支持中间位置(midPosition)");
|
||||
}
|
||||
if (string.Equals(request.startPosition.Trim(), request.endPosition.Trim(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new Exception("点到点模式起点和终点不能相同");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.productCode))
|
||||
{
|
||||
throw new Exception("点到点模式产品编码(productCode)不能为空");
|
||||
}
|
||||
|
||||
request.routeCode = FirstText(request.routeCode, "MANUAL_POINT_TO_POINT");
|
||||
string requestTaskId = string.IsNullOrWhiteSpace(request.requestTaskId) ? Guid.NewGuid().ToString() : request.requestTaskId;
|
||||
string materialCode = FirstText(request.materialCode, request.productCode, request.containerNo);
|
||||
string triggerMode = string.IsNullOrWhiteSpace(defaultTriggerMode) ? "WEB" : defaultTriggerMode;
|
||||
|
||||
DataRow validateRow = ValidatePointToPoint(request);
|
||||
LGWEB_RouteInfo route = new LGWEB_RouteInfo
|
||||
{
|
||||
RouteCode = request.routeCode,
|
||||
StartPosition = request.startPosition,
|
||||
MidPosition = "",
|
||||
OriginalEndPosition = request.endPosition,
|
||||
ActualEndPosition = request.endPosition,
|
||||
InterfaceName = "AddTaskFromMes",
|
||||
BusinessType = "点到点搬运",
|
||||
TriggerMode = triggerMode,
|
||||
SourceWorkStation = ReadColumn(validateRow, "起点工位号"),
|
||||
TargetWorkStation = ReadColumn(validateRow, "终点工位号"),
|
||||
ProductPointMatched = "0",
|
||||
ProcessPointType = "",
|
||||
RouteMessage = ReadColumn(validateRow, "msg")
|
||||
};
|
||||
|
||||
LGAGV_CallResult agvResult = LGAGV_BusinessLogic.CallAddTask(new LGAGV_AddTaskRequest
|
||||
{
|
||||
requestTaskId = requestTaskId,
|
||||
startPosition = request.startPosition,
|
||||
endPosition = request.endPosition,
|
||||
materialCode = materialCode
|
||||
});
|
||||
|
||||
SaveDispatchResult(request, route, requestTaskId, request.startPosition, "", request.endPosition, materialCode, agvResult, triggerMode);
|
||||
|
||||
return new LGWEB_DispatchResult
|
||||
{
|
||||
Success = agvResult.Success,
|
||||
Message = agvResult.Success ? "AGV点到点调度成功" : $"AGV点到点调度失败:{agvResult.Message}",
|
||||
DispatchMode = "POINT_TO_POINT",
|
||||
RequestTaskId = requestTaskId,
|
||||
RouteCode = request.routeCode,
|
||||
StartPosition = request.startPosition,
|
||||
MidPosition = "",
|
||||
EndPosition = request.endPosition,
|
||||
OriginalEndPosition = request.endPosition,
|
||||
ProductPointMatched = "0",
|
||||
ProcessPointType = "",
|
||||
RouteMessage = route.RouteMessage,
|
||||
AgvResponse = agvResult.Response
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网页按钮放行临工AGV离开。
|
||||
/// </summary>
|
||||
public static string WEB_AllowLeave(string url, [FromBody] JObject jobj)
|
||||
{
|
||||
var result = new MsgResHeader<object>
|
||||
{
|
||||
code = 200,
|
||||
message = "",
|
||||
Data = null
|
||||
};
|
||||
|
||||
if (jobj == null)
|
||||
{
|
||||
result.code = 500;
|
||||
result.message = "参数格式不正确!";
|
||||
return JsonConvert.SerializeObject(result);
|
||||
}
|
||||
|
||||
string requestText = jobj.ToString();
|
||||
SaveLog_Interface_Request(url, 2, requestText, out int aid);
|
||||
|
||||
try
|
||||
{
|
||||
LGWEB_AllowLeaveRequest request = JsonConvert.DeserializeObject<LGWEB_AllowLeaveRequest>(requestText);
|
||||
if (request == null)
|
||||
{
|
||||
throw new Exception("请求参数格式不正确");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.requestId))
|
||||
{
|
||||
throw new Exception("请求ID(requestId)不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(request.position))
|
||||
{
|
||||
throw new Exception("位置(position)不能为空");
|
||||
}
|
||||
|
||||
LGAGV_CallResult agvResult = LGAGV_BusinessLogic.CallAllowLeave(new LGAGV_AllowLeaveRequest
|
||||
{
|
||||
requestId = request.requestId,
|
||||
position = request.position,
|
||||
agvNo = request.agvNo,
|
||||
allowLeave = 1
|
||||
});
|
||||
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@requestId", request.requestId ?? ""),
|
||||
new SqlParameter("@position", request.position ?? ""),
|
||||
new SqlParameter("@agvNo", request.agvNo ?? ""),
|
||||
new SqlParameter("@操作人工号", request.operatorCode ?? ""),
|
||||
new SqlParameter("@操作人姓名", request.operatorName ?? ""),
|
||||
new SqlParameter("@备注", request.remark ?? ""),
|
||||
new SqlParameter("@是否成功", agvResult.Success ? 1 : 2),
|
||||
new SqlParameter("@错误信息", agvResult.Success ? "" : (agvResult.Message ?? ""))
|
||||
};
|
||||
ExecuteResultProcedure("LG_AGV_库位Moby_允许离开", ref param);
|
||||
|
||||
result.code = agvResult.Success ? 200 : 500;
|
||||
result.message = agvResult.Success ? "AGV放行成功" : $"AGV放行失败:{agvResult.Message}";
|
||||
result.Data = new
|
||||
{
|
||||
requestId = request.requestId,
|
||||
position = request.position,
|
||||
agvResponse = agvResult.Response
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.code = 500;
|
||||
result.message = ex.Message;
|
||||
SaveMesLog("LGWEB_AllowLeave", ex.Message, MesLogType.ERROR);
|
||||
}
|
||||
|
||||
string responseText = JsonConvert.SerializeObject(result);
|
||||
SaveLog_Interface_Response(responseText, aid);
|
||||
return responseText;
|
||||
}
|
||||
|
||||
private static bool IsPointToPointDispatch(LGWEB_DispatchRequest request)
|
||||
{
|
||||
if (string.Equals((request.dispatchMode ?? "").Trim(), "POINT_TO_POINT", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !string.IsNullOrWhiteSpace(request.startPosition) && !string.IsNullOrWhiteSpace(request.endPosition);
|
||||
}
|
||||
|
||||
private static DataRow ValidatePointToPoint(LGWEB_DispatchRequest request)
|
||||
{
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@起点位置", request.startPosition ?? ""),
|
||||
new SqlParameter("@终点位置", request.endPosition ?? ""),
|
||||
new SqlParameter("@产品编码", request.productCode ?? "")
|
||||
};
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("LG_AGV_库位Moby_点到点校验", ref param, out DataTable dt, out string errMessage);
|
||||
if (!string.IsNullOrEmpty(errMessage))
|
||||
{
|
||||
throw new Exception(errMessage);
|
||||
}
|
||||
if (dt == null || dt.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("点到点校验无返回结果");
|
||||
}
|
||||
|
||||
DataRow row = dt.Rows[0];
|
||||
string resultText = row.Table.Columns.Contains("result") ? row["result"].ToString() : "2";
|
||||
if (resultText != "1")
|
||||
{
|
||||
string msg = ReadColumn(row, "msg", "message");
|
||||
throw new Exception(string.IsNullOrWhiteSpace(msg) ? "点到点校验失败" : msg);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
private static LGWEB_RouteInfo GetRouteInfo(LGWEB_DispatchRequest request)
|
||||
{
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@路线编码", request.routeCode ?? ""),
|
||||
new SqlParameter("@产品型号代码", request.productModelCode ?? ""),
|
||||
new SqlParameter("@产品型号", request.productModel ?? ""),
|
||||
new SqlParameter("@动作编码", request.actionCode ?? ""),
|
||||
new SqlParameter("@过程点大类", request.processPointType ?? ""),
|
||||
new SqlParameter("@工位号", request.workStation ?? "")
|
||||
};
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure("LG_AGV_路线_实际终点解析", ref param, out DataTable dt, out string errMessage);
|
||||
if (!string.IsNullOrEmpty(errMessage))
|
||||
{
|
||||
throw new Exception(errMessage);
|
||||
}
|
||||
if (dt == null || dt.Rows.Count == 0)
|
||||
{
|
||||
throw new Exception("路线解析无返回结果");
|
||||
}
|
||||
|
||||
DataRow row = dt.Rows[0];
|
||||
string resultText = row.Table.Columns.Contains("result") ? row["result"].ToString() : "2";
|
||||
if (resultText != "1")
|
||||
{
|
||||
string msg = ReadColumn(row, "msg", "message");
|
||||
throw new Exception(string.IsNullOrWhiteSpace(msg) ? "路线不可用" : msg);
|
||||
}
|
||||
|
||||
return new LGWEB_RouteInfo
|
||||
{
|
||||
RouteCode = ReadColumn(row, "路线编码"),
|
||||
StartPosition = ReadColumn(row, "起点位置"),
|
||||
MidPosition = ReadColumn(row, "中间位置"),
|
||||
OriginalEndPosition = ReadColumn(row, "原终点位置", "终点位置"),
|
||||
ActualEndPosition = ReadColumn(row, "实际终点位置"),
|
||||
InterfaceName = FirstText(ReadColumn(row, "调用接口"), "AddTaskFromMes"),
|
||||
BusinessType = ReadColumn(row, "业务类型"),
|
||||
TriggerMode = ReadColumn(row, "触发方式"),
|
||||
SourceWorkStation = ReadColumn(row, "源工位号"),
|
||||
TargetWorkStation = ReadColumn(row, "目标工位号"),
|
||||
ProductPointMatched = ReadColumn(row, "是否匹配型号点位"),
|
||||
ProductModelCode = ReadColumn(row, "产品型号代码"),
|
||||
ProductModel = ReadColumn(row, "产品型号"),
|
||||
ActionCode = ReadColumn(row, "动作编码"),
|
||||
ProcessPointType = ReadColumn(row, "过程点大类"),
|
||||
RouteMessage = ReadColumn(row, "msg", "message")
|
||||
};
|
||||
}
|
||||
|
||||
private static void SaveDispatchResult(LGWEB_DispatchRequest request, LGWEB_RouteInfo route, string requestTaskId,
|
||||
string startPosition, string midPosition, string endPosition, string materialCode, LGAGV_CallResult agvResult, string defaultTriggerMode)
|
||||
{
|
||||
var param = new SqlParameter[]
|
||||
{
|
||||
new SqlParameter("@路线编码", request.routeCode ?? ""),
|
||||
new SqlParameter("@业务类型", route.BusinessType ?? ""),
|
||||
new SqlParameter("@触发方式", string.IsNullOrWhiteSpace(route.TriggerMode) ? (defaultTriggerMode ?? "WEB") : route.TriggerMode),
|
||||
new SqlParameter("@订单号", request.orderNo ?? ""),
|
||||
new SqlParameter("@产品编码", FirstText(request.productCode, request.materialCode)),
|
||||
new SqlParameter("@产品型号", request.productModel ?? ""),
|
||||
new SqlParameter("@器具号", request.containerNo ?? ""),
|
||||
new SqlParameter("@requestTaskId", requestTaskId ?? ""),
|
||||
new SqlParameter("@起点位置", startPosition ?? ""),
|
||||
new SqlParameter("@中间位置", midPosition ?? ""),
|
||||
new SqlParameter("@终点位置", endPosition ?? ""),
|
||||
new SqlParameter("@原终点位置", route.OriginalEndPosition ?? ""),
|
||||
new SqlParameter("@materialCode", materialCode ?? ""),
|
||||
new SqlParameter("@调用接口", route.InterfaceName ?? ""),
|
||||
new SqlParameter("@操作人工号", request.operatorCode ?? ""),
|
||||
new SqlParameter("@操作人姓名", request.operatorName ?? ""),
|
||||
new SqlParameter("@备注", request.remark ?? ""),
|
||||
new SqlParameter("@是否成功", agvResult.Success ? 1 : 2),
|
||||
new SqlParameter("@错误信息", agvResult.Success ? "" : (agvResult.Message ?? ""))
|
||||
};
|
||||
ExecuteResultProcedure("LG_AGV_库位Moby_下发任务", ref param);
|
||||
}
|
||||
|
||||
private static string ReadColumn(DataRow row, params string[] columnNames)
|
||||
{
|
||||
foreach (string columnName in columnNames)
|
||||
{
|
||||
if (row.Table.Columns.Contains(columnName))
|
||||
{
|
||||
return row[columnName]?.ToString() ?? "";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static string FirstText(params string[] values)
|
||||
{
|
||||
foreach (string value in values)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static void ExecuteResultProcedure(string procedureName, ref SqlParameter[] param)
|
||||
{
|
||||
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure(procedureName, ref param, out DataTable dt, out string errMessage);
|
||||
if (!string.IsNullOrEmpty(errMessage))
|
||||
{
|
||||
throw new Exception(errMessage);
|
||||
}
|
||||
if (dt != null && dt.Rows.Count > 0 && dt.Columns.Contains("result") && dt.Rows[0]["result"].ToString() != "1")
|
||||
{
|
||||
string msg = dt.Columns.Contains("msg") ? dt.Rows[0]["msg"].ToString() : "存储过程执行失败";
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class LGWEB_RouteInfo
|
||||
{
|
||||
public string RouteCode { get; set; }
|
||||
public string StartPosition { get; set; }
|
||||
public string MidPosition { get; set; }
|
||||
public string OriginalEndPosition { get; set; }
|
||||
public string ActualEndPosition { get; set; }
|
||||
public string InterfaceName { get; set; }
|
||||
public string BusinessType { get; set; }
|
||||
public string TriggerMode { get; set; }
|
||||
public string SourceWorkStation { get; set; }
|
||||
public string TargetWorkStation { get; set; }
|
||||
public string ProductPointMatched { get; set; }
|
||||
public string ProductModelCode { get; set; }
|
||||
public string ProductModel { get; set; }
|
||||
public string ActionCode { get; set; }
|
||||
public string ProcessPointType { get; set; }
|
||||
public string RouteMessage { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_Models.cs
Normal file
88
Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_Models.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace MisDataSaveDate
|
||||
{
|
||||
/// <summary>
|
||||
/// 临工AGV网页按钮调度请求。
|
||||
/// </summary>
|
||||
public class LGWEB_DispatchRequest
|
||||
{
|
||||
public string dispatchMode { get; set; }
|
||||
public string routeCode { get; set; }
|
||||
public string requestTaskId { get; set; }
|
||||
public string startPosition { get; set; }
|
||||
public string midPosition { get; set; }
|
||||
public string endPosition { get; set; }
|
||||
public string materialCode { get; set; }
|
||||
public string productCode { get; set; }
|
||||
public string productModelCode { get; set; }
|
||||
public string productModel { get; set; }
|
||||
public string actionCode { get; set; }
|
||||
public string processPointType { get; set; }
|
||||
public string workStation { get; set; }
|
||||
public string containerNo { get; set; }
|
||||
public string orderNo { get; set; }
|
||||
public string operatorCode { get; set; }
|
||||
public string operatorName { get; set; }
|
||||
public string remark { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV网页按钮放行请求。
|
||||
/// </summary>
|
||||
public class LGWEB_AllowLeaveRequest
|
||||
{
|
||||
public string requestId { get; set; }
|
||||
public string position { get; set; }
|
||||
public string agvNo { get; set; }
|
||||
public string operatorCode { get; set; }
|
||||
public string operatorName { get; set; }
|
||||
public string remark { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临工AGV调度内部结果,WebAPI 和 Function 共用。
|
||||
/// </summary>
|
||||
public class LGWEB_DispatchResult
|
||||
{
|
||||
[JsonProperty("success")]
|
||||
public bool Success { get; set; }
|
||||
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
[JsonProperty("dispatchMode")]
|
||||
public string DispatchMode { get; set; }
|
||||
|
||||
[JsonProperty("requestTaskId")]
|
||||
public string RequestTaskId { get; set; }
|
||||
|
||||
[JsonProperty("routeCode")]
|
||||
public string RouteCode { get; set; }
|
||||
|
||||
[JsonProperty("startPosition")]
|
||||
public string StartPosition { get; set; }
|
||||
|
||||
[JsonProperty("midPosition")]
|
||||
public string MidPosition { get; set; }
|
||||
|
||||
[JsonProperty("endPosition")]
|
||||
public string EndPosition { get; set; }
|
||||
|
||||
[JsonProperty("originalEndPosition")]
|
||||
public string OriginalEndPosition { get; set; }
|
||||
|
||||
[JsonProperty("productPointMatched")]
|
||||
public string ProductPointMatched { get; set; }
|
||||
|
||||
[JsonProperty("processPointType")]
|
||||
public string ProcessPointType { get; set; }
|
||||
|
||||
[JsonProperty("routeMessage")]
|
||||
public string RouteMessage { get; set; }
|
||||
|
||||
[JsonProperty("agvResponse")]
|
||||
public JObject AgvResponse { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace MisDataSaveDate
|
||||
throw new Exception("OperAtion_JobStart 缺少必要参数:工位号、订单号或工件编号");
|
||||
}
|
||||
|
||||
CALL_Inerface_DataHandle.CALL_Inerface_JobStart(workStation1, orderNo1, workpieceNo1);
|
||||
CALL_Inerface_DataHandle.CALL_Inerface_JobStart(workStation1, workpieceNo1, orderNo1);
|
||||
break;
|
||||
|
||||
case "OperAtion_JobFinished":
|
||||
|
||||
Reference in New Issue
Block a user