From dcec36611d9f1f5fcf358118146e36e21a59aa78 Mon Sep 17 00:00:00 2001
From: XingCheng3 <1773407212@qq.com>
Date: Thu, 16 Jul 2026 16:46:06 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0LG-AGV=E6=8E=A5?=
=?UTF-8?q?=E5=8F=A3=E5=B9=B6=E5=AE=8C=E5=96=84=E7=89=A9=E6=96=99=E6=A0=A1?=
=?UTF-8?q?=E9=AA=8C=E4=B8=8E=E6=8A=A5=E5=B7=A5=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../14MisDataFunctionDB/MisDataFun.DB.cs | 18 +-
..._FactoryMes_JobFinished_断路器质量聚合.sql | 177 +++++++++
...IOT接口_报工记录_是否报工判断_断路器规则.sql | 63 +++
.../SlMesDbIterface/ExternalDataSync.csproj | 6 +-
.../WebAPI/AGV/LGAGV_BusinessLogic.cs | 364 ++++++++++++++++++
.../WebAPI/AGV/LGAGV_Models.cs | 106 +++++
.../WebAPI/Controller/AGVController.cs | 30 ++
.../WebAPI/Controller/WEBController.cs | 32 +-
.../FactoryMES/CALL_Inerface_DataHandle.cs | 19 +-
.../WebAPI/WEB/LGWEB_BusinessLogic.cs | 319 +++++++++++++++
.../WebAPI/WEB/LGWEB_Models.cs | 34 ++
.../WebAPI/WEB/WEB_BusinessLogic.cs | 6 +-
MisDataFun_Exe/09MesDataFunction.dll | Bin 122880 -> 122880 bytes
MisDataFun_Exe/09MesDataFunction.pdb | Bin 380416 -> 378368 bytes
MisDataFun_Exe/ExternalDataSync.exe | Bin 471552 -> 473088 bytes
MisDataFun_Exe/ExternalDataSync.pdb | Bin 1035776 -> 1031680 bytes
MisDataFun_Exe/Function1051.dll | Bin 27648 -> 28672 bytes
MisDataFun_Exe/Function1051.pdb | Bin 67072 -> 69120 bytes
MisDataFun_Exe/Function1052.dll | Bin 25600 -> 26624 bytes
MisDataFun_Exe/Function1052.pdb | Bin 60928 -> 60928 bytes
MisDataFun_Exe/Function1053.dll | Bin 17408 -> 18432 bytes
MisDataFun_Exe/Function1053.pdb | Bin 50688 -> 50688 bytes
MisDataFun_Exe/Function1054.dll | Bin 15872 -> 16896 bytes
MisDataFun_Exe/Function1054.pdb | Bin 50688 -> 54784 bytes
MisDataFun_Exe/MisDataFun.exe | Bin 118784 -> 118784 bytes
MisDataFun_Exe/MisDataFun.pdb | Bin 167424 -> 165376 bytes
MisDataFun_Exe/MyLog4Net.dll | Bin 6144 -> 6144 bytes
MisDataFun_Exe/MyLog4Net.pdb | Bin 24064 -> 24064 bytes
.../Function1051/OpcServer/EngineGetOver.cs | 7 +-
.../Function1051/OpcServer/MaterialsVerify.cs | 33 +-
.../Function1051/OpcServer/MesRead.cs | 11 +-
.../Function1052/OpcServer/EngineGetOver.cs | 7 +-
.../Function1052/OpcServer/MaterialsVerify.cs | 33 +-
.../Function1052/OpcServer/MesRead.cs | 11 +-
.../Function1053/OpcServer/MaterialsVerify.cs | 33 +-
.../OpcServer/RequestReturnMaterial.cs | 1 -
36 files changed, 1274 insertions(+), 36 deletions(-)
create mode 100644 DatabaseScripts/CallWebApi_FactoryMes_JobFinished_断路器质量聚合.sql
create mode 100644 DatabaseScripts/接口_IOT接口_报工记录_是否报工判断_断路器规则.sql
create mode 100644 Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_BusinessLogic.cs
create mode 100644 Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_Models.cs
create mode 100644 Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_BusinessLogic.cs
create mode 100644 Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_Models.cs
diff --git a/Common/09MesDataFunction/MesDataFunction/14MisDataFunctionDB/MisDataFun.DB.cs b/Common/09MesDataFunction/MesDataFunction/14MisDataFunctionDB/MisDataFun.DB.cs
index 6047738..5810bc1 100644
--- a/Common/09MesDataFunction/MesDataFunction/14MisDataFunctionDB/MisDataFun.DB.cs
+++ b/Common/09MesDataFunction/MesDataFunction/14MisDataFunctionDB/MisDataFun.DB.cs
@@ -212,13 +212,14 @@ namespace MisDataFunDll
///
///
///
- public static DataTable IOT_ReqData_UpLoad_IsSend(string opName, string OrderFrom, string reqType)
+ public static DataTable IOT_ReqData_UpLoad_IsSend(string opName, string OrderFrom, string reqType, string engineID = "")
{
string produceName = "接口_IOT接口_报工记录_是否报工判断";
- SqlParameter[] thisParms = new SqlParameter[3];
+ SqlParameter[] thisParms = new SqlParameter[4];
thisParms[0] = new System.Data.SqlClient.SqlParameter("@工位号", opName);
thisParms[1] = new System.Data.SqlClient.SqlParameter("@订单号", OrderFrom);
thisParms[2] = new System.Data.SqlClient.SqlParameter("@报工类型", reqType);
+ thisParms[3] = new System.Data.SqlClient.SqlParameter("@工件编号", engineID ?? "");
DataAccess.ExecuteStoredProcedure(produceName, ref thisParms, out DataTable dt);
return dt;
}
@@ -1772,6 +1773,19 @@ namespace MisDataFunDll
return dt;
}
+ ///
+ /// 根据工件编号查询派工订单执行计划信息
+ ///
+ public static DataTable XD_GetPlanInfoByEngineID(string engineID)
+ {
+ DataTable dt = new DataTable();
+ string procedureName = "XD_派工订单执行计划_按工件编号查询";
+ SqlParameter[] thisParms = new SqlParameter[1];
+ thisParms[0] = new System.Data.SqlClient.SqlParameter("@工件编号", engineID ?? "");
+ DataAccess.ExecuteStoredProcedure(procedureName, ref thisParms, out dt);
+ return dt;
+ }
+
///
/// 报警工位记录表_MOBY_查询
///
diff --git a/DatabaseScripts/CallWebApi_FactoryMes_JobFinished_断路器质量聚合.sql b/DatabaseScripts/CallWebApi_FactoryMes_JobFinished_断路器质量聚合.sql
new file mode 100644
index 0000000..7169610
--- /dev/null
+++ b/DatabaseScripts/CallWebApi_FactoryMes_JobFinished_断路器质量聚合.sql
@@ -0,0 +1,177 @@
+ALTER PROCEDURE [dbo].[CallWebApi_FactoryMes_JobFinished]
+ @订单号 nvarchar(50) = null,
+ @工序号 nvarchar(50) = null,
+ @工件编号 nvarchar(100) = null
+AS
+BEGIN
+ SET NOCOUNT ON
+
+ declare @开工时间 datetime
+ declare @结束时间 datetime
+ declare @操作时间 datetime
+ declare @节拍 int
+ declare @是否合格 int=0
+ declare @是否断路器聚合 bit = 0
+
+ if(@工序号 like 'AC06%' and charindex('-', @工序号) = 0)
+ begin
+ set @是否断路器聚合 = 1
+ end
+
+ -- 1、获取当前触发报工工件的开完工时间
+ select top(1)
+ @开工时间=[到达时间],
+ @结束时间=[离开时间],
+ @节拍=[在线时间],
+ @操作时间=操作时间,
+ @是否合格=是否合格
+ from [测量数据发动机在线状态]
+ where 发动机号=@工件编号 and 工位号=@工序号
+ order by ID desc
+
+ -- 如果开完工数据没有,手动报工使用当前时间兜底
+ if(@开工时间 is null or @开工时间 = '')
+ begin
+ SET @开工时间 = GETDATE()
+ SET @结束时间 = GETDATE()
+ SET @节拍 = 0
+ SET @操作时间 = GETDATE()
+ SET @是否合格 = 1
+ end
+
+ -- 表1:订单任务信息
+ SELECT TOP(1) a.[订单ID],[任务ID],[工序ID],[工序编号],[工序名称],产品编号,1 as 完工数量,
+ FORMAT(@开工时间, 'yyyy-MM-dd HH:mm:ss') as 开工时间,
+ FORMAT(@结束时间, 'yyyy-MM-dd HH:mm:ss') as 结束时间,
+ @节拍 as 节拍,
+ FORMAT(@操作时间, 'yyyy-MM-dd HH:mm:ss') as 最后修改时间,
+ b.产品型号
+ FROM [生产计划_派工订单_工序任务] a
+ inner join [生产计划_派工订单_执行计划] b on a.workOrderNo=b.订单号
+ where a.workOrderNo=@订单号 and a.工序编号=@工序号
+ order by [任务号]
+
+ -- 2、获取检验信息
+ declare @Id_tagCF int=0
+ select top(1) @Id_tagCF=Id_tagCF
+ from [测量数据合格索引]
+ where EngineID=@工件编号 and 工位号=@工序号
+ order by Id_tagCF desc
+
+ -- 获取当前订单的物料号(产品编号)
+ declare @物料号 nvarchar(100) = ''
+ select top(1) @物料号 = 产品编号
+ from [生产计划_派工订单_工序任务]
+ where workOrderNo=@订单号 and 工序编号=@工序号
+ order by [任务号]
+
+ -- 获取该物料号+工序号下最新下发的模板ID
+ declare @最新模板ID nvarchar(100) = ''
+ select top(1) @最新模板ID = Id
+ from [MOM_检验模板]
+ where MaterialCode = @物料号 and ProcedureCode = @工序号
+ order by [操作时间] desc
+
+ if(@是否断路器聚合 = 1)
+ begin
+ declare @聚合是否合格 int = 1
+
+ ;with 最新索引 as
+ (
+ select
+ i.Id_tagCF,
+ i.EngineID,
+ i.工位号,
+ i.合格标志,
+ row_number() over(partition by i.EngineID, i.工位号 order by i.Id_tagCF desc) as rn
+ from [测量数据合格索引] i
+ inner join [生产计划_派工订单_执行计划] p on p.工件编号 = i.EngineID
+ where p.订单号 = @订单号
+ and i.工位号 = @工序号
+ and isnull(p.小机型, '') in ('1','2','3')
+ )
+ select @聚合是否合格 = case when count(1) = 0 then @是否合格 else min(isnull(合格标志, 1)) end
+ from 最新索引
+ where rn = 1
+
+ ;with 最新索引 as
+ (
+ select
+ i.Id_tagCF,
+ i.EngineID,
+ i.工位号,
+ row_number() over(partition by i.EngineID, i.工位号 order by i.Id_tagCF desc) as rn
+ from [测量数据合格索引] i
+ inner join [生产计划_派工订单_执行计划] p on p.工件编号 = i.EngineID
+ where p.订单号 = @订单号
+ and i.工位号 = @工序号
+ and isnull(p.小机型, '') in ('1','2','3')
+ )
+ SELECT a.[工位号],a.[Id_tagCF],a.[EngineID],
+ @聚合是否合格 as 是否合格,
+ a.[测量项目],a.测量位置 as 质检项目名称,
+ CASE
+ WHEN TRY_CAST(a.[TagValue] AS FLOAT) IS NOT NULL
+ THEN CAST(ROUND(CAST(a.[TagValue] AS FLOAT), 2) AS NVARCHAR(100))
+ ELSE a.[TagValue]
+ END AS TagValue,
+ [IsGoodBad] as 检测结果,上限值,下限值,理论值,a.测量单位,
+ c.TemplateId as 检验项目ID, t.Code as 模板编号, c.LineNum as 检验项目编号
+ FROM 最新索引 x
+ inner join [测量数据合格] a on a.Id_tagCF = x.Id_tagCF
+ LEFT JOIN MOM_检验模板_关联表 b ON a.TagID = b.TagID
+ LEFT JOIN MOM_检验模板_检验项目 c ON c.TemplateId = @最新模板ID AND c.InspectionItemName = b.模板项名称
+ LEFT JOIN MOM_检验模板 t ON t.Id = @最新模板ID
+ where x.rn = 1
+ and a.测量项目 != '备用'
+ and a.TagValue != '0'
+ order by a.EngineID, a.id desc
+ end
+ else if(@Id_tagCF = 0 or @Id_tagCF is null) -- 前端手动报工用
+ begin
+ SELECT [工位号],[Id_tagCF],[EngineID],@是否合格 as 是否合格,[测量项目],测量位置 as 质检项目名称,
+ CASE
+ WHEN TRY_CAST([TagValue] AS FLOAT) IS NOT NULL
+ THEN CAST(ROUND(CAST([TagValue] AS FLOAT), 2) AS NVARCHAR(100))
+ ELSE [TagValue]
+ END AS TagValue,
+ [IsGoodBad] as 检测结果,上限值,下限值,理论值,测量单位,
+ '' as 检验项目ID, '' as 模板编号, '' as 检验项目编号
+ FROM [测量数据合格]
+ where Id_tagCF=2
+ order by id desc
+ end
+ else
+ begin
+ SELECT a.[工位号],[Id_tagCF],[EngineID],@是否合格 as 是否合格,a.[测量项目],a.测量位置 as 质检项目名称,
+ CASE
+ WHEN TRY_CAST(a.[TagValue] AS FLOAT) IS NOT NULL
+ THEN CAST(ROUND(CAST(a.[TagValue] AS FLOAT), 2) AS NVARCHAR(100))
+ ELSE a.[TagValue]
+ END AS TagValue,
+ [IsGoodBad] as 检测结果,上限值,下限值,理论值,a.测量单位,
+ c.TemplateId as 检验项目ID, t.Code as 模板编号, c.LineNum as 检验项目编号
+ FROM [测量数据合格] a
+ LEFT JOIN MOM_检验模板_关联表 b ON a.TagID = b.TagID
+ LEFT JOIN MOM_检验模板_检验项目 c ON c.TemplateId = @最新模板ID AND c.InspectionItemName = b.模板项名称
+ LEFT JOIN MOM_检验模板 t ON t.Id = @最新模板ID
+ where EngineID=@工件编号 and a.工位号=@工序号 and Id_tagCF=@Id_tagCF and a.测量项目 != '备用' and TagValue != '0'
+ order by a.id desc
+ end
+
+ -- 3、获取物料信息(从PLC扫码物料记录读取)
+ SELECT [工位号]
+ ,[产品编号] as [工件编号]
+ ,[工单号] as [订单号]
+ ,'' as [任务号]
+ ,[物料代码] as 物料编号
+ ,[物料批次号]
+ ,[物料流水号]
+ ,[物料名称]
+ ,1 as [数量]
+ FROM [dbo].[XD_物料记录]
+ where [工位号]=@工序号 and [产品编号]=@工件编号 and isnull([物料代码], '') != ''
+ order by [操作时间]
+
+ -- 4、获取工时信息
+END
diff --git a/DatabaseScripts/接口_IOT接口_报工记录_是否报工判断_断路器规则.sql b/DatabaseScripts/接口_IOT接口_报工记录_是否报工判断_断路器规则.sql
new file mode 100644
index 0000000..c7aa0c9
--- /dev/null
+++ b/DatabaseScripts/接口_IOT接口_报工记录_是否报工判断_断路器规则.sql
@@ -0,0 +1,63 @@
+ALTER PROCEDURE [dbo].[接口_IOT接口_报工记录_是否报工判断]
+@工位号 nvarchar(50) = 'OP10',
+@订单号 nvarchar(50) = 'SA10025',
+@报工类型 nvarchar(50) = '开工',
+@工件编号 nvarchar(100) = null
+AS
+SET NOCOUNT ON
+
+-- 已成功报工的工序不重复报工
+declare @成功次数 int
+select @成功次数 = count(1)
+from 接口_IOT接口_报工记录
+where 工位号 = @工位号
+ and 订单号 = @订单号
+ and 报工类型 = @报工类型
+ and 报工结果 = 1
+
+if(@成功次数 > 0)
+begin
+ select 2 as result,@工位号 + '订单号:'+@订单号+'产品工序已'+@报工类型+',无需二次报工' as msg
+ return
+end
+
+-- 断路器主工位:静端进站开工,拐臂箱出站完工;副工位如 AC0603-1 不参与此判断
+if(@工位号 like 'AC06%' and charindex('-', @工位号) = 0)
+begin
+ declare @当前工件编号 nvarchar(100) = null
+ declare @小机型 int = null
+
+ set @当前工件编号 = nullif(@工件编号, '')
+
+ if(@当前工件编号 is null)
+ begin
+ select top 1 @当前工件编号 = 变速器序列号
+ from 北汽福田工位状态监控MOBY
+ where 工位号 = @工位号
+ order by ID desc
+ end
+
+ select top 1 @小机型 = try_convert(int, 小机型)
+ from 生产计划_派工订单_执行计划
+ where 工件编号 = @当前工件编号
+
+ if(@小机型 is null)
+ begin
+ select 2 as result,@工位号 + '订单号:'+@订单号+'产品工序'+@报工类型+',未查询到工件编号['+isnull(@当前工件编号,'')+']对应的小机型' as msg
+ return
+ end
+
+ if(@报工类型 = '开工' and @小机型 <> 1)
+ begin
+ select 2 as result,@工位号 + '订单号:'+@订单号+'产品工序开工,非静端不进行报工' as msg
+ return
+ end
+
+ if(@报工类型 = '完工' and @小机型 <> 3)
+ begin
+ select 2 as result,@工位号 + '订单号:'+@订单号+'产品工序完工,非拐臂箱不进行报工' as msg
+ return
+ end
+end
+
+select 1 as result,'' as msg
diff --git a/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj b/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj
index 812ee07..d7ba396 100644
--- a/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj
+++ b/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj
@@ -212,8 +212,12 @@
+
+
+
+
@@ -519,4 +523,4 @@
-
\ No newline at end of file
+
diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_BusinessLogic.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_BusinessLogic.cs
new file mode 100644
index 0000000..d1503ec
--- /dev/null
+++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_BusinessLogic.cs
@@ -0,0 +1,364 @@
+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;
+
+namespace MisDataSaveDate
+{
+ ///
+ /// 临工AGV接口业务处理。
+ ///
+ public class LGAGV_BusinessLogic
+ {
+ private const string DirectionMesToAgv = "MES_TO_AGV";
+ private const string DirectionAgvToMes = "AGV_TO_MES";
+
+ ///
+ /// MES调用临工AGV两点任务接口。
+ ///
+ 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);
+ }
+
+ ///
+ /// MES调用临工AGV三点任务接口。
+ ///
+ 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);
+ }
+
+ ///
+ /// MES调用临工AGV放行接口。
+ ///
+ 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);
+ }
+
+ ///
+ /// 处理临工AGV到达/离开回调。
+ ///
+ 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(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);
+
+ 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;
+ }
+
+ ///
+ /// 处理临工AGV任务结果回调。
+ ///
+ 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(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);
+ }
+ }
+ }
+}
diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_Models.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_Models.cs
new file mode 100644
index 0000000..db77b26
--- /dev/null
+++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_Models.cs
@@ -0,0 +1,106 @@
+using Newtonsoft.Json.Linq;
+
+namespace MisDataSaveDate
+{
+ ///
+ /// 临工AGV两点任务请求。
+ ///
+ public class LGAGV_AddTaskRequest
+ {
+ public string requestTaskId { get; set; }
+ public string startPosition { get; set; }
+ public string endPosition { get; set; }
+ public string materialCode { get; set; }
+ }
+
+ ///
+ /// 临工AGV三点任务请求。
+ ///
+ 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; }
+ }
+
+ ///
+ /// 临工AGV放行请求。
+ ///
+ 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;
+ }
+
+ ///
+ /// 临工AGV到达/离开回调。
+ ///
+ 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; }
+ }
+
+ ///
+ /// 临工AGV任务执行结果回调。
+ ///
+ 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; }
+ }
+
+ ///
+ /// 返回给临工AGV的通用响应。
+ ///
+ 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
+ };
+ }
+ }
+
+ ///
+ /// MES调用临工AGV接口后的内部结果。
+ ///
+ 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; }
+ }
+}
diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs
index e2c2be2..17a652b 100644
--- a/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs
+++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs
@@ -40,5 +40,35 @@ namespace MisDataSaveDate
};
}
+ ///
+ /// 临工AGV到达/离开状态回调接口。
+ ///
+ /// 临工AGV状态回调数据
+ /// 处理结果
+ [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")
+ };
+ }
+
+ ///
+ /// 临工AGV任务结果回调接口。
+ ///
+ /// 临工AGV任务结果数据
+ /// 处理结果
+ [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")
+ };
+ }
+
}
}
diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/WEBController.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/WEBController.cs
index ba93382..b640c57 100644
--- a/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/WEBController.cs
+++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/WEBController.cs
@@ -99,6 +99,36 @@ namespace MisDataSaveDate
};
}
+ ///
+ /// 临工AGV网页按钮调度接口。
+ ///
+ /// 调度请求数据
+ /// 处理结果
+ [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")
+ };
+ }
+
+ ///
+ /// 临工AGV网页按钮放行接口。
+ ///
+ /// 放行请求数据
+ /// 处理结果
+ [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")
+ };
+ }
+
///
/// 批量读取PLC点位值接口
/// 前端传递TagTypeCodeID数组和工位号,返回对应点位的值
@@ -131,4 +161,4 @@ namespace MisDataSaveDate
};
}
}
-}
\ No newline at end of file
+}
diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/FactoryMES/CALL_Inerface_DataHandle.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/FactoryMES/CALL_Inerface_DataHandle.cs
index e03c662..a7cfd56 100644
--- a/Interface_WebAPI/SlMesDbIterface/WebAPI/FactoryMES/CALL_Inerface_DataHandle.cs
+++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/FactoryMES/CALL_Inerface_DataHandle.cs
@@ -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;
+ }
+
///
/// 开工(工序)
///
@@ -32,10 +43,8 @@ namespace WebApi
///
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;
}
@@ -101,10 +110,8 @@ namespace WebApi
///
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;
}
diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_BusinessLogic.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_BusinessLogic.cs
new file mode 100644
index 0000000..dddc90d
--- /dev/null
+++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_BusinessLogic.cs
@@ -0,0 +1,319 @@
+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
+{
+ ///
+ /// 临工AGV网页按钮业务处理。
+ ///
+ public class LGWEB_BusinessLogic
+ {
+ ///
+ /// 网页按钮下发临工AGV搬运任务。
+ ///
+ public static string WEB_DispatchAGV(string url, [FromBody] JObject jobj)
+ {
+ var result = new MsgResHeader