diff --git a/Common/09MesDataFunction/MesDataFunction/13MIS_FuntionSaveData/Funtion.MesRead.cs b/Common/09MesDataFunction/MesDataFunction/13MIS_FuntionSaveData/Funtion.MesRead.cs index 3866226..2acbf0e 100644 --- a/Common/09MesDataFunction/MesDataFunction/13MIS_FuntionSaveData/Funtion.MesRead.cs +++ b/Common/09MesDataFunction/MesDataFunction/13MIS_FuntionSaveData/Funtion.MesRead.cs @@ -158,8 +158,6 @@ namespace MisDataSaveDateMesRead //保存质量数 BaseData_tagTable_QualityData_B5A_IndexInsert(engineID, tagID, engineType, engineTypeID, opName, qualityMask, partPallet, out id_tagCF); BaseData_tagTable_QualityData_B5A_Insert(id_tagCF, engineTypeID, engineID, opName, dt_WWW, isCheck); - //保存质量数据到 接口表 - MisDataFun.SaveQualityInterfaceData(opName, engineID); } catch (Exception err) { 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/AGV举升回调_现场总装.sql b/DatabaseScripts/AGV举升回调_现场总装.sql deleted file mode 100644 index 0a24d11..0000000 --- a/DatabaseScripts/AGV举升回调_现场总装.sql +++ /dev/null @@ -1,95 +0,0 @@ --- 现场总装数据库:MESBasicDB_XD_ZZ --- 用途:支持 AGV lower/raise 回调与 PLC 允许下降/举升放行查询。 --- 说明:请在目标库手工执行。本脚本不直接修改 AGV_光栅请求记录 表结构。 - -SET NOCOUNT ON; -GO - --- 1. 增加变量类型代码。500/501 是 MES 写 PLC 请求位,550/551 是 PLC 允许位。 -IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_基本变量变量类型代码] WHERE [变量类型代码] = 500) -BEGIN - INSERT INTO [dbo].[MES_基本变量变量类型代码] - ([变量类型], [TagTypeDataType], [TagName], [变量类型代码], [TagTypeChange], [MesTagTypeChange], [WebTagTypeChange], [信号点名称], [变量类型名称]) - VALUES - (N'X', 11, N'AGV请求下降', 500, 1, 0, 1, N'AGV请求下降', N'AGV请求下降'); -END - -IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_基本变量变量类型代码] WHERE [变量类型代码] = 501) -BEGIN - INSERT INTO [dbo].[MES_基本变量变量类型代码] - ([变量类型], [TagTypeDataType], [TagName], [变量类型代码], [TagTypeChange], [MesTagTypeChange], [WebTagTypeChange], [信号点名称], [变量类型名称]) - VALUES - (N'X', 11, N'AGV请求举升', 501, 1, 0, 1, N'AGV请求举升', N'AGV请求举升'); -END - -IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_基本变量变量类型代码] WHERE [变量类型代码] = 550) -BEGIN - INSERT INTO [dbo].[MES_基本变量变量类型代码] - ([变量类型], [TagTypeDataType], [TagName], [变量类型代码], [TagTypeChange], [MesTagTypeChange], [WebTagTypeChange], [信号点名称], [变量类型名称]) - VALUES - (N'X', 11, N'允许AGV下降', 550, 1, 0, 1, N'允许AGV下降', N'允许AGV下降'); -END - -IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_基本变量变量类型代码] WHERE [变量类型代码] = 551) -BEGIN - INSERT INTO [dbo].[MES_基本变量变量类型代码] - ([变量类型], [TagTypeDataType], [TagName], [变量类型代码], [TagTypeChange], [MesTagTypeChange], [WebTagTypeChange], [信号点名称], [变量类型名称]) - VALUES - (N'X', 11, N'允许AGV举升', 551, 1, 0, 1, N'允许AGV举升', N'允许AGV举升'); -END -GO - --- 2. 扩展 AGV continueTask 放行查询。 --- apply/release 保持原有 XD_库位Moby 查询。 --- lower/raise 从 AGV_光栅请求记录 取最新未允许或最近请求,避免改动 XD_库位Moby 与历史表列顺序。 -ALTER PROCEDURE [dbo].[AGV_允许进入离开_查询] - @opName nvarchar(50) = 'AC0901-02', - @engineID nvarchar(50) = '0', - @type nvarchar(50) = 'apply' -AS -BEGIN - SET NOCOUNT ON; - - IF (@type = 'apply') - BEGIN - SELECT [进入req] AS reqCode, [进入task] AS taskCode - FROM [dbo].[XD_库位Moby] - WHERE [库位号] = @opName - AND [AGV请求进入时间] IS NOT NULL; - END - - IF (@type = 'release') - BEGIN - SELECT [离开req] AS reqCode, [离开task] AS taskCode - FROM [dbo].[XD_库位Moby] - WHERE [库位号] = @opName - AND [AGV请求离开时间] IS NOT NULL; - END - - IF (@type = 'lower') - BEGIN - SELECT TOP 1 [reqCode], [taskCode] - FROM [dbo].[AGV_光栅请求记录] - WHERE [method] = 'lower' - AND ( - [currentPositionCode] = @opName - OR [currentPositionCode] LIKE @opName + N'[_]%' - OR [wbCode] = @opName - ) - ORDER BY ISNULL([是否允许], 0) ASC, [创建时间] DESC, [ID] DESC; - END - - IF (@type = 'raise') - BEGIN - SELECT TOP 1 [reqCode], [taskCode] - FROM [dbo].[AGV_光栅请求记录] - WHERE [method] = 'raise' - AND ( - [currentPositionCode] = @opName - OR [currentPositionCode] LIKE @opName + N'[_]%' - OR [wbCode] = @opName - ) - ORDER BY ISNULL([是否允许], 0) ASC, [创建时间] DESC, [ID] DESC; - END -END -GO diff --git a/DatabaseScripts/TCS_AGV接口仿真服务.mjs b/DatabaseScripts/TCS_AGV接口仿真服务.mjs new file mode 100644 index 0000000..799e096 --- /dev/null +++ b/DatabaseScripts/TCS_AGV接口仿真服务.mjs @@ -0,0 +1,115 @@ +import http from 'node:http' + +const host = '127.0.0.1' +const port = Number(process.env.TCS_MOCK_PORT || 18080) +const tasks = new Map() + +const sendJson = (response, payload, statusCode = 200) => { + response.writeHead(statusCode, { 'Content-Type': 'application/json; charset=utf-8' }) + response.end(JSON.stringify(payload)) +} + +const success = result => ({ + success: true, + message: '仿真接口调用成功', + code: 200, + result, + timestamp: Date.now() +}) + +const readBody = request => new Promise((resolve, reject) => { + let body = '' + request.setEncoding('utf8') + request.on('data', chunk => { body += chunk }) + request.on('end', () => { + if (!body) { + resolve({}) + return + } + try { + resolve(JSON.parse(body)) + } catch (error) { + reject(error) + } + }) + request.on('error', reject) +}) + +const server = http.createServer(async (request, response) => { + const url = new URL(request.url, `http://${host}:${port}`) + try { + if (request.method === 'POST' && url.pathname === '/api/createExternalBusinessTask') { + const body = await readBody(request) + tasks.set(body.externalCode, body) + console.log('CREATE', JSON.stringify(body)) + sendJson(response, success({ externalCode: body.externalCode })) + return + } + + if (request.method === 'GET' && url.pathname === '/api/getExternalBusinessTaskStatus') { + const externalCode = url.searchParams.get('externalCode') || '' + sendJson(response, success([{ + externalCode, + status: '1', + ip: '10.146.79.9', + type: tasks.get(externalCode)?.type || 'nav_action_program', + beginTime: '2026-07-13 14:40:00', + endTime: '', + remark: '仿真状态同步' + }])) + return + } + + if (request.method === 'GET' && url.pathname === '/api/getMcrInfo') { + sendJson(response, success([{ + name: 'AGV-01', + ip: '10.146.79.9', + speed: 0, + power: 80, + autoCharging: '1', + chargingThreshold: 20, + status: '0', + currentPos: 'S000214', + control: '1', + CameraInfo: '' + }])) + return + } + + const successfulGetRoutes = new Set([ + '/api/cancelExternalBusinessTask', + '/api/stopExternalBusinessTask', + '/api/reset', + '/api/stopNow' + ]) + if (request.method === 'GET' && successfulGetRoutes.has(url.pathname)) { + console.log('GET', url.pathname, url.search) + sendJson(response, success('成功')) + return + } + + sendJson(response, { + success: false, + message: `未实现的仿真路由:${request.method} ${url.pathname}`, + code: 500, + result: null, + timestamp: Date.now() + }, 404) + } catch (error) { + sendJson(response, { + success: false, + message: error.message, + code: 500, + result: null, + timestamp: Date.now() + }, 500) + } +}) + +server.listen(port, host, () => { + console.log(`TCS AGV mock listening on http://${host}:${port}`) +}) + +const close = () => server.close(() => process.exit(0)) +process.on('SIGINT', close) +process.on('SIGTERM', close) diff --git a/DatabaseScripts/XD_TCS_AGV插拔任务.sql b/DatabaseScripts/XD_TCS_AGV插拔任务.sql new file mode 100644 index 0000000..59bfcea --- /dev/null +++ b/DatabaseScripts/XD_TCS_AGV插拔任务.sql @@ -0,0 +1,711 @@ +SET NOCOUNT ON +GO + +IF OBJECT_ID(N'dbo.XD_TCS_AGV_配置', N'U') IS NULL +BEGIN + CREATE TABLE dbo.XD_TCS_AGV_配置 + ( + 配置键 nvarchar(50) NOT NULL CONSTRAINT PK_XD_TCS_AGV_配置 PRIMARY KEY, + 配置值 nvarchar(500) NOT NULL, + 配置说明 nvarchar(200) NULL, + 是否启用 bit NOT NULL CONSTRAINT DF_XD_TCS_AGV_配置_是否启用 DEFAULT(1), + 操作时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_配置_操作时间 DEFAULT(GETDATE()) + ) +END +GO + +IF OBJECT_ID(N'dbo.XD_TCS_AGV_点位配置', N'U') IS NULL +BEGIN + CREATE TABLE dbo.XD_TCS_AGV_点位配置 + ( + ID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_XD_TCS_AGV_点位配置 PRIMARY KEY, + 产线代码 nvarchar(20) NOT NULL, + MES工位号 nvarchar(50) NOT NULL, + 现场位置 nvarchar(50) NOT NULL, + WorkStation nvarchar(50) NOT NULL, + 插XSDProgramName nvarchar(100) NOT NULL, + 插XSEProgramName nvarchar(100) NOT NULL, + 拔XSDProgramName nvarchar(100) NOT NULL, + 拔XSEProgramName nvarchar(100) NOT NULL, + 排序 int NOT NULL, + 是否启用 bit NOT NULL CONSTRAINT DF_XD_TCS_AGV_点位配置_是否启用 DEFAULT(1), + 操作时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_点位配置_操作时间 DEFAULT(GETDATE()), + CONSTRAINT UK_XD_TCS_AGV_点位配置_MES工位号 UNIQUE(MES工位号), + CONSTRAINT UK_XD_TCS_AGV_点位配置_WorkStation UNIQUE(WorkStation) + ) +END +GO + +IF OBJECT_ID(N'dbo.XD_TCS_AGV_型号动作映射', N'U') IS NULL +BEGIN + CREATE TABLE dbo.XD_TCS_AGV_型号动作映射 + ( + ID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_XD_TCS_AGV_型号动作映射 PRIMARY KEY, + 产线代码 nvarchar(20) NOT NULL, + 产品型号 nvarchar(100) NOT NULL, + 任务动作 nvarchar(10) NOT NULL, + 执行XSD bit NOT NULL, + 执行XSE bit NOT NULL, + 是否启用 bit NOT NULL CONSTRAINT DF_XD_TCS_AGV_型号动作映射_是否启用 DEFAULT(1), + 操作时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_型号动作映射_操作时间 DEFAULT(GETDATE()), + CONSTRAINT UK_XD_TCS_AGV_型号动作映射 UNIQUE(产线代码,产品型号,任务动作), + CONSTRAINT CK_XD_TCS_AGV_型号动作映射_动作 CHECK(任务动作 IN(N'插',N'拔')), + CONSTRAINT CK_XD_TCS_AGV_型号动作映射_组合 CHECK(执行XSD=1 OR 执行XSE=1) + ) +END +GO + +IF OBJECT_ID(N'dbo.XD_TCS_AGV_任务', N'U') IS NULL +BEGIN + CREATE TABLE dbo.XD_TCS_AGV_任务 + ( + ID bigint IDENTITY(1,1) NOT NULL CONSTRAINT PK_XD_TCS_AGV_任务 PRIMARY KEY, + 外部任务编号 nvarchar(100) NOT NULL, + 原任务编号 nvarchar(100) NULL, + MES工位号 nvarchar(50) NOT NULL, + 现场位置 nvarchar(50) NULL, + TCS站点 nvarchar(50) NULL, + 任务动作 nvarchar(20) NOT NULL, + 产品型号 nvarchar(100) NULL, + 动作组合 nvarchar(20) NULL, + ProgramName nvarchar(100) NULL, + 任务类型 nvarchar(50) NOT NULL, + 参数 nvarchar(max) NOT NULL, + 优先级 int NOT NULL, + 机器人组 nvarchar(50) NULL, + 机器人IP nvarchar(50) NULL, + 来源 nvarchar(20) NOT NULL, + 操作人 nvarchar(50) NULL, + 任务状态 int NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_任务状态 DEFAULT(0), + 状态说明 nvarchar(50) NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_状态说明 DEFAULT(N'未开始'), + 开始时间 nvarchar(50) NULL, + 结束时间 nvarchar(50) NULL, + TCS备注 nvarchar(1000) NULL, + 请求报文 nvarchar(max) NULL, + 响应报文 nvarchar(max) NULL, + 错误信息 nvarchar(2000) NULL, + 是否通知PLC bit NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_是否通知PLC DEFAULT(0), + PLC已通知 bit NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_PLC已通知 DEFAULT(0), + 处理状态 int NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_处理状态 DEFAULT(0), + 已复位 bit NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_已复位 DEFAULT(0), + 处理人 nvarchar(50) NULL, + 处理时间 datetime NULL, + 处理说明 nvarchar(1000) NULL, + 创建时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_创建时间 DEFAULT(GETDATE()), + 更新时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_任务_更新时间 DEFAULT(GETDATE()), + CONSTRAINT UK_XD_TCS_AGV_任务_外部任务编号 UNIQUE(外部任务编号), + CONSTRAINT CK_XD_TCS_AGV_任务_状态 CHECK(任务状态 IN (0,1,2,3,4,5)) + ) + + CREATE INDEX IX_XD_TCS_AGV_任务_状态时间 + ON dbo.XD_TCS_AGV_任务(任务状态, 创建时间 DESC) + CREATE INDEX IX_XD_TCS_AGV_任务_工位时间 + ON dbo.XD_TCS_AGV_任务(MES工位号, 创建时间 DESC) +END +GO + +IF COL_LENGTH(N'dbo.XD_TCS_AGV_任务', N'产品型号') IS NULL + ALTER TABLE dbo.XD_TCS_AGV_任务 ADD 产品型号 nvarchar(100) NULL +GO + +IF COL_LENGTH(N'dbo.XD_TCS_AGV_任务', N'动作组合') IS NULL + ALTER TABLE dbo.XD_TCS_AGV_任务 ADD 动作组合 nvarchar(20) NULL +GO + +IF COL_LENGTH(N'dbo.XD_TCS_AGV_任务', N'已复位') IS NULL +BEGIN + ALTER TABLE dbo.XD_TCS_AGV_任务 ADD 已复位 bit NOT NULL + CONSTRAINT DF_XD_TCS_AGV_任务_已复位 DEFAULT(0) +END +GO + +IF EXISTS +( + SELECT 1 FROM sys.check_constraints + WHERE parent_object_id=OBJECT_ID(N'dbo.XD_TCS_AGV_任务') + AND name=N'CK_XD_TCS_AGV_任务_状态' +) + ALTER TABLE dbo.XD_TCS_AGV_任务 DROP CONSTRAINT CK_XD_TCS_AGV_任务_状态 +GO + +ALTER TABLE dbo.XD_TCS_AGV_任务 ADD CONSTRAINT CK_XD_TCS_AGV_任务_状态 + CHECK(任务状态 IN (0,1,2,3,4,5)) +GO + +IF OBJECT_ID(N'dbo.XD_TCS_AGV_位置状态', N'U') IS NULL +BEGIN + CREATE TABLE dbo.XD_TCS_AGV_位置状态 + ( + ID int NOT NULL CONSTRAINT PK_XD_TCS_AGV_位置状态 PRIMARY KEY, + 机器人IP nvarchar(50) NULL, + 当前站点 nvarchar(100) NULL, + 目标站点 nvarchar(100) NULL, + 原始报文 nvarchar(max) NULL, + 更新时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_位置状态_更新时间 DEFAULT(GETDATE()), + CONSTRAINT CK_XD_TCS_AGV_位置状态_单车 CHECK(ID = 1) + ) +END +GO + +IF OBJECT_ID(N'dbo.XD_TCS_AGV_操作记录', N'U') IS NULL +BEGIN + CREATE TABLE dbo.XD_TCS_AGV_操作记录 + ( + ID bigint IDENTITY(1,1) NOT NULL CONSTRAINT PK_XD_TCS_AGV_操作记录 PRIMARY KEY, + 外部任务编号 nvarchar(100) NULL, + MES工位号 nvarchar(50) NULL, + 操作类型 nvarchar(50) NOT NULL, + 操作人 nvarchar(50) NULL, + 请求报文 nvarchar(max) NULL, + 响应报文 nvarchar(max) NULL, + 是否成功 bit NOT NULL, + 操作结果 nvarchar(1000) NULL, + 操作时间 datetime NOT NULL CONSTRAINT DF_XD_TCS_AGV_操作记录_操作时间 DEFAULT(GETDATE()) + ) + + CREATE INDEX IX_XD_TCS_AGV_操作记录_时间 + ON dbo.XD_TCS_AGV_操作记录(操作时间 DESC) +END +GO + +DECLARE @默认配置 TABLE +( + 配置键 nvarchar(50), + 配置值 nvarchar(500), + 配置说明 nvarchar(200) +) + +INSERT INTO @默认配置 VALUES +(N'TCS_BaseUrl', N'http://10.112.111.21:11008', N'TCS调度服务地址,客户已确认'), +(N'TCS_Enabled', N'0', N'1启用真实下发,0仅允许查询配置'), +(N'McrGroup', N'G001', N'机器人组'), +(N'McrIp', N'10.146.79.9', N'客户确认的单台AGV IP'), +(N'TCS_OperatorUserId', N'BZS001', N'TCS任务状态定向推送标识'), +(N'DefaultPriority', N'1', N'默认任务优先级'), +(N'HttpTimeoutSeconds', N'15', N'TCS HTTP超时秒数') + +MERGE dbo.XD_TCS_AGV_配置 AS T +USING @默认配置 AS S ON T.配置键 = S.配置键 +WHEN NOT MATCHED THEN + INSERT(配置键,配置值,配置说明) VALUES(S.配置键,S.配置值,S.配置说明); +GO + +DECLARE @产线代码 nvarchar(20) +SELECT TOP 1 @产线代码 = 值 FROM dbo.基本配置 WHERE 参数名称 = N'产线名称' + +DECLARE @点位 TABLE +( + 产线代码 nvarchar(20), MES工位号 nvarchar(50), 现场位置 nvarchar(50), WorkStation nvarchar(50), + 插XSD nvarchar(100), 插XSE nvarchar(100), 拔XSD nvarchar(100), 拔XSE nvarchar(100), 排序 int +) + +IF @产线代码 = N'GLKG' +BEGIN + INSERT INTO @点位 VALUES + (N'GLKG',N'AC0909-01',N'GIS1',N'S000214',N'214GIS1插XSD',N'214GIS1插XSE',N'214GIS1拔XSD',N'214GIS1拔XSE',1), + (N'GLKG',N'AC0909-02',N'GIS2',N'S000215',N'215GIS2插XSD',N'215GIS2插XSE',N'215GIS2拔XSD',N'215GIS2拔XSE',2), + (N'GLKG',N'AC0909-03',N'GIS3',N'S000217',N'217GIS3插XSD',N'217GIS3插XSE',N'217GIS3拔XSD',N'217GIS3拔XSE',3), + (N'GLKG',N'AC0909-04',N'GIS4',N'S000218',N'218GIS4插XSD',N'218GIS4插XSE',N'218GIS4拔XSD',N'218GIS4拔XSE',4), + (N'GLKG',N'AC0909-05',N'GIS5',N'S000219',N'219GIS5插XSD',N'219GIS5插XSE',N'219GIS5拔XSD',N'219GIS5拔XSE',5), + (N'GLKG',N'AC0909-06',N'GIS6',N'S000220',N'220GIS6插XSD',N'220GIS6插XSE',N'220GIS6拔XSD',N'220GIS6拔XSE',6), + (N'GLKG',N'AC0909-07',N'GIS7',N'S000221',N'221GIS7插XSD',N'221GIS7插XSE',N'221GIS7拔XSD',N'221GIS7拔XSE',7), + (N'GLKG',N'AC0909-08',N'GIS8',N'S000222',N'222GIS8插XSD',N'222GIS8插XSE',N'222GIS8拔XSD',N'222GIS8拔XSE',8), + (N'GLKG',N'AC0909-09',N'GIS9',N'S000201',N'201GIS9插XSD',N'201GIS9插XSE',N'201GIS9拔XSD',N'201GIS9拔XSE',9), + (N'GLKG',N'AC0909-10',N'GIS10',N'S000202',N'202GIS10插XSD',N'202GIS10插XSE',N'202GIS10拔XSD',N'202GIS10拔XSE',10) +END +ELSE IF @产线代码 = N'DLQ' +BEGIN + INSERT INTO @点位 VALUES + (N'DLQ',N'AC0605-01',N'GCB1',N'S000225',N'225GCB1插XSD',N'225GCB1插XSE',N'225GCB1拔XSD',N'225GCB1拔XSE',1), + (N'DLQ',N'AC0605-02',N'GCB2',N'S000226',N'226GCB2插XSD',N'226GCB2插XSE',N'226GCB2拔XSD',N'226GCB2拔XSE',2), + (N'DLQ',N'AC0605-03',N'GCB3',N'S000227',N'227GCB3插XSD',N'227GCB3插XSE',N'227GCB3拔XSD',N'227GCB3拔XSE',3), + (N'DLQ',N'AC0605-04',N'GCB4',N'S000228',N'228GCB4插XSD',N'228GCB4插XSE',N'228GCB4拔XSD',N'228GCB4拔XSE',4) +END + +MERGE dbo.XD_TCS_AGV_点位配置 AS T +USING @点位 AS S ON T.MES工位号 = S.MES工位号 +WHEN MATCHED THEN UPDATE SET + T.产线代码=S.产线代码,T.现场位置=S.现场位置,T.WorkStation=S.WorkStation, + T.插XSDProgramName=S.插XSD,T.插XSEProgramName=S.插XSE, + T.拔XSDProgramName=S.拔XSD,T.拔XSEProgramName=S.拔XSE, + T.排序=S.排序,T.是否启用=1,T.操作时间=GETDATE() +WHEN NOT MATCHED THEN INSERT + (产线代码,MES工位号,现场位置,WorkStation,插XSDProgramName,插XSEProgramName,拔XSDProgramName,拔XSEProgramName,排序) + VALUES(S.产线代码,S.MES工位号,S.现场位置,S.WorkStation,S.插XSD,S.插XSE,S.拔XSD,S.拔XSE,S.排序); +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_配置_获取 +AS +BEGIN + SET NOCOUNT ON + SELECT + TCS_BaseUrl = MAX(CASE WHEN 配置键=N'TCS_BaseUrl' THEN 配置值 END), + TCS_Enabled = MAX(CASE WHEN 配置键=N'TCS_Enabled' THEN 配置值 END), + McrGroup = MAX(CASE WHEN 配置键=N'McrGroup' THEN 配置值 END), + McrIp = MAX(CASE WHEN 配置键=N'McrIp' THEN 配置值 END), + TCS_OperatorUserId = MAX(CASE WHEN 配置键=N'TCS_OperatorUserId' THEN 配置值 END), + DefaultPriority = MAX(CASE WHEN 配置键=N'DefaultPriority' THEN 配置值 END), + HttpTimeoutSeconds = MAX(CASE WHEN 配置键=N'HttpTimeoutSeconds' THEN 配置值 END) + FROM dbo.XD_TCS_AGV_配置 WHERE 是否启用=1 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_点位配置_查询 +@MES工位号 nvarchar(50) = N'' +AS +BEGIN + SET NOCOUNT ON + SELECT * FROM dbo.XD_TCS_AGV_点位配置 + WHERE 是否启用=1 AND (@MES工位号=N'' OR MES工位号=@MES工位号) + ORDER BY 排序 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_型号动作映射_查询 +@产线代码 nvarchar(20), +@产品型号 nvarchar(100), +@任务动作 nvarchar(10) +AS +BEGIN + SET NOCOUNT ON + SELECT TOP 1 ID,产线代码,产品型号,任务动作,执行XSD,执行XSE, + CASE WHEN 执行XSD=1 AND 执行XSE=1 THEN N'XSD+XSE' + WHEN 执行XSD=1 THEN N'XSD' ELSE N'XSE' END 动作组合 + FROM dbo.XD_TCS_AGV_型号动作映射 + WHERE 产线代码=@产线代码 AND 产品型号=@产品型号 + AND 任务动作=@任务动作 AND 是否启用=1 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_库位产品_查询 +@MES工位号 nvarchar(50) +AS +BEGIN + SET NOCOUNT ON + SELECT TOP 1 产品编号,产品型号 + FROM dbo.XD_磨合_状态 + WHERE 库位号=@MES工位号 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_创建 +@外部任务编号 nvarchar(100), +@原任务编号 nvarchar(100)=N'', +@MES工位号 nvarchar(50), +@任务动作 nvarchar(20), +@产品型号 nvarchar(100)=N'', +@动作组合 nvarchar(20)=N'', +@ProgramName nvarchar(100)=N'', +@任务类型 nvarchar(50), +@参数 nvarchar(max), +@优先级 int, +@机器人组 nvarchar(50)=N'', +@机器人IP nvarchar(50)=N'', +@来源 nvarchar(20), +@操作人 nvarchar(50)=N'', +@是否通知PLC bit=0 +AS +BEGIN + SET NOCOUNT ON + SET XACT_ABORT ON + BEGIN TRAN + + IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_点位配置 WHERE MES工位号=@MES工位号 AND 是否启用=1) + BEGIN + ROLLBACK + SELECT 2 result,N'工位未配置TCS点位' msg + RETURN + END + + IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号) + BEGIN + ROLLBACK + SELECT 2 result,N'外部任务编号已存在' msg + RETURN + END + + IF ISNULL(@原任务编号,N'')<>N'' + BEGIN + DECLARE @原任务工位 nvarchar(50),@原任务状态 int,@原处理状态 int,@原任务已复位 bit + SELECT @原任务工位=MES工位号,@原任务状态=任务状态, + @原处理状态=处理状态,@原任务已复位=已复位 + FROM dbo.XD_TCS_AGV_任务 WITH(UPDLOCK,HOLDLOCK) + WHERE 外部任务编号=@原任务编号 + + IF @原任务工位 IS NULL + BEGIN + ROLLBACK + SELECT 2 result,N'原失败任务不存在' msg + RETURN + END + IF @原任务状态 NOT IN(4,5) OR ISNULL(@原处理状态,0)<>0 + BEGIN + ROLLBACK + SELECT 2 result,N'原任务不是待处理的失败任务' msg + RETURN + END + IF ISNULL(@原任务已复位,0)<>1 + BEGIN + ROLLBACK + SELECT 2 result,N'请先复位原失败任务对应的移动机器人' msg + RETURN + END + IF @原任务工位<>@MES工位号 + BEGIN + ROLLBACK + SELECT 2 result,N'恢复任务工位必须与原失败任务一致' msg + RETURN + END + END + + -- MES允许各工位独立下发任务,排队与执行顺序由TCS调度。 + + DECLARE @现场位置 nvarchar(50),@TCS站点 nvarchar(50) + SELECT @现场位置=现场位置,@TCS站点=WorkStation + FROM dbo.XD_TCS_AGV_点位配置 WHERE MES工位号=@MES工位号 AND 是否启用=1 + + INSERT INTO dbo.XD_TCS_AGV_任务 + (外部任务编号,原任务编号,MES工位号,现场位置,TCS站点,任务动作,产品型号,动作组合,ProgramName,任务类型,参数, + 优先级,机器人组,机器人IP,来源,操作人,是否通知PLC) + VALUES + (@外部任务编号,NULLIF(@原任务编号,N''),@MES工位号,@现场位置,@TCS站点,@任务动作,NULLIF(@产品型号,N''),NULLIF(@动作组合,N''),NULLIF(@ProgramName,N''), + @任务类型,@参数,@优先级,@机器人组,@机器人IP,@来源,@操作人,@是否通知PLC) + + DECLARE @ID bigint=SCOPE_IDENTITY() + COMMIT + SELECT 1 result,N'任务已创建' msg,@ID ID,@外部任务编号 外部任务编号 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_下发结果更新 +@外部任务编号 nvarchar(100), +@请求报文 nvarchar(max)=N'', +@响应报文 nvarchar(max)=N'', +@是否成功 bit, +@错误信息 nvarchar(2000)=N'' +AS +BEGIN + SET NOCOUNT ON + UPDATE dbo.XD_TCS_AGV_任务 SET + 请求报文=@请求报文,响应报文=@响应报文, + 任务状态=CASE WHEN @是否成功=1 THEN 0 ELSE 4 END, + 状态说明=CASE WHEN @是否成功=1 THEN N'未开始' ELSE N'任务错误' END, + 错误信息=NULLIF(@错误信息,N''),更新时间=GETDATE() + WHERE 外部任务编号=@外部任务编号 + + SELECT CASE WHEN @@ROWCOUNT=1 THEN 1 ELSE 2 END result +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_状态更新 +@外部任务编号 nvarchar(100), +@任务状态 int, +@机器人IP nvarchar(50)=N'', +@任务类型 nvarchar(50)=N'', +@开始时间 nvarchar(50)=N'', +@结束时间 nvarchar(50)=N'', +@备注 nvarchar(1000)=N'' +AS +BEGIN + SET NOCOUNT ON + IF @任务状态 NOT IN(0,1,2,3,4,5) + BEGIN + SELECT 2 result,N'任务状态不正确' msg + RETURN + END + + IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号) + BEGIN + SELECT 2 result,N'外部任务编号不存在' msg + RETURN + END + + DECLARE @原状态 int + SELECT @原状态=任务状态 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 + + IF (@原状态 IN(2,3,5) AND @任务状态<>@原状态) + OR (@原状态=4 AND @任务状态 NOT IN(4,5)) + BEGIN + SELECT 1 result,N'已忽略结束状态变更' msg,MES工位号,任务动作,是否通知PLC,PLC已通知 + FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 + RETURN + END + + UPDATE dbo.XD_TCS_AGV_任务 SET + 任务状态=@任务状态, + 状态说明=CASE @任务状态 WHEN 0 THEN N'未开始' WHEN 1 THEN N'进行中' WHEN 2 THEN N'已完成' WHEN 3 THEN N'已取消' WHEN 4 THEN N'任务错误' ELSE N'任务错误(已处理)' END, + 机器人IP=CASE WHEN @机器人IP=N'' THEN 机器人IP ELSE @机器人IP END, + 任务类型=CASE WHEN @任务类型=N'' THEN 任务类型 ELSE @任务类型 END, + 开始时间=CASE WHEN @开始时间=N'' THEN 开始时间 ELSE @开始时间 END, + 结束时间=CASE WHEN @结束时间=N'' THEN 结束时间 ELSE @结束时间 END, + TCS备注=NULLIF(@备注,N''), + 错误信息=CASE WHEN @任务状态=4 THEN NULLIF(@备注,N'') ELSE 错误信息 END, + 已复位=CASE WHEN @任务状态=5 THEN 1 ELSE 已复位 END, + 更新时间=GETDATE() + WHERE 外部任务编号=@外部任务编号 + + SELECT 1 result,N'状态已更新' msg,MES工位号,任务动作,是否通知PLC,PLC已通知 + FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_PLC通知完成 +@外部任务编号 nvarchar(100) +AS +BEGIN + SET NOCOUNT ON + UPDATE dbo.XD_TCS_AGV_任务 SET PLC已通知=1,更新时间=GETDATE() + WHERE 外部任务编号=@外部任务编号 AND 任务状态=2 + SELECT CASE WHEN @@ROWCOUNT=1 THEN 1 ELSE 2 END result +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_获取 +@外部任务编号 nvarchar(100) +AS +BEGIN + SET NOCOUNT ON + SELECT * FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_人工处理 +@外部任务编号 nvarchar(100), +@处理人 nvarchar(50)=N'', +@处理说明 nvarchar(1000)=N'' +AS +BEGIN + SET NOCOUNT ON + IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 AND 任务状态 IN(4,5)) + BEGIN + SELECT 2 result,N'仅任务错误状态可以标记人工处理' msg + RETURN + END + + + IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 AND 已复位=1) + BEGIN + SELECT 2 result,N'请先复位移动机器人再完成人工处理' msg + RETURN + END + + UPDATE dbo.XD_TCS_AGV_任务 SET 处理状态=1,处理人=@处理人,处理时间=GETDATE(),处理说明=@处理说明,更新时间=GETDATE() + WHERE 外部任务编号=@外部任务编号 + SELECT 1 result,N'已标记人工处理' msg +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_复位标记 +@外部任务编号 nvarchar(100) +AS +BEGIN + SET NOCOUNT ON + UPDATE dbo.XD_TCS_AGV_任务 SET 已复位=1,更新时间=GETDATE() + WHERE 外部任务编号=@外部任务编号 AND 任务状态 IN(4,5) + SELECT CASE WHEN @@ROWCOUNT=1 THEN 1 ELSE 2 END result, + CASE WHEN @@ROWCOUNT=1 THEN N'复位状态已记录' ELSE N'未找到对应失败任务' END msg +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_本地状态设置 +@外部任务编号 nvarchar(100), +@任务状态 int, +@状态说明 nvarchar(50), +@错误信息 nvarchar(2000)=N'' +AS +BEGIN + SET NOCOUNT ON + UPDATE dbo.XD_TCS_AGV_任务 SET 任务状态=@任务状态,状态说明=@状态说明, + 错误信息=NULLIF(@错误信息,N''),更新时间=GETDATE() + WHERE 外部任务编号=@外部任务编号 + SELECT CASE WHEN @@ROWCOUNT=1 THEN 1 ELSE 2 END result +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_分页查询 +@开始时间 nvarchar(50)=N'', +@结束时间 nvarchar(50)=N'', +@MES工位号 nvarchar(50)=N'', +@外部任务编号 nvarchar(100)=N'', +@任务动作 nvarchar(20)=N'', +@任务状态 nvarchar(10)=N'', +@来源 nvarchar(20)=N'', +@PageCurrent int=1, +@PageSize int=20, +@PageCount int output, +@ItemCount int output +AS +BEGIN + SET NOCOUNT ON + DECLARE @where nvarchar(2000)=N'1=1' + IF @开始时间<>N'' SET @where+=N' AND 创建时间>='''+REPLACE(@开始时间,'''','''''')+N'''' + IF @结束时间<>N'' SET @where+=N' AND 创建时间<='''+REPLACE(@结束时间,'''','''''')+N'''' + IF @MES工位号<>N'' SET @where+=N' AND MES工位号='''+REPLACE(@MES工位号,'''','''''')+N'''' + IF @外部任务编号<>N'' SET @where+=N' AND 外部任务编号 LIKE ''%'+REPLACE(@外部任务编号,'''','''''')+N'%''' + IF @任务动作<>N'' SET @where+=N' AND 任务动作='''+REPLACE(@任务动作,'''','''''')+N'''' + IF @任务状态<>N'' SET @where+=N' AND 任务状态='+CONVERT(nvarchar(10),CONVERT(int,@任务状态)) + IF @来源<>N'' SET @where+=N' AND 来源='''+REPLACE(@来源,'''','''''')+N'''' + + EXEC sp_xt_pagesplit N'XD_TCS_AGV_任务',N'ID',@where, + N'ID,外部任务编号,原任务编号,MES工位号,现场位置,TCS站点,任务动作,产品型号,动作组合,ProgramName,任务类型,优先级,机器人组,机器人IP,来源,操作人,任务状态,状态说明,开始时间,结束时间,TCS备注,错误信息,是否通知PLC,PLC已通知,处理状态,已复位,处理人,处理时间,处理说明,创建时间,更新时间', + N'ID DESC',@PageCurrent,@PageSize,@PageCount output,@ItemCount output +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_详情查询 +@外部任务编号 nvarchar(100) +AS +BEGIN + SET NOCOUNT ON + SELECT * FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@外部任务编号 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_当前查询 +AS +BEGIN + SET NOCOUNT ON + SELECT TOP 1 * FROM dbo.XD_TCS_AGV_任务 + WHERE 任务状态=1 + ORDER BY 更新时间 DESC,ID DESC +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_任务_概览查询 +AS +BEGIN + SET NOCOUNT ON + SELECT + ISNULL(SUM(CASE WHEN 任务状态=0 THEN 1 ELSE 0 END),0) 待执行数量, + ISNULL(SUM(CASE WHEN 任务状态=1 THEN 1 ELSE 0 END),0) 进行中数量, + ISNULL(SUM(CASE WHEN 任务状态 IN(4,5) AND 处理状态=0 THEN 1 ELSE 0 END),0) 失败待处理数量 + FROM dbo.XD_TCS_AGV_任务 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_工位日志_分页查询 +@MES工位号 nvarchar(50)=N'', +@日志类型 nvarchar(50)=N'', +@日志文本 nvarchar(200)=N'', +@开始时间 nvarchar(50)=N'', +@结束时间 nvarchar(50)=N'', +@PageCurrent int=1, +@PageSize int=20, +@PageCount int OUTPUT, +@ItemCount int OUTPUT +AS +BEGIN + SET NOCOUNT ON + + IF ISNULL(@PageCurrent,0)<1 SET @PageCurrent=1 + IF ISNULL(@PageSize,0)<1 SET @PageSize=20 + + DECLARE @开始 datetime=TRY_CONVERT(datetime,NULLIF(@开始时间,N'')) + DECLARE @结束 datetime=TRY_CONVERT(datetime,NULLIF(@结束时间,N'')) + + SELECT @ItemCount=COUNT(1) + FROM dbo.MES_系统日志 L + WHERE EXISTS + ( + SELECT 1 FROM dbo.XD_TCS_AGV_点位配置 P + WHERE P.MES工位号=L.工位号 AND P.是否启用=1 + ) + AND (@MES工位号=N'' OR L.工位号=@MES工位号) + AND (@日志类型=N'' OR L.日志类型=@日志类型) + AND (@日志文本=N'' OR L.日志文本 LIKE N'%'+@日志文本+N'%') + AND (@开始 IS NULL OR L.操作时间>=@开始) + AND (@结束 IS NULL OR L.操作时间<=@结束) + + SET @PageCount=CASE WHEN @ItemCount=0 THEN 0 ELSE CEILING(@ItemCount*1.0/@PageSize) END + + SELECT L.ID,L.工位号,L.日志类型,L.日志文本,L.操作时间 + FROM dbo.MES_系统日志 L + WHERE EXISTS + ( + SELECT 1 FROM dbo.XD_TCS_AGV_点位配置 P + WHERE P.MES工位号=L.工位号 AND P.是否启用=1 + ) + AND (@MES工位号=N'' OR L.工位号=@MES工位号) + AND (@日志类型=N'' OR L.日志类型=@日志类型) + AND (@日志文本=N'' OR L.日志文本 LIKE N'%'+@日志文本+N'%') + AND (@开始 IS NULL OR L.操作时间>=@开始) + AND (@结束 IS NULL OR L.操作时间<=@结束) + ORDER BY L.操作时间 DESC,L.ID DESC + OFFSET (@PageCurrent-1)*@PageSize ROWS FETCH NEXT @PageSize ROWS ONLY +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_位置_更新 +@机器人IP nvarchar(50)=N'', +@当前站点 nvarchar(100)=N'', +@目标站点 nvarchar(100)=N'', +@原始报文 nvarchar(max)=N'' +AS +BEGIN + SET NOCOUNT ON + IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_位置状态 WHERE ID=1) + UPDATE dbo.XD_TCS_AGV_位置状态 SET 机器人IP=@机器人IP,当前站点=@当前站点,目标站点=@目标站点,原始报文=@原始报文,更新时间=GETDATE() WHERE ID=1 + ELSE + INSERT INTO dbo.XD_TCS_AGV_位置状态(ID,机器人IP,当前站点,目标站点,原始报文) VALUES(1,@机器人IP,@当前站点,@目标站点,@原始报文) + SELECT 1 result +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_位置_查询 +AS +BEGIN + SET NOCOUNT ON + SELECT * FROM dbo.XD_TCS_AGV_位置状态 WHERE ID=1 +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_操作记录_增加 +@外部任务编号 nvarchar(100)=N'', +@MES工位号 nvarchar(50)=N'', +@操作类型 nvarchar(50), +@操作人 nvarchar(50)=N'', +@请求报文 nvarchar(max)=N'', +@响应报文 nvarchar(max)=N'', +@是否成功 bit, +@操作结果 nvarchar(1000)=N'' +AS +BEGIN + SET NOCOUNT ON + INSERT INTO dbo.XD_TCS_AGV_操作记录(外部任务编号,MES工位号,操作类型,操作人,请求报文,响应报文,是否成功,操作结果) + VALUES(NULLIF(@外部任务编号,N''),NULLIF(@MES工位号,N''),@操作类型,@操作人,@请求报文,@响应报文,@是否成功,@操作结果) + SELECT 1 result +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_操作记录_分页查询 +@开始时间 nvarchar(50)=N'', +@结束时间 nvarchar(50)=N'', +@操作类型 nvarchar(50)=N'', +@PageCurrent int=1, +@PageSize int=20, +@PageCount int output, +@ItemCount int output +AS +BEGIN + SET NOCOUNT ON + DECLARE @where nvarchar(1000)=N'1=1' + IF @开始时间<>N'' SET @where+=N' AND 操作时间>='''+REPLACE(@开始时间,'''','''''')+N'''' + IF @结束时间<>N'' SET @where+=N' AND 操作时间<='''+REPLACE(@结束时间,'''','''''')+N'''' + IF @操作类型<>N'' SET @where+=N' AND 操作类型='''+REPLACE(@操作类型,'''','''''')+N'''' + EXEC sp_xt_pagesplit N'XD_TCS_AGV_操作记录',N'ID',@where, + N'ID,外部任务编号,MES工位号,操作类型,操作人,是否成功,操作结果,操作时间', + N'ID DESC',@PageCurrent,@PageSize,@PageCount output,@ItemCount output +END +GO + +CREATE OR ALTER PROCEDURE dbo.XD_TCS_AGV_操作记录_任务查询 +@外部任务编号 nvarchar(100) +AS +BEGIN + SET NOCOUNT ON + SELECT ID,外部任务编号,MES工位号,操作类型,操作人,是否成功,操作结果,操作时间 + FROM dbo.XD_TCS_AGV_操作记录 + WHERE 外部任务编号=@外部任务编号 + ORDER BY ID DESC +END +GO diff --git a/DatabaseScripts/XD_TCS_AGV状态机测试.sql b/DatabaseScripts/XD_TCS_AGV状态机测试.sql new file mode 100644 index 0000000..45d2b05 --- /dev/null +++ b/DatabaseScripts/XD_TCS_AGV状态机测试.sql @@ -0,0 +1,98 @@ +SET NOCOUNT ON + +DECLARE @前缀 nvarchar(50)=N'UT_AGV_STATE_' +DECLARE @首任务 nvarchar(100)=@前缀+N'BASE' +DECLARE @并发任务 nvarchar(100)=@前缀+N'SECOND' +DECLARE @未复位恢复 nvarchar(100)=@前缀+N'NORESET' +DECLARE @跨工位恢复 nvarchar(100)=@前缀+N'WRONG_STATION' +DECLARE @正确恢复 nvarchar(100)=@前缀+N'RECOVERY' +DECLARE @失败未处理阻断 nvarchar(100)=@前缀+N'BLOCKED' +DECLARE @处理后任务 nvarchar(100)=@前缀+N'AFTER_HANDLE' +DECLARE @失败断言数 int=0 + +DELETE FROM dbo.XD_TCS_AGV_操作记录 WHERE 外部任务编号 LIKE @前缀+N'%' +DELETE FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号 LIKE @前缀+N'%' + +PRINT N'[1] 创建首个任务' +EXEC dbo.XD_TCS_AGV_任务_创建 + @首任务,N'',N'AC0909-01',N'插',N'',N'nav_action_program', + N'[{"workStation":"S000214"},{"programName":"214GIS1插XSD"},{"programName":"214GIS1插XSE"}]', + 1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@首任务) + SET @失败断言数+=1 + +PRINT N'[2] 单车活动任务拦截' +EXEC dbo.XD_TCS_AGV_任务_创建 + @并发任务,N'',N'AC0909-02',N'插',N'',N'nav_action_program',N'[{"workStation":"S000215"}]', + 1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@并发任务) + SET @失败断言数+=1 + +EXEC dbo.XD_TCS_AGV_任务_本地状态设置 @首任务,4,N'任务错误',N'单元测试失败' + +PRINT N'[3] 未复位恢复任务拦截' +EXEC dbo.XD_TCS_AGV_任务_创建 + @未复位恢复,@首任务,N'AC0909-01',N'插-单步',N'214GIS1插XSD',N'program', + N'[{"programName":"214GIS1插XSD"}]',1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@未复位恢复) + SET @失败断言数+=1 + +PRINT N'[4] 复位标记与跨工位恢复拦截' +EXEC dbo.XD_TCS_AGV_任务_复位标记 @首任务 +EXEC dbo.XD_TCS_AGV_任务_状态更新 + @首任务,5,N'10.146.79.9',N'nav_action_program',N'',N'',N'任务错误已处理' +IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@首任务 AND 任务状态=5 AND 已复位=1) + SET @失败断言数+=1 +EXEC dbo.XD_TCS_AGV_任务_创建 + @跨工位恢复,@首任务,N'AC0909-02',N'插-单步',N'215GIS2插XSD',N'program', + N'[{"programName":"215GIS2插XSD"}]',1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@跨工位恢复) + SET @失败断言数+=1 + +PRINT N'[5] 复位后同工位恢复放行' +EXEC dbo.XD_TCS_AGV_任务_创建 + @正确恢复,@首任务,N'AC0909-01',N'插-单步',N'214GIS1插XSD',N'program', + N'[{"programName":"214GIS1插XSD"}]',1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@正确恢复) + SET @失败断言数+=1 +EXEC dbo.XD_TCS_AGV_任务_状态更新 + @正确恢复,2,N'10.146.79.9',N'program',N'2026-07-13 10:00:00',N'2026-07-13 10:01:00',N'' + +PRINT N'[6] 原失败任务未处理时继续阻断' +EXEC dbo.XD_TCS_AGV_任务_创建 + @失败未处理阻断,N'',N'AC0909-02',N'插',N'',N'nav_action_program',N'[{"workStation":"S000215"}]', + 1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@失败未处理阻断) + SET @失败断言数+=1 + +PRINT N'[7] 人工处理后新任务放行' +EXEC dbo.XD_TCS_AGV_任务_人工处理 @首任务,N'状态机测试',N'恢复任务已完成' +EXEC dbo.XD_TCS_AGV_任务_状态更新 @首任务,2,N'',N'',N'',N'',N'迟到完成' +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@首任务 AND 任务状态<>5) + SET @失败断言数+=1 +EXEC dbo.XD_TCS_AGV_任务_创建 + @处理后任务,N'',N'AC0909-02',N'拔',N'',N'nav_action_program',N'[{"workStation":"S000215"}]', + 1,N'G001',N'10.146.79.9',N'UNIT_TEST',N'状态机测试',0 +IF NOT EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@处理后任务) + SET @失败断言数+=1 + +PRINT N'[8] 未复位失败任务不能人工处理,终态不能改写' +EXEC dbo.XD_TCS_AGV_任务_本地状态设置 @处理后任务,4,N'任务错误',N'终态测试' +EXEC dbo.XD_TCS_AGV_任务_人工处理 @处理后任务,N'状态机测试',N'不应成功' +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@处理后任务 AND 处理状态=1) + SET @失败断言数+=1 +EXEC dbo.XD_TCS_AGV_任务_状态更新 @处理后任务,2,N'',N'',N'',N'',N'迟到完成' +IF EXISTS(SELECT 1 FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号=@处理后任务 AND 任务状态<>4) + SET @失败断言数+=1 + +SELECT @失败断言数 AS 失败断言数, + (SELECT COUNT(*) FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号 LIKE @前缀+N'%') AS 测试任务数 + +DELETE FROM dbo.XD_TCS_AGV_操作记录 WHERE 外部任务编号 LIKE @前缀+N'%' +DELETE FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号 LIKE @前缀+N'%' + +IF @失败断言数<>0 + RAISERROR(N'AGV数据库状态机测试失败',16,1) + +SELECT COUNT(*) AS 清理后测试任务数 +FROM dbo.XD_TCS_AGV_任务 WHERE 外部任务编号 LIKE @前缀+N'%' diff --git a/DatabaseScripts/XD_电能表谐波数据.sql b/DatabaseScripts/XD_电能表谐波数据.sql deleted file mode 100644 index 8c6308a..0000000 --- a/DatabaseScripts/XD_电能表谐波数据.sql +++ /dev/null @@ -1,173 +0,0 @@ -IF OBJECT_ID(N'dbo.XD_电能表谐波数据', N'U') IS NULL -BEGIN - CREATE TABLE dbo.XD_电能表谐波数据 - ( - ID int IDENTITY(1,1) NOT NULL, - 工位号 nvarchar(50) NULL, - A相电压总谐波畸变 float NULL, - B相电压总谐波畸变 float NULL, - C相电压总谐波畸变 float NULL, - 系统电压总谐波畸变 float NULL, - A相电流总谐波畸变 float NULL, - B相电流总谐波畸变 float NULL, - C相电流总谐波畸变 float NULL, - 系统电流总谐波畸变 float NULL, - A相电压奇次谐波畸变 float NULL, - B相电压奇次谐波畸变 float NULL, - C相电压奇次谐波畸变 float NULL, - A相电流奇次谐波畸变 float NULL, - B相电流奇次谐波畸变 float NULL, - C相电流奇次谐波畸变 float NULL, - A相电压偶次谐波畸变 float NULL, - B相电压偶次谐波畸变 float NULL, - C相电压偶次谐波畸变 float NULL, - A相电流偶次谐波畸变 float NULL, - B相电流偶次谐波畸变 float NULL, - C相电流偶次谐波畸变 float NULL, - 操作时间 datetime NULL CONSTRAINT DF_XD_电能表谐波数据_操作时间 DEFAULT (GETDATE()), - CONSTRAINT PK_XD_电能表谐波数据 PRIMARY KEY CLUSTERED (ID ASC) - ); -END -GO - -IF NOT EXISTS ( - SELECT 1 - FROM sys.indexes - WHERE name = N'IX_XD_电能表谐波数据_工位号_操作时间' - AND object_id = OBJECT_ID(N'dbo.XD_电能表谐波数据') -) -BEGIN - CREATE NONCLUSTERED INDEX IX_XD_电能表谐波数据_工位号_操作时间 - ON dbo.XD_电能表谐波数据 (工位号 ASC, 操作时间 DESC); -END -GO - -IF OBJECT_ID(N'dbo.XD_电能表谐波数据_增加', N'P') IS NOT NULL - DROP PROCEDURE dbo.XD_电能表谐波数据_增加; -GO - -CREATE PROCEDURE dbo.XD_电能表谐波数据_增加 - @工位号 nvarchar(50) = N'', - @A相电压总谐波畸变 float = NULL, - @B相电压总谐波畸变 float = NULL, - @C相电压总谐波畸变 float = NULL, - @系统电压总谐波畸变 float = NULL, - @A相电流总谐波畸变 float = NULL, - @B相电流总谐波畸变 float = NULL, - @C相电流总谐波畸变 float = NULL, - @系统电流总谐波畸变 float = NULL, - @A相电压奇次谐波畸变 float = NULL, - @B相电压奇次谐波畸变 float = NULL, - @C相电压奇次谐波畸变 float = NULL, - @A相电流奇次谐波畸变 float = NULL, - @B相电流奇次谐波畸变 float = NULL, - @C相电流奇次谐波畸变 float = NULL, - @A相电压偶次谐波畸变 float = NULL, - @B相电压偶次谐波畸变 float = NULL, - @C相电压偶次谐波畸变 float = NULL, - @A相电流偶次谐波畸变 float = NULL, - @B相电流偶次谐波畸变 float = NULL, - @C相电流偶次谐波畸变 float = NULL -AS -BEGIN - SET NOCOUNT ON; - - IF NULLIF(LTRIM(RTRIM(@工位号)), N'') IS NULL - RETURN; - - -- 电表返回 -1 表示无效数据;任一谐波点无效时,本次整条采集不入库。 - IF @A相电压总谐波畸变 = -1 - OR @B相电压总谐波畸变 = -1 - OR @C相电压总谐波畸变 = -1 - OR @系统电压总谐波畸变 = -1 - OR @A相电流总谐波畸变 = -1 - OR @B相电流总谐波畸变 = -1 - OR @C相电流总谐波畸变 = -1 - OR @系统电流总谐波畸变 = -1 - OR @A相电压奇次谐波畸变 = -1 - OR @B相电压奇次谐波畸变 = -1 - OR @C相电压奇次谐波畸变 = -1 - OR @A相电流奇次谐波畸变 = -1 - OR @B相电流奇次谐波畸变 = -1 - OR @C相电流奇次谐波畸变 = -1 - OR @A相电压偶次谐波畸变 = -1 - OR @B相电压偶次谐波畸变 = -1 - OR @C相电压偶次谐波畸变 = -1 - OR @A相电流偶次谐波畸变 = -1 - OR @B相电流偶次谐波畸变 = -1 - OR @C相电流偶次谐波畸变 = -1 - RETURN; - - -- 谐波畸变允许为 0;只有全部点位都为空时跳过保存。 - IF @A相电压总谐波畸变 IS NULL - AND @B相电压总谐波畸变 IS NULL - AND @C相电压总谐波畸变 IS NULL - AND @系统电压总谐波畸变 IS NULL - AND @A相电流总谐波畸变 IS NULL - AND @B相电流总谐波畸变 IS NULL - AND @C相电流总谐波畸变 IS NULL - AND @系统电流总谐波畸变 IS NULL - AND @A相电压奇次谐波畸变 IS NULL - AND @B相电压奇次谐波畸变 IS NULL - AND @C相电压奇次谐波畸变 IS NULL - AND @A相电流奇次谐波畸变 IS NULL - AND @B相电流奇次谐波畸变 IS NULL - AND @C相电流奇次谐波畸变 IS NULL - AND @A相电压偶次谐波畸变 IS NULL - AND @B相电压偶次谐波畸变 IS NULL - AND @C相电压偶次谐波畸变 IS NULL - AND @A相电流偶次谐波畸变 IS NULL - AND @B相电流偶次谐波畸变 IS NULL - AND @C相电流偶次谐波畸变 IS NULL - RETURN; - - INSERT INTO dbo.XD_电能表谐波数据 - ( - 工位号, - A相电压总谐波畸变, - B相电压总谐波畸变, - C相电压总谐波畸变, - 系统电压总谐波畸变, - A相电流总谐波畸变, - B相电流总谐波畸变, - C相电流总谐波畸变, - 系统电流总谐波畸变, - A相电压奇次谐波畸变, - B相电压奇次谐波畸变, - C相电压奇次谐波畸变, - A相电流奇次谐波畸变, - B相电流奇次谐波畸变, - C相电流奇次谐波畸变, - A相电压偶次谐波畸变, - B相电压偶次谐波畸变, - C相电压偶次谐波畸变, - A相电流偶次谐波畸变, - B相电流偶次谐波畸变, - C相电流偶次谐波畸变 - ) - VALUES - ( - @工位号, - @A相电压总谐波畸变 / 1000.0, - @B相电压总谐波畸变 / 1000.0, - @C相电压总谐波畸变 / 1000.0, - @系统电压总谐波畸变 / 1000.0, - @A相电流总谐波畸变 / 1000.0, - @B相电流总谐波畸变 / 1000.0, - @C相电流总谐波畸变 / 1000.0, - @系统电流总谐波畸变 / 1000.0, - @A相电压奇次谐波畸变 / 1000.0, - @B相电压奇次谐波畸变 / 1000.0, - @C相电压奇次谐波畸变 / 1000.0, - @A相电流奇次谐波畸变 / 1000.0, - @B相电流奇次谐波畸变 / 1000.0, - @C相电流奇次谐波畸变 / 1000.0, - @A相电压偶次谐波畸变 / 1000.0, - @B相电压偶次谐波畸变 / 1000.0, - @C相电压偶次谐波畸变 / 1000.0, - @A相电流偶次谐波畸变 / 1000.0, - @B相电流偶次谐波畸变 / 1000.0, - @C相电流偶次谐波畸变 / 1000.0 - ); -END -GO diff --git a/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj b/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj index 812ee07..b1886cb 100644 --- a/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj +++ b/Interface_WebAPI/SlMesDbIterface/ExternalDataSync.csproj @@ -212,8 +212,14 @@ + + + + + + @@ -519,4 +525,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..37f142b --- /dev/null +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/LGAGV_BusinessLogic.cs @@ -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 +{ + /// + /// 临工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); + 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); + } + } + + /// + /// 处理临工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/AGV/TCSAGV_BusinessLogic.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_BusinessLogic.cs new file mode 100644 index 0000000..6530d06 --- /dev/null +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_BusinessLogic.cs @@ -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 +{ + /// + /// TCS插拔任务业务处理。PLC自动任务与Web人工任务共用此入口。 + /// + 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 { { "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 { { "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 { { "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 { { "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 query = new Dictionary + { + { "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(); + 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(); + 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 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 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); + } + } +} diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_Models.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_Models.cs new file mode 100644 index 0000000..7f88f38 --- /dev/null +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_Models.cs @@ -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() + }; + } + } +} diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs index e2c2be2..8d3e974 100644 --- a/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/AGVController.cs @@ -40,5 +40,202 @@ 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") + }; + } + + [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 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") + }; + } } } 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..201f3f0 100644 --- a/Interface_WebAPI/SlMesDbIterface/WebAPI/FactoryMES/CALL_Inerface_DataHandle.cs +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/FactoryMES/CALL_Inerface_DataHandle.cs @@ -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; + } + /// /// 开工(工序) /// @@ -32,19 +43,17 @@ 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; } //查询工单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 /// 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 } } + /// + /// 物料转序 + /// + /// 起始位置编号 + /// 终点位置编号 + /// 派工任务id + /// 搬运类型:1:搬运容器,2:搬运货架 + /// 载具类型:0-空;1-满 + /// 返回调用结果 JObject,包含 code 和 message /// /// 物料转序 /// @@ -940,3 +957,4 @@ namespace WebApi //#endregion } } + 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..b438a21 --- /dev/null +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_BusinessLogic.cs @@ -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 +{ + /// + /// 临工AGV网页按钮业务处理。 + /// + public class LGWEB_BusinessLogic + { + /// + /// 网页按钮下发临工AGV搬运任务。 + /// + public static string WEB_DispatchAGV(string url, [FromBody] JObject jobj) + { + var result = new MsgResHeader + { + 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(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; + } + + /// + /// 下发临工AGV搬运任务,供 WebAPI 和 Function 直接复用。 + /// + 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 + }; + } + + /// + /// 网页按钮放行临工AGV离开。 + /// + public static string WEB_AllowLeave(string url, [FromBody] JObject jobj) + { + var result = new MsgResHeader + { + 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(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; } + } + } +} diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_Models.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_Models.cs new file mode 100644 index 0000000..1260e8b --- /dev/null +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/LGWEB_Models.cs @@ -0,0 +1,88 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MisDataSaveDate +{ + /// + /// 临工AGV网页按钮调度请求。 + /// + 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; } + } + + /// + /// 临工AGV网页按钮放行请求。 + /// + 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; } + } + + /// + /// 临工AGV调度内部结果,WebAPI 和 Function 共用。 + /// + 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; } + } +} diff --git a/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/WEB_BusinessLogic.cs b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/WEB_BusinessLogic.cs index 1631abc..4ed43a9 100644 --- a/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/WEB_BusinessLogic.cs +++ b/Interface_WebAPI/SlMesDbIterface/WebAPI/WEB/WEB_BusinessLogic.cs @@ -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": diff --git a/MisDataFun/MisDataFun/App.config b/MisDataFun/MisDataFun/App.config index 3eedead..0890213 100644 --- a/MisDataFun/MisDataFun/App.config +++ b/MisDataFun/MisDataFun/App.config @@ -10,12 +10,12 @@ - + - - - + + + @@ -25,7 +25,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -111,4 +111,4 @@ - \ No newline at end of file + diff --git a/MisDataFun/MisDataFun/MisDataFun.Designer.cs b/MisDataFun/MisDataFun/MisDataFun.Designer.cs index be54a6c..31703fd 100644 --- a/MisDataFun/MisDataFun/MisDataFun.Designer.cs +++ b/MisDataFun/MisDataFun/MisDataFun.Designer.cs @@ -268,7 +268,7 @@ namespace MisDataSaveDate this.tableLayoutPanel1.Controls.Add(this.panel5, 1, 3); this.tableLayoutPanel1.Controls.Add(this.panel2, 0, 3); this.tableLayoutPanel1.Location = new System.Drawing.Point(334, 319); - this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(2); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 4; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20F)); @@ -283,9 +283,9 @@ namespace MisDataSaveDate this.groupBox5.Controls.Add(this.textBox_WEB_TO_MES); this.groupBox5.Dock = System.Windows.Forms.DockStyle.Fill; this.groupBox5.Location = new System.Drawing.Point(2, 172); - this.groupBox5.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox5.Margin = new System.Windows.Forms.Padding(2); this.groupBox5.Name = "groupBox5"; - this.groupBox5.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox5.Padding = new System.Windows.Forms.Padding(2); this.groupBox5.Size = new System.Drawing.Size(386, 64); this.groupBox5.TabIndex = 4; this.groupBox5.TabStop = false; @@ -295,7 +295,7 @@ namespace MisDataSaveDate // this.textBox_WEB_TO_MES.Dock = System.Windows.Forms.DockStyle.Fill; this.textBox_WEB_TO_MES.Location = new System.Drawing.Point(2, 16); - this.textBox_WEB_TO_MES.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.textBox_WEB_TO_MES.Margin = new System.Windows.Forms.Padding(2); this.textBox_WEB_TO_MES.Multiline = true; this.textBox_WEB_TO_MES.Name = "textBox_WEB_TO_MES"; this.textBox_WEB_TO_MES.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; @@ -307,9 +307,9 @@ namespace MisDataSaveDate this.groupBox1.Controls.Add(this.textBox_PLC_TO_MES); this.groupBox1.Controls.Add(this.panel8); this.groupBox1.Location = new System.Drawing.Point(2, 2); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2); this.groupBox1.Size = new System.Drawing.Size(386, 64); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; @@ -319,7 +319,7 @@ namespace MisDataSaveDate // this.textBox_PLC_TO_MES.Dock = System.Windows.Forms.DockStyle.Fill; this.textBox_PLC_TO_MES.Location = new System.Drawing.Point(2, 16); - this.textBox_PLC_TO_MES.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.textBox_PLC_TO_MES.Margin = new System.Windows.Forms.Padding(2); this.textBox_PLC_TO_MES.Multiline = true; this.textBox_PLC_TO_MES.Name = "textBox_PLC_TO_MES"; this.textBox_PLC_TO_MES.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; @@ -532,9 +532,9 @@ namespace MisDataSaveDate this.groupBox3.Controls.Add(this.textBox_MES_TO_WEB); this.groupBox3.Dock = System.Windows.Forms.DockStyle.Fill; this.groupBox3.Location = new System.Drawing.Point(2, 70); - this.groupBox3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox3.Margin = new System.Windows.Forms.Padding(2); this.groupBox3.Name = "groupBox3"; - this.groupBox3.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox3.Padding = new System.Windows.Forms.Padding(2); this.groupBox3.Size = new System.Drawing.Size(386, 98); this.groupBox3.TabIndex = 2; this.groupBox3.TabStop = false; @@ -544,7 +544,7 @@ namespace MisDataSaveDate // this.textBox_MES_TO_WEB.Dock = System.Windows.Forms.DockStyle.Fill; this.textBox_MES_TO_WEB.Location = new System.Drawing.Point(2, 16); - this.textBox_MES_TO_WEB.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.textBox_MES_TO_WEB.Margin = new System.Windows.Forms.Padding(2); this.textBox_MES_TO_WEB.Multiline = true; this.textBox_MES_TO_WEB.Name = "textBox_MES_TO_WEB"; this.textBox_MES_TO_WEB.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; @@ -556,7 +556,7 @@ namespace MisDataSaveDate this.panel1.Controls.Add(this.tableLayoutPanel3); this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; this.panel1.Location = new System.Drawing.Point(392, 2); - this.panel1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.panel1.Margin = new System.Windows.Forms.Padding(2); this.panel1.Name = "panel1"; this.panel1.Size = new System.Drawing.Size(196, 64); this.panel1.TabIndex = 10; @@ -574,7 +574,7 @@ namespace MisDataSaveDate this.tableLayoutPanel3.Controls.Add(this.button_PLC_TO_MES_Small, 1, 0); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(2); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 2; this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -590,7 +590,7 @@ namespace MisDataSaveDate this.checkBox_PLC_TO_MES.AutoSize = true; this.checkBox_PLC_TO_MES.Dock = System.Windows.Forms.DockStyle.Fill; this.checkBox_PLC_TO_MES.Location = new System.Drawing.Point(2, 2); - this.checkBox_PLC_TO_MES.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.checkBox_PLC_TO_MES.Margin = new System.Windows.Forms.Padding(2); this.checkBox_PLC_TO_MES.Name = "checkBox_PLC_TO_MES"; this.checkBox_PLC_TO_MES.Size = new System.Drawing.Size(54, 22); this.checkBox_PLC_TO_MES.TabIndex = 0; @@ -601,7 +601,7 @@ namespace MisDataSaveDate // this.button_PLC_TO_MES_Clear.Dock = System.Windows.Forms.DockStyle.Fill; this.button_PLC_TO_MES_Clear.Location = new System.Drawing.Point(138, 2); - this.button_PLC_TO_MES_Clear.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_PLC_TO_MES_Clear.Margin = new System.Windows.Forms.Padding(2); this.button_PLC_TO_MES_Clear.Name = "button_PLC_TO_MES_Clear"; this.button_PLC_TO_MES_Clear.Size = new System.Drawing.Size(56, 22); this.button_PLC_TO_MES_Clear.TabIndex = 1; @@ -611,7 +611,7 @@ namespace MisDataSaveDate // button_PLC_TO_MES_Big // this.button_PLC_TO_MES_Big.Location = new System.Drawing.Point(99, 2); - this.button_PLC_TO_MES_Big.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_PLC_TO_MES_Big.Margin = new System.Windows.Forms.Padding(2); this.button_PLC_TO_MES_Big.Name = "button_PLC_TO_MES_Big"; this.button_PLC_TO_MES_Big.Size = new System.Drawing.Size(34, 20); this.button_PLC_TO_MES_Big.TabIndex = 2; @@ -621,7 +621,7 @@ namespace MisDataSaveDate // button_PLC_TO_MES_Small // this.button_PLC_TO_MES_Small.Location = new System.Drawing.Point(60, 2); - this.button_PLC_TO_MES_Small.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_PLC_TO_MES_Small.Margin = new System.Windows.Forms.Padding(2); this.button_PLC_TO_MES_Small.Name = "button_PLC_TO_MES_Small"; this.button_PLC_TO_MES_Small.Size = new System.Drawing.Size(34, 20); this.button_PLC_TO_MES_Small.TabIndex = 2; @@ -633,7 +633,7 @@ namespace MisDataSaveDate this.panel3.Controls.Add(this.tableLayoutPanel2); this.panel3.Dock = System.Windows.Forms.DockStyle.Fill; this.panel3.Location = new System.Drawing.Point(392, 70); - this.panel3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.panel3.Margin = new System.Windows.Forms.Padding(2); this.panel3.Name = "panel3"; this.panel3.Size = new System.Drawing.Size(196, 98); this.panel3.TabIndex = 12; @@ -652,7 +652,7 @@ namespace MisDataSaveDate this.tableLayoutPanel2.Controls.Add(this.button_MES_TO_WEB_Big, 2, 0); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(2); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 2; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -673,7 +673,7 @@ namespace MisDataSaveDate this.tableLayoutPanel2.SetColumnSpan(this.dataGridView_CheckOpName, 4); this.dataGridView_CheckOpName.Dock = System.Windows.Forms.DockStyle.Fill; this.dataGridView_CheckOpName.Location = new System.Drawing.Point(2, 28); - this.dataGridView_CheckOpName.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.dataGridView_CheckOpName.Margin = new System.Windows.Forms.Padding(2); this.dataGridView_CheckOpName.MultiSelect = false; this.dataGridView_CheckOpName.Name = "dataGridView_CheckOpName"; this.dataGridView_CheckOpName.RowHeadersVisible = false; @@ -705,7 +705,7 @@ namespace MisDataSaveDate this.checkBox__MES_TO_WEB.AutoSize = true; this.checkBox__MES_TO_WEB.Dock = System.Windows.Forms.DockStyle.Fill; this.checkBox__MES_TO_WEB.Location = new System.Drawing.Point(2, 2); - this.checkBox__MES_TO_WEB.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.checkBox__MES_TO_WEB.Margin = new System.Windows.Forms.Padding(2); this.checkBox__MES_TO_WEB.Name = "checkBox__MES_TO_WEB"; this.checkBox__MES_TO_WEB.Size = new System.Drawing.Size(54, 22); this.checkBox__MES_TO_WEB.TabIndex = 0; @@ -716,7 +716,7 @@ namespace MisDataSaveDate // this.button_MES_TO_WEB_Clear.Dock = System.Windows.Forms.DockStyle.Fill; this.button_MES_TO_WEB_Clear.Location = new System.Drawing.Point(138, 2); - this.button_MES_TO_WEB_Clear.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_MES_TO_WEB_Clear.Margin = new System.Windows.Forms.Padding(2); this.button_MES_TO_WEB_Clear.Name = "button_MES_TO_WEB_Clear"; this.button_MES_TO_WEB_Clear.Size = new System.Drawing.Size(56, 22); this.button_MES_TO_WEB_Clear.TabIndex = 2; @@ -726,7 +726,7 @@ namespace MisDataSaveDate // button_MES_TO_WEB_Small // this.button_MES_TO_WEB_Small.Location = new System.Drawing.Point(60, 2); - this.button_MES_TO_WEB_Small.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_MES_TO_WEB_Small.Margin = new System.Windows.Forms.Padding(2); this.button_MES_TO_WEB_Small.Name = "button_MES_TO_WEB_Small"; this.button_MES_TO_WEB_Small.Size = new System.Drawing.Size(34, 20); this.button_MES_TO_WEB_Small.TabIndex = 4; @@ -736,7 +736,7 @@ namespace MisDataSaveDate // button_MES_TO_WEB_Big // this.button_MES_TO_WEB_Big.Location = new System.Drawing.Point(99, 2); - this.button_MES_TO_WEB_Big.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_MES_TO_WEB_Big.Margin = new System.Windows.Forms.Padding(2); this.button_MES_TO_WEB_Big.Name = "button_MES_TO_WEB_Big"; this.button_MES_TO_WEB_Big.Size = new System.Drawing.Size(34, 20); this.button_MES_TO_WEB_Big.TabIndex = 4; @@ -749,7 +749,7 @@ namespace MisDataSaveDate this.panel4.Controls.Add(this.tableLayoutPanel4); this.panel4.Dock = System.Windows.Forms.DockStyle.Fill; this.panel4.Location = new System.Drawing.Point(392, 172); - this.panel4.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.panel4.Margin = new System.Windows.Forms.Padding(2); this.panel4.Name = "panel4"; this.panel4.Size = new System.Drawing.Size(196, 64); this.panel4.TabIndex = 13; @@ -767,7 +767,7 @@ namespace MisDataSaveDate this.tableLayoutPanel4.Controls.Add(this.button_WEB_TO_MES_Clear, 3, 0); this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(2); this.tableLayoutPanel4.Name = "tableLayoutPanel4"; this.tableLayoutPanel4.RowCount = 2; this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -778,7 +778,7 @@ namespace MisDataSaveDate // button_WEB_TO_MES_Big // this.button_WEB_TO_MES_Big.Location = new System.Drawing.Point(98, 2); - this.button_WEB_TO_MES_Big.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_WEB_TO_MES_Big.Margin = new System.Windows.Forms.Padding(2); this.button_WEB_TO_MES_Big.Name = "button_WEB_TO_MES_Big"; this.button_WEB_TO_MES_Big.Size = new System.Drawing.Size(34, 20); this.button_WEB_TO_MES_Big.TabIndex = 6; @@ -788,7 +788,7 @@ namespace MisDataSaveDate // button_WEB_TO_MES_Small // this.button_WEB_TO_MES_Small.Location = new System.Drawing.Point(60, 2); - this.button_WEB_TO_MES_Small.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_WEB_TO_MES_Small.Margin = new System.Windows.Forms.Padding(2); this.button_WEB_TO_MES_Small.Name = "button_WEB_TO_MES_Small"; this.button_WEB_TO_MES_Small.Size = new System.Drawing.Size(34, 20); this.button_WEB_TO_MES_Small.TabIndex = 5; @@ -800,7 +800,7 @@ namespace MisDataSaveDate this.checkBox_WEB_TO_MES.AutoSize = true; this.checkBox_WEB_TO_MES.Dock = System.Windows.Forms.DockStyle.Fill; this.checkBox_WEB_TO_MES.Location = new System.Drawing.Point(2, 2); - this.checkBox_WEB_TO_MES.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.checkBox_WEB_TO_MES.Margin = new System.Windows.Forms.Padding(2); this.checkBox_WEB_TO_MES.Name = "checkBox_WEB_TO_MES"; this.checkBox_WEB_TO_MES.Size = new System.Drawing.Size(54, 22); this.checkBox_WEB_TO_MES.TabIndex = 0; @@ -811,7 +811,7 @@ namespace MisDataSaveDate // this.button_WEB_TO_MES_Clear.Dock = System.Windows.Forms.DockStyle.Fill; this.button_WEB_TO_MES_Clear.Location = new System.Drawing.Point(136, 2); - this.button_WEB_TO_MES_Clear.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_WEB_TO_MES_Clear.Margin = new System.Windows.Forms.Padding(2); this.button_WEB_TO_MES_Clear.Name = "button_WEB_TO_MES_Clear"; this.button_WEB_TO_MES_Clear.Size = new System.Drawing.Size(56, 22); this.button_WEB_TO_MES_Clear.TabIndex = 1; @@ -895,7 +895,7 @@ namespace MisDataSaveDate // button_SaveData // this.button_SaveData.Location = new System.Drawing.Point(13, 95); - this.button_SaveData.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_SaveData.Margin = new System.Windows.Forms.Padding(2); this.button_SaveData.Name = "button_SaveData"; this.button_SaveData.Size = new System.Drawing.Size(56, 18); this.button_SaveData.TabIndex = 4; @@ -991,7 +991,7 @@ namespace MisDataSaveDate this.tabPage1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.tabPage1.Size = new System.Drawing.Size(171, 69); + this.tabPage1.Size = new System.Drawing.Size(170, 69); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "产品信息"; this.tabPage1.UseVisualStyleBackColor = true; @@ -1002,7 +1002,7 @@ namespace MisDataSaveDate this.tabPage2.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.tabPage2.Size = new System.Drawing.Size(171, 69); + this.tabPage2.Size = new System.Drawing.Size(170, 69); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "工步信息"; this.tabPage2.UseVisualStyleBackColor = true; @@ -1012,7 +1012,7 @@ namespace MisDataSaveDate this.tabPage3.Location = new System.Drawing.Point(4, 22); this.tabPage3.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(171, 69); + this.tabPage3.Size = new System.Drawing.Size(170, 69); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "物料信息"; this.tabPage3.UseVisualStyleBackColor = true; @@ -1022,7 +1022,7 @@ namespace MisDataSaveDate this.tabPage4.Location = new System.Drawing.Point(4, 22); this.tabPage4.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(171, 69); + this.tabPage4.Size = new System.Drawing.Size(170, 69); this.tabPage4.TabIndex = 3; this.tabPage4.Text = "操作图片"; this.tabPage4.UseVisualStyleBackColor = true; @@ -1032,7 +1032,7 @@ namespace MisDataSaveDate this.tabPage5.Location = new System.Drawing.Point(4, 22); this.tabPage5.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.tabPage5.Name = "tabPage5"; - this.tabPage5.Size = new System.Drawing.Size(171, 69); + this.tabPage5.Size = new System.Drawing.Size(170, 69); this.tabPage5.TabIndex = 4; this.tabPage5.Text = "PLC信号"; this.tabPage5.UseVisualStyleBackColor = true; @@ -1304,6 +1304,7 @@ namespace MisDataSaveDate this.pb_OnLine_Print.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.pb_OnLine_Print.TabIndex = 1485; this.pb_OnLine_Print.TabStop = false; + this.pb_OnLine_Print.Visible = false; // // label28 // @@ -1314,6 +1315,7 @@ namespace MisDataSaveDate this.label28.Size = new System.Drawing.Size(41, 12); this.label28.TabIndex = 1484; this.label28.Text = "打印机"; + this.label28.Visible = false; // // pb_OnLine_SQL // diff --git a/MisDataFun/MisDataFun/MisDataFun.cs b/MisDataFun/MisDataFun/MisDataFun.cs index 2dfb975..af2803c 100644 --- a/MisDataFun/MisDataFun/MisDataFun.cs +++ b/MisDataFun/MisDataFun/MisDataFun.cs @@ -697,7 +697,7 @@ namespace MisDataSaveDate { string mesAlarmType = errDt["测量单位"].ToString(); if (AlarmExceptionTypeMap.ContainsKey(mesAlarmType)) mesAlarmType = AlarmExceptionTypeMap[mesAlarmType]; - WebApi.CALL_Inerface_DataHandle.CALL_Inerface_DeviceAlarm(opName, tagID, mesAlarmType, errDt["测量项目"].ToString()); + // WebApi.CALL_Inerface_DataHandle.CALL_Inerface_DeviceAlarm(opName, tagID, mesAlarmType, errDt["测量项目"].ToString()); } } diff --git a/MisDataFun/MisDataFun/mes_signal_conf/MES_CONF.cs b/MisDataFun/MisDataFun/mes_signal_conf/MES_CONF.cs index 43222ea..fbe5fba 100644 --- a/MisDataFun/MisDataFun/mes_signal_conf/MES_CONF.cs +++ b/MisDataFun/MisDataFun/mes_signal_conf/MES_CONF.cs @@ -1,4 +1,4 @@ -using SlMesDbIterface; +using SlMesDbIterface; using System; using System.Data; using System.Linq; diff --git a/MisDataFun_Exe/09MesDataFunction.dll b/MisDataFun_Exe/09MesDataFunction.dll index 930dbe5..cce85df 100644 Binary files a/MisDataFun_Exe/09MesDataFunction.dll and b/MisDataFun_Exe/09MesDataFunction.dll differ diff --git a/MisDataFun_Exe/09MesDataFunction.pdb b/MisDataFun_Exe/09MesDataFunction.pdb index 96306ca..a94435d 100644 Binary files a/MisDataFun_Exe/09MesDataFunction.pdb and b/MisDataFun_Exe/09MesDataFunction.pdb differ diff --git a/MisDataFun_Exe/ExternalDataSync.exe b/MisDataFun_Exe/ExternalDataSync.exe index fe26901..3dd0502 100644 Binary files a/MisDataFun_Exe/ExternalDataSync.exe and b/MisDataFun_Exe/ExternalDataSync.exe differ diff --git a/MisDataFun_Exe/ExternalDataSync.pdb b/MisDataFun_Exe/ExternalDataSync.pdb index 49ce525..ff0ba92 100644 Binary files a/MisDataFun_Exe/ExternalDataSync.pdb and b/MisDataFun_Exe/ExternalDataSync.pdb differ diff --git a/MisDataFun_Exe/Function1051.dll b/MisDataFun_Exe/Function1051.dll index ed0fecd..faa4df5 100644 Binary files a/MisDataFun_Exe/Function1051.dll and b/MisDataFun_Exe/Function1051.dll differ diff --git a/MisDataFun_Exe/Function1051.pdb b/MisDataFun_Exe/Function1051.pdb index b4c9576..80468ea 100644 Binary files a/MisDataFun_Exe/Function1051.pdb and b/MisDataFun_Exe/Function1051.pdb differ diff --git a/MisDataFun_Exe/Function1052.dll b/MisDataFun_Exe/Function1052.dll index 9d094b6..f084d51 100644 Binary files a/MisDataFun_Exe/Function1052.dll and b/MisDataFun_Exe/Function1052.dll differ diff --git a/MisDataFun_Exe/Function1052.pdb b/MisDataFun_Exe/Function1052.pdb index ca30208..5efa1f0 100644 Binary files a/MisDataFun_Exe/Function1052.pdb and b/MisDataFun_Exe/Function1052.pdb differ diff --git a/MisDataFun_Exe/Function1053.dll b/MisDataFun_Exe/Function1053.dll index 9c4a5bb..06a0049 100644 Binary files a/MisDataFun_Exe/Function1053.dll and b/MisDataFun_Exe/Function1053.dll differ diff --git a/MisDataFun_Exe/Function1053.pdb b/MisDataFun_Exe/Function1053.pdb index eded3bb..1caabaf 100644 Binary files a/MisDataFun_Exe/Function1053.pdb and b/MisDataFun_Exe/Function1053.pdb differ diff --git a/MisDataFun_Exe/Function1054.dll b/MisDataFun_Exe/Function1054.dll index 5c7d86f..9cb9227 100644 Binary files a/MisDataFun_Exe/Function1054.dll and b/MisDataFun_Exe/Function1054.dll differ diff --git a/MisDataFun_Exe/Function1054.pdb b/MisDataFun_Exe/Function1054.pdb index bd2ba4a..319ff72 100644 Binary files a/MisDataFun_Exe/Function1054.pdb and b/MisDataFun_Exe/Function1054.pdb differ diff --git a/MisDataFun_Exe/MisDataFun.exe b/MisDataFun_Exe/MisDataFun.exe index 3df2e95..cdde390 100644 Binary files a/MisDataFun_Exe/MisDataFun.exe and b/MisDataFun_Exe/MisDataFun.exe differ diff --git a/MisDataFun_Exe/MisDataFun.exe.config b/MisDataFun_Exe/MisDataFun.exe.config index 3eedead..0562d32 100644 --- a/MisDataFun_Exe/MisDataFun.exe.config +++ b/MisDataFun_Exe/MisDataFun.exe.config @@ -4,18 +4,18 @@ - + - + - - - + + + @@ -25,7 +25,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -111,4 +111,4 @@ - \ No newline at end of file + diff --git a/MisDataFun_Exe/MisDataFun.pdb b/MisDataFun_Exe/MisDataFun.pdb index 3c8efb6..d223899 100644 Binary files a/MisDataFun_Exe/MisDataFun.pdb and b/MisDataFun_Exe/MisDataFun.pdb differ diff --git a/MisDataFun_Exe/MyLog4Net.dll b/MisDataFun_Exe/MyLog4Net.dll index 6271052..5f08bd5 100644 Binary files a/MisDataFun_Exe/MyLog4Net.dll and b/MisDataFun_Exe/MyLog4Net.dll differ diff --git a/MisDataFun_Exe/MyLog4Net.pdb b/MisDataFun_Exe/MyLog4Net.pdb index c1669be..70ae174 100644 Binary files a/MisDataFun_Exe/MyLog4Net.pdb and b/MisDataFun_Exe/MyLog4Net.pdb differ diff --git a/MisDataFun_Exe/SIGNAL_MODEL.xlsx b/MisDataFun_Exe/SIGNAL_MODEL.xlsx index 8dc3517..2645cca 100644 Binary files a/MisDataFun_Exe/SIGNAL_MODEL.xlsx and b/MisDataFun_Exe/SIGNAL_MODEL.xlsx differ diff --git a/MisDataFunction/Function1051/MesServerFunction/Function1051.cs b/MisDataFunction/Function1051/MesServerFunction/Function1051.cs index f14cc0a..5f2f76e 100644 --- a/MisDataFunction/Function1051/MesServerFunction/Function1051.cs +++ b/MisDataFunction/Function1051/MesServerFunction/Function1051.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using MisDataFunDll; +using System.Configuration; namespace MesServerFunctions @@ -120,6 +121,46 @@ namespace MesServerFunctions fun_ReqTestResistor(e); break; } + if (ConfigurationManager.AppSettings["WebapiPostHeader_Systemcode"].ToString() == "MES_ZHDQ_126ZZ") + { + switch (e.TagTypeCodeID.ToString()) + { + case "58": // 请求AGV进站(上线) + if (tagValue == "1") MIS_BASE.WritePLC(28, m_OpName, true); + else MIS_BASE.WritePLC(28, m_OpName, false); + break; + case "59": // 请求前往总装点(上线) + if (tagValue == "1") MIS_BASE.WritePLC(29, m_OpName, true); + else MIS_BASE.WritePLC(29, m_OpName, false); + break; + case "76": // 请求AGV离开(上线) + if (tagValue == "1") MIS_BASE.WritePLC(30, m_OpName, true); + else MIS_BASE.WritePLC(30, m_OpName, false); + break; + case "61": // 请求AGV退出(自动) + if (tagValue == "1") MIS_BASE.WritePLC(31, m_OpName, true); + else MIS_BASE.WritePLC(31, m_OpName, false); + break; + case "62": // 请求AGV进入(自动) + if (tagValue == "1") MIS_BASE.WritePLC(32, m_OpName, true); + else MIS_BASE.WritePLC(32, m_OpName, false); + break; + case "63": // 请求AGV托盘举升 + if (tagValue == "1") MIS_BASE.WritePLC(33, m_OpName, true); + else MIS_BASE.WritePLC(33, m_OpName, false); + break; + case "64": // 请求AGV托盘下降 + if (tagValue == "1") MIS_BASE.WritePLC(34, m_OpName, true); + else MIS_BASE.WritePLC(34, m_OpName, false); + break; + case "65": // 请求AGV离站(自动) + if (tagValue == "1") MIS_BASE.WritePLC(35, m_OpName, true); + else MIS_BASE.WritePLC(35, m_OpName, false); + break; + default: + break; + } + } break; } } diff --git a/MisDataFunction/Function1051/OpcServer/EngineGetOver.cs b/MisDataFunction/Function1051/OpcServer/EngineGetOver.cs index ae34da7..ed7633f 100644 --- a/MisDataFunction/Function1051/OpcServer/EngineGetOver.cs +++ b/MisDataFunction/Function1051/OpcServer/EngineGetOver.cs @@ -18,13 +18,15 @@ namespace MesServerFunctions /// private void EngineTypeGetOver_PLC(object e) { - lock(lockBarcodeEngineTypeGetOver) + string opName = ""; + lock (lockBarcodeEngineTypeGetOver) { try { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); + opName = OpName; int tagValue = Convert.ToInt32(msgEvent.TagValue); //判断PLC机型与MES机型是否一致 if (tagValue == 1) @@ -61,7 +63,7 @@ namespace MesServerFunctions MIS_BASE.GetEngineTypeFromPLC_MES(OpName, out EngineTypeID_MES, out EngineType_MES, out EngineID_MES, out OrderForm_MES); // 读取MES区数据 校验MES区数据是否符合 同时判断是否此工件已工作过,若已工作过则弹出弹窗提示 - if (EngineTypeID == EngineTypeID_MES & EngineID == EngineID_MES & EngineType == EngineType_MES & OrderForm == OrderForm_MES) + if (EngineTypeID == EngineTypeID_MES & EngineID == EngineID_MES & EngineType == EngineType_MES & OrderForm == OrderForm_MES) { if (EngineTypeID == 0 || EngineID == "" || EngineType == "" || OrderForm == "") { @@ -71,12 +73,12 @@ namespace MesServerFunctions return; } - DataTable checkTable = MisDataFun.WorkOrderCheck(OpName,EngineID_MES,OrderForm_MES,EngineType_MES); + DataTable checkTable = MisDataFun.WorkOrderCheck(OpName, EngineID_MES, OrderForm_MES, EngineType_MES); int result = Convert.ToInt32(checkTable.Rows[0]["result"]); string resultMsg = checkTable.Rows[0]["msg"].ToString(); if (result != 2) { - + if (result == 3) { string msg = "【" + OpName + "】" + resultMsg; @@ -123,13 +125,16 @@ namespace MesServerFunctions } catch (Exception err) { - ////ApplicationLog.WriteLog(err, "Function08:EngineTypeGetOver_PLC"); + string logOpName = string.IsNullOrWhiteSpace(opName) ? "Function1051_EngineGetOver" : opName; + string logText = $"EngineTypeGetOver异常:异常={err.Message}"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(logOpName, logText, MisDataSaveDate.Helper.MesLogType.ERROR); + MyLog4Net.MyLogHelper.Error("Function1051_EngineGetOver", $"{logText}{Environment.NewLine}{err}"); } } - + } - + } } diff --git a/MisDataFunction/Function1051/OpcServer/MaterialsVerify.cs b/MisDataFunction/Function1051/OpcServer/MaterialsVerify.cs index 51130ff..043341c 100644 --- a/MisDataFunction/Function1051/OpcServer/MaterialsVerify.cs +++ b/MisDataFunction/Function1051/OpcServer/MaterialsVerify.cs @@ -27,12 +27,33 @@ namespace MesServerFunctions //判断PLC机型与MES机型是否一致 if (tagValue == 1) { - int EngineTypeID;//机型代码 - int PartPallet_Code;//托盘编号 - string EngineType;//机型 - string EngineID;//工件编号 - string OrderForm; - MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + int EngineTypeID = 0;//机型代码 + int PartPallet_Code = 0;//托盘编号 + string EngineType = "";//机型 + string OrderForm = ""; + MIS_BASE.Read_EngineID(OpName, out string PLCEngineID); + MIS_BASE.Read_EngineID_MES(OpName, out string MESEngineID); + string EngineID = string.IsNullOrEmpty(PLCEngineID) ? MESEngineID : PLCEngineID; + + if (string.IsNullOrEmpty(EngineID)) + { + string msg = $"【{OpName}】PLC与MES产品编号点位均为空,继续按空产品信息保存物料扫码记录!"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "MaterialsVerify " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + } + else + { + DataTable planDt = MisDataFun.XD_GetPlanInfoByEngineID(EngineID); + if (planDt.Rows.Count > 0) + { + OrderForm = planDt.Rows[0]["订单号"].ToString(); + EngineType = planDt.Rows[0]["产品型号"].ToString(); + } + else + { + string msg = $"【{OpName}】产品:{EngineID} 未在生产计划_派工订单_执行计划中查询到记录,继续保存物料扫码记录!"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "MaterialsVerify " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + } + } int MaterialsTypeCode = Convert.ToInt32(MIS_BASE.ReadPLC(201, OpName)); string MaterialsCode = MIS_BASE.ReadPLC(40, OpName).ToString(); diff --git a/MisDataFunction/Function1051/OpcServer/MesRead.cs b/MisDataFunction/Function1051/OpcServer/MesRead.cs index 80abd35..ab4a0de 100644 --- a/MisDataFunction/Function1051/OpcServer/MesRead.cs +++ b/MisDataFunction/Function1051/OpcServer/MesRead.cs @@ -8,7 +8,7 @@ namespace MesServerFunctions { partial class FunctionMES { - object lockMesRead = new object (); + object lockMesRead = new object(); /// /// 保存完成(针对半自动和手动压装工位) /// @@ -16,6 +16,9 @@ namespace MesServerFunctions /// private void MesRead(object e) { + string opName = ""; + string engineID = ""; + string orderForm = ""; try { int EngineTypeID; @@ -32,12 +35,15 @@ namespace MesServerFunctions { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); + opName = OpName; int tagValue = Convert.ToInt32(msgEvent.TagValue); if (tagValue == 1) { int qualityMask; - MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID,out PartPallet_Code, out OrderForm); + MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + engineID = EngineID; + orderForm = OrderForm; //保存数据到线首表 先保存到 北汽福田变速器序列号总线上线 用于之前判断是否重号 // 保存质量数据 @@ -49,9 +55,12 @@ namespace MesServerFunctions // 保存过站信息 MisDataFun.WorkStartInsert(OpName, qualityMask); - // 存追溯表数据 同时质量数据存入 接口表 + //保存质量数据到 接口表 + MisDataFun.SaveQualityInterfaceData(OpName, EngineID); + + // 调用工位完工 MisDataFun.WorkOrderOpWorkOver(OpName, EngineID, OrderForm); - + // 推送质量数据到MES的页面 SendMessageFun.SendInfomation("ShowTimelyQuality", "1&" + qualityMask.ToString(), OpName); @@ -76,7 +85,10 @@ namespace MesServerFunctions } catch (Exception err) { - ////ApplicationLog.WriteLog(err, "Function08:MesReadOver"); + string logOpName = string.IsNullOrWhiteSpace(opName) ? "Function1051_MesRead" : opName; + string logText = $"MesRead异常:订单号={orderForm}, 工件编号={engineID}, 异常={err.Message}"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(logOpName, logText, MisDataSaveDate.Helper.MesLogType.ERROR); + MyLog4Net.MyLogHelper.Error("Function1051_MesRead", $"{logText}{Environment.NewLine}{err}"); } } diff --git a/MisDataFunction/Function1052/OpcServer/EngineGetOver.cs b/MisDataFunction/Function1052/OpcServer/EngineGetOver.cs index 276639f..9c44355 100644 --- a/MisDataFunction/Function1052/OpcServer/EngineGetOver.cs +++ b/MisDataFunction/Function1052/OpcServer/EngineGetOver.cs @@ -14,12 +14,14 @@ namespace MesServerFunctions /// private void EngineTypeGetOver_PLC(object e) { + string opName = ""; { try { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); + opName = OpName; int tagValue = Convert.ToInt32(msgEvent.TagValue); //判断PLC机型与MES机型是否一致 if (tagValue == 1) @@ -61,7 +63,7 @@ namespace MesServerFunctions string msg = "【" + OpName + "】" + resultMsg; MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); SendMessage.AsyncSendMessage_Notice(OpName, msg); - MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "PLC传递机型 "+ msg, MisDataSaveDate.Helper.MesLogType.ERROR); + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "PLC传递机型 " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); } int parType = Convert.ToInt32(checkTable.Rows[0]["小机型"]); EngineTypeID = Convert.ToInt32(checkTable.Rows[0]["型号代码"]); @@ -108,7 +110,10 @@ namespace MesServerFunctions } catch (Exception err) { - ////ApplicationLog.WriteLog(err, "Function08:EngineTypeGetOver_PLC"); + string logOpName = string.IsNullOrWhiteSpace(opName) ? "Function1052_EngineGetOver" : opName; + string logText = $"EngineTypeGetOver异常:异常={err.Message}"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(logOpName, logText, MisDataSaveDate.Helper.MesLogType.ERROR); + MyLog4Net.MyLogHelper.Error("Function1052_EngineGetOver", $"{logText}{Environment.NewLine}{err}"); } } diff --git a/MisDataFunction/Function1052/OpcServer/MaterialsVerify.cs b/MisDataFunction/Function1052/OpcServer/MaterialsVerify.cs index 51130ff..043341c 100644 --- a/MisDataFunction/Function1052/OpcServer/MaterialsVerify.cs +++ b/MisDataFunction/Function1052/OpcServer/MaterialsVerify.cs @@ -27,12 +27,33 @@ namespace MesServerFunctions //判断PLC机型与MES机型是否一致 if (tagValue == 1) { - int EngineTypeID;//机型代码 - int PartPallet_Code;//托盘编号 - string EngineType;//机型 - string EngineID;//工件编号 - string OrderForm; - MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + int EngineTypeID = 0;//机型代码 + int PartPallet_Code = 0;//托盘编号 + string EngineType = "";//机型 + string OrderForm = ""; + MIS_BASE.Read_EngineID(OpName, out string PLCEngineID); + MIS_BASE.Read_EngineID_MES(OpName, out string MESEngineID); + string EngineID = string.IsNullOrEmpty(PLCEngineID) ? MESEngineID : PLCEngineID; + + if (string.IsNullOrEmpty(EngineID)) + { + string msg = $"【{OpName}】PLC与MES产品编号点位均为空,继续按空产品信息保存物料扫码记录!"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "MaterialsVerify " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + } + else + { + DataTable planDt = MisDataFun.XD_GetPlanInfoByEngineID(EngineID); + if (planDt.Rows.Count > 0) + { + OrderForm = planDt.Rows[0]["订单号"].ToString(); + EngineType = planDt.Rows[0]["产品型号"].ToString(); + } + else + { + string msg = $"【{OpName}】产品:{EngineID} 未在生产计划_派工订单_执行计划中查询到记录,继续保存物料扫码记录!"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "MaterialsVerify " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + } + } int MaterialsTypeCode = Convert.ToInt32(MIS_BASE.ReadPLC(201, OpName)); string MaterialsCode = MIS_BASE.ReadPLC(40, OpName).ToString(); diff --git a/MisDataFunction/Function1052/OpcServer/MesRead.cs b/MisDataFunction/Function1052/OpcServer/MesRead.cs index 17a29af..c189b51 100644 --- a/MisDataFunction/Function1052/OpcServer/MesRead.cs +++ b/MisDataFunction/Function1052/OpcServer/MesRead.cs @@ -16,6 +16,9 @@ namespace MesServerFunctions /// private void MesRead(object e) { + string opName = ""; + string engineID = ""; + string orderForm = ""; { try { @@ -33,6 +36,7 @@ namespace MesServerFunctions { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); + opName = OpName; int tagValue = Convert.ToInt32(msgEvent.TagValue); if (tagValue == 1) @@ -40,6 +44,8 @@ namespace MesServerFunctions int qualityMask; MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + engineID = EngineID; + orderForm = OrderForm; //MIS_BASE.GetEngineTypeFromPLC_MES(OpName, out EngineTypeID_MES, out EngineType_MES, out EngineID_MES, out OrderForm_MES); //保存数据到线首表 先保存到 北汽福田变速器序列号总线上线 用于之前判断是否重号 // 保存质量数据 @@ -51,7 +57,10 @@ namespace MesServerFunctions // 测量数据发动机在线状态 MisDataFun.WorkStartInsert(OpName, qualityMask); - // 存追溯表数据 + //保存质量数据到 接口表 + MisDataFun.SaveQualityInterfaceData(OpName, EngineID); + + // 调用工位完工 MisDataFun.WorkOrderOpWorkOver(OpName, EngineID, OrderForm); // 推送质量数据到MES的页面 @@ -79,7 +88,10 @@ namespace MesServerFunctions } catch (Exception err) { - ////ApplicationLog.WriteLog(err, "Function08:MesReadOver"); + string logOpName = string.IsNullOrWhiteSpace(opName) ? "Function1052_MesRead" : opName; + string logText = $"MesRead异常:订单号={orderForm}, 工件编号={engineID}, 异常={err.Message}"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(logOpName, logText, MisDataSaveDate.Helper.MesLogType.ERROR); + MyLog4Net.MyLogHelper.Error("Function1052_MesRead", $"{logText}{Environment.NewLine}{err}"); } } diff --git a/MisDataFunction/Function1053/DataAccess/DataAccess.cs b/MisDataFunction/Function1053/DataAccess/DataAccess.cs index cd36930..a7f91fa 100644 --- a/MisDataFunction/Function1053/DataAccess/DataAccess.cs +++ b/MisDataFunction/Function1053/DataAccess/DataAccess.cs @@ -1,7 +1,8 @@  + namespace MesServerFunctions { - partial class Function1053 + partial class FunctionMES { //针对“MIS.BizFacade.Dll”中没有的存储过程,在此类中新建 //新建原则:所有的函数用private,只允许在内部使用 diff --git a/MisDataFunction/Function1053/DataAccess/vssver2.scc b/MisDataFunction/Function1053/DataAccess/vssver2.scc index d045c26..1083b3a 100644 Binary files a/MisDataFunction/Function1053/DataAccess/vssver2.scc and b/MisDataFunction/Function1053/DataAccess/vssver2.scc differ diff --git a/MisDataFunction/Function1053/Db.cs b/MisDataFunction/Function1053/Db.cs index cce85a9..a0f37b3 100644 --- a/MisDataFunction/Function1053/Db.cs +++ b/MisDataFunction/Function1053/Db.cs @@ -10,7 +10,6 @@ namespace MesServerFunctions { public class Db { - } } diff --git a/MisDataFunction/Function1053/Function02.csproj.vspscc b/MisDataFunction/Function1053/Function02.csproj.vspscc deleted file mode 100644 index 0f0f36c..0000000 --- a/MisDataFunction/Function1053/Function02.csproj.vspscc +++ /dev/null @@ -1,10 +0,0 @@ -"" -{ -"FILE_VERSION" = "9237" -"ENLISTMENT_CHOICE" = "NEVER" -"PROJECT_FILE_RELATIVE_PATH" = "relative:MesServer.Function\\Function02" -"NUMBER_OF_EXCLUDED_FILES" = "0" -"ORIGINAL_PROJECT_FILE_PATH" = "" -"NUMBER_OF_NESTED_PROJECTS" = "0" -"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" -} diff --git a/MisDataFunction/Function1053/Function1053.csproj b/MisDataFunction/Function1053/Function1053.csproj index 9500104..ead2f8d 100644 --- a/MisDataFunction/Function1053/Function1053.csproj +++ b/MisDataFunction/Function1053/Function1053.csproj @@ -32,6 +32,7 @@ DEBUG;TRACE prompt 4 + AnyCPU false false @@ -48,17 +49,12 @@ ..\..\dll_common\MesWork.DeviceDriver.dll - - ..\..\..\Common\dll\MQTTnet.dll - - - ..\..\..\Common\dll\MQTTnet.Extensions.ManagedClient.dll - False ..\..\dll_common\Newtonsoft.Json.dll + @@ -93,18 +89,21 @@ - - - + + + + - + + + + - @@ -113,42 +112,14 @@ - - {f55da1a0-a982-4479-8c47-0d9a5aaf3e18} - 00MesWorkMqtt - - - {0d1af432-439a-4920-8692-43ae139f5530} - 01_01DoWhatPlc - - - {f434e066-4c59-47c8-aa82-6f48cc84501a} - 04-DataBaseAccess - - - {f0a0c525-03fd-428a-9b17-7f54aa0e4475} - 07BusinessFacade - - - {d98be764-adeb-488d-9714-61e308aa8201} - 08-WebFun_base - {90e76fb4-646d-45e2-95db-0b8ab4e465d6} - 09-MesDataFunction + 01-MesDataFunction {2f33d79d-1dff-4cda-b357-fcd5221cab9a} ExternalDataSync - - {e4eb6420-906d-4672-947a-ca33ddcdadfc} - 12SendMessageToWeb - - - {55b510c1-59e9-4bfd-ae84-d76d46f6e365} - 02-13.3MIS_FuntionSaveData - {1dc48c83-1842-4de8-acaf-26e1e7f7c58f} 00_MyLog4Net @@ -169,4 +140,4 @@ --> - \ No newline at end of file + diff --git a/MisDataFunction/Function1053/MesServerFunction/Fun_1053.cs b/MisDataFunction/Function1053/MesServerFunction/Fun_1053.cs deleted file mode 100644 index 7b44663..0000000 --- a/MisDataFunction/Function1053/MesServerFunction/Fun_1053.cs +++ /dev/null @@ -1,270 +0,0 @@ -using MesServerWork; -using MisDataFunDll; -using MisDataSaveDate; -using System.Collections.Generic; -using System.Threading; -using System.Xml.Linq; - -namespace MesServerFunctions -{ - public partial class FunctionMES - { - object lockFunWork; - //public void FunWork(DeviceDriver_BasicData.CustomeEvetnArgs e) - public void FunWork(string recData) - { - - - lockFunWork = new object(); - lock (lockFunWork) - { - List dataArray = MisDataFun.GetCmdStringList(recData); - //string[] dataArray = recData.Split('|'); - //if (dataArray.Count != 4) - //return; - //消息来源 - string m_Source = dataArray[0].ToString(); - //消息类型 Barcode - string m_Command = dataArray[1].ToString(); - //工位号 - string m_OpName = dataArray[2].ToString(); - //消息参数 - string m_Value = dataArray[3].ToString(); - - DeviceDriver_BasicData.CustomeEvetnArgs e = new DeviceDriver_BasicData.CustomeEvetnArgs();// = Newtonsoft.Json.JsonConvert.DeserializeObject(m_Value); - string tagValue; - - switch (m_Source) - { - case "BarCode": - e.OpName = m_OpName; - e.TagValue = m_Value; - fun_Barcode(e); - break; - case "WEB": - e.OpName = m_OpName; - e.TagValue = m_Command + "|" + m_Value; - fun_WebSubmit(e); - break; - case "PLC": - e = Newtonsoft.Json.JsonConvert.DeserializeObject(m_Value); - string TagID = e.TagID.ToString(); - switch (e.TagValue.ToString().ToLower()) - { - case "false": - tagValue = "0"; - break; - case "true": - tagValue = "1"; - break; - default: - tagValue = e.TagValue.ToString(); - break; - } - e.TagValue = tagValue; - switch (e.TagTypeCodeID.ToString()) - { - //PLC 工件到位 - case "2": - fun_WorkStart(e); - break; - //PLC 允许保存质量数据 - case "19": - fun_MesRead(e); - break; - //MES 保存数据完成 - case "20": - fun_MesReadOver(e); - break; - //PLC 申请上线 - case "43": - PartLoad(e); - break; - //PLC 传递机型 - case "44": - fun_EngineTypeGetOverPLC(e); - break; - //MES 合格放行 - case "51": - fun_ConfirmOkGo(e); - break; - //MES 不合格放行 - case "8": - fun_FalseGo(e); - break; - //PLC 工位合格标志 - case "21": - fun_IsOk(e); - break; - //MES 系统健康心跳 - case "14": - fun_HeartBeatMIS(e); - break; - //空料握手plc - case "49": - fun_Handshake(e); - break; - //待上料数量plc - case "38": - UpdateWait_NUM_PLC(e); - break; - case "63": - string S_plcStatus;//DBX501.5 PLC直通,1 强制放行 0 正常循环 - MIS_BASE.Read_TagTypeID(63, m_OpName, out S_plcStatus); - if (S_plcStatus.ToLower() != "true" || S_plcStatus.ToLower() == "1") - { - SendMessageFun.SendInfomation("PlcStatus", "0", m_OpName); - } - else - { - SendMessageFun.SendInfomation("PlcStatus", "1", m_OpName); - } - break; - //物料扫码完成 - case "65": - fun_MaterialsVerify(e); - break; - } - break; - } - } - } - - //1.工件到位后,PLC给MES传递机型(DBX0.4)(44), - //MES判断条码是否全部扫描完成 - //PLC给出允许保存(DBX100.2)(19),MES见到(DBX100.2)(19)为1后给出保存完成(DBX102.2)(20), - //PLC见到保存完成(DBX102.2)(20)为1后,清空允许保存(DBX100.2)(19), - //MES见到允许保存(DBX100.2)(19)为0后,清空保存完成(DBX102.2)(20) - //MES判断总合格标志(INT104)(21)为1后,给出合格放行(DBX2.5)(51) - /// - /// 扫描条码 - /// - /// - /// - public void fun_Barcode(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(Barcode, e); - } - - /// - /// 传递机型 - /// - /// - /// - public void fun_EngineTypeGetOverPLC(DeviceDriver_BasicData .CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(EngineTypeGetOver_PLC, e); - } - - /// - /// 合格放行 - /// - /// - /// - public void fun_ConfirmOkGo(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - // ThreadPool.QueueUserWorkItem(ConfirmOkGo, e); - } - - /// - /// 不合格放行 - /// - /// - /// - public void fun_FalseGo(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - // ThreadPool.QueueUserWorkItem(FalseGO, e); - } - - /// - /// 允许保存 - /// - /// - /// - public void fun_MesRead(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(MesRead, e); - } - - /// - /// 物料扫码完成 - /// - public void fun_MaterialsVerify(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(MaterialsVerify, e); - } - - /// - /// 保存完成 - /// - /// - /// - public void fun_MesReadOver(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - // ThreadPool.QueueUserWorkItem(MesReadOver, e); - } - - /// - /// 工件到位离开(清空所有的MES信号) - /// - /// - /// - public void fun_WorkStart(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(WorkStart, e); - } - - /// - /// 处理WEB页面发送过来的请求(m_Command + "|" + m_Value;) - /// - /// - /// - public void fun_WebSubmit(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(WebSubmit, e); - } - - - /// - /// 工位是否合格 - /// - /// - /// - public void fun_IsOk(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - ThreadPool.QueueUserWorkItem(IsOk, e); - } - - /// - /// 系统健康心跳监测 - /// - /// - /// - public void fun_HeartBeatMIS(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - // ThreadPool.QueueUserWorkItem(HeartBeat, e); - } - - - /// - /// 空料握手plc - /// - public void fun_Handshake(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - //ThreadPool.QueueUserWorkItem(Handshake_Fun, e); - } - - - /// - /// MES实时保存质量数据 - /// - /// - /// - public void fun_MesSaveNowData(DeviceDriver_BasicData.CustomeEvetnArgs e) - { - // ThreadPool.QueueUserWorkItem(MesSaveNowData, e); - } - - - } -} diff --git a/MisDataFunction/Function1053/MesServerFunction/vssver2.scc b/MisDataFunction/Function1053/MesServerFunction/vssver2.scc index a246f67..775bb6c 100644 Binary files a/MisDataFunction/Function1053/MesServerFunction/vssver2.scc and b/MisDataFunction/Function1053/MesServerFunction/vssver2.scc differ diff --git a/MisDataFunction/Function1053/Methods/EngineGetOverBaseWork.cs b/MisDataFunction/Function1053/Methods/EngineGetOverBaseWork.cs index 46e4f96..155058e 100644 --- a/MisDataFunction/Function1053/Methods/EngineGetOverBaseWork.cs +++ b/MisDataFunction/Function1053/Methods/EngineGetOverBaseWork.cs @@ -4,83 +4,108 @@ using System.Threading; using MesServerWork; using MisDataFunDll; +//using SystemFramework; +using WebApi; + + namespace MesServerFunctions { partial class FunctionMES { /// - /// 正常逻辑工作(传递机型) + /// 分线上总线的数量 + /// + public static int SubLineLoadPartCount = 2; + /// + /// 分线上总线已经匹配的数量 + /// + public static int SubLineLoadPartCountMatch = 0; + /// + /// 正常逻辑工作 /// /// /// /// /// /// - private void EngineTypeGetOver_PLC_Work(string OpName, int EngineTypeID, string EngineType, string EngineID, int PartPallet_Code, string OrderForm) + private void EngineTypeGetOver_PLC_Work(string OpName, int EngineTypeID, string EngineType, string EngineID, int PartPallet_Code,string OrderForm) { int IsAllowWork; int RepairPartStatusPLC = 0; + int MES_QualityMask = 1; if (EngineTypeID <= 0 || EngineID.Length == 0 || EngineType.Length == 0) { string msg = "【" + OpName + "】" + "PLC传递机型为空!"; MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); - SendMessageFun.AsyncSendMessage_Notice(OpName, msg); + SendMessageFun.AsyncSendMessage_Notice(OpName, "PLC传递机型为空"); return; } - //电子看板_装配零件_临时表_增加_北汽 - //第二步,将零件信息转移到零件_临时表中 - MisDataFun.MesServer_Process_EngineTypeOverBQ(OpName); + //初始化物料临时表 + //第二步,将零件信息转移到零件_临时表中(本地BOM与订单BOM的选择显示关系) + //BaseDataSystemMES.MesServer_Process_EngineTypeOver_BQ_FirstOP(OpName); - //通知web显示 - //MIS_BASE.Read_PalletInfo(OpName, out MES_QualityMask);//合格标志 合格标志暂时改为即时响应式的 - MIS_BASE.Read_RepairStatus_PLC(OpName, out RepairPartStatusPLC);//返修标志 - //SendMessageFun.SendInfomation("QualityMask", Convert.ToString(MES_QualityMask), OpName);//显示合格标志 - SendMessageFun.SendInfomation("RepairPartStatusPLC", Convert.ToString(RepairPartStatusPLC), OpName);//显示返修标志 + //5 显示订单、机型信息 线首工位用 + SendMessage.ShowMoby_FirstOpName(OpName); + //3显示操作指导图片 PicShow_String_FirstOpName + SendMessage.PicShow_FirstOpName(OpName); + //1(直接在界面通过选择机型确认工序内容) + SendMessage.ProcessList_FirstOpName(OpName); + //界面显示物料信息 + SendMessage.MaterialList_FirstOpName(OpName); //第四步,获取是否允许工作 MisDataFun.MesServer_Judge_IsCanWork(OpName, out IsAllowWork); - //暂时先定义为扫描完成才能进行压装工作,因为考虑到工作完成后,操作工未必会去扫描物料的情况 + // 暂时先定义为扫描完成才能进行压装工作,因为考虑到工作完成后,操作工未必会去扫描物料的情况 if (IsAllowWork == 1) { - MIS_BASE.Write_WorkStart(OpName, true); + //通知PLC允许工作,允许工作在保存完成时清空 MIS_BASE.Write_FixAllow(OpName, true); - MIS_BASE.Write_EngineTypeGetOver_PLC(OpName, true); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.FixAllow, "1"); + + //调用工厂MES开工接口 + WebApi.CALL_Inerface_DataHandle.CALL_Inerface_JobStart(OpName, EngineID, OrderForm); + } else { SendMessageFun.AsyncSendMessage_Notice(OpName, "请扫描物料!"); } - SendMessageFun.SendMessage("1235", "1111", OpName); - } - - /// - /// 二次工作 - /// - /// - private void EngineTypeGetOver_PLC_Work_two(string OpName) - { - int EngineTypeID;//机型代码 - int PartPallet_Code;//托盘编号 - - string EngineType;//机型 - string EngineID;//工件编号 - string OrderForm; - MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); - EngineTypeGetOver_PLC_Work(OpName, EngineTypeID, EngineType, EngineID, Convert.ToInt32(PartPallet_Code), OrderForm); } + + /// - /// 跳过二次工作 + /// 保存MOBY信息 /// /// - private void EngineTypeGetOver_PLC_Work_Skip(string OpName) + /// + /// + /// + private void SaveMobyMessage(string OpName, int engineTypeID, string engineType, string engineID, string orderForm) { - //MIS_BASE.Write_MesReadOver(OpName, true); - MIS_BASE.Write_MaterialVerifyOver(OpName, true); + + if (MIS_BASE.hashtable_EngineGetOver_EngineTypeID == null) + { + MIS_BASE.InitHashtable_MesServerCode(); + } + if (MIS_BASE.hashtable_EngineGetOver_EngineTypeID.ContainsKey(OpName)) + { + MIS_BASE.hashtable_EngineGetOver_EngineTypeID[OpName] = engineTypeID; + } + if (MIS_BASE.hashtable_EngineGetOver_EngineType.ContainsKey(OpName)) + { + MIS_BASE.hashtable_EngineGetOver_EngineType[OpName] = engineType; + } + if (MIS_BASE.hashtable_EngineGetOver_EngineID.ContainsKey(OpName)) + { + MIS_BASE.hashtable_EngineGetOver_EngineID[OpName] = engineID; + } + if (MIS_BASE.hashtable_EngineGetOver_OrderForm.ContainsKey(OpName)) + { + MIS_BASE.hashtable_EngineGetOver_OrderForm[OpName] = orderForm; + } } /// @@ -89,27 +114,178 @@ namespace MesServerFunctions /// 工位号 private void IsNeedRepaire_OK(string OpName) { - //string orderForm = ""; - //int engineTypeID; - //string engineType = ""; - //string engineID = ""; - //string palletCode = ""; - //int isRepair; - //string repairCode = ""; - ////从监控系统中查询出本工位信息 - //MisDataFun.OpName_MIS_Moby_Select(OpName, - //out orderForm, out engineTypeID, out engineType, - //out engineID, out palletCode, out isRepair, out repairCode); - //EngineTypeGetOver_PLC_Work(OpName, engineTypeID, engineType, engineID, Convert.ToInt32(palletCode), orderForm); + int isRepair; + int engineTypeID; + + string engineType = ""; + string engineID = ""; + string palletCode = ""; + string orderForm = ""; + string repairCode = ""; + //从监控系统中查询出本工位信息 + //BaseDataSystemMES.OpName_MIS_Moby_Select(OpName, + //out orderForm, out engineTypeID, out engineType, + //out engineID, out palletCode, out isRepair, out repairCode); + + //EngineTypeGetOver_PLC_Work(OpName, engineTypeID, engineType, engineID, Convert.ToInt32(palletCode),orderForm); + } + /// + /// 正常匹配分线和总线 + /// + /// + /// 总线工件号 + /// 总线工件机型代码 + /// 总线工件机型 + private void Match(string opName, string engineID, int engineTypeID, string engineType, int PartPallet_Code) + { + try + { + bool m_EngineGetOver_PLC_SubLine; + int engineTypeID_SubLine; + int partPallet_Code_SubLine; + int PalletInfo = 1;//总线托盘状态 + + string opName_SubLine = "";//分线工件信息 + string engineID_SubLine; + string engineType_SubLine; + string AlarmStr; + if (MIS_BASE.hashtable_OpNameRepair == null) + { + MIS_BASE.InitHashtable_MesServerCode(); + } + //第一步:获取分线中间交互工位号 + if (MIS_BASE.hashtable_OpNameRepair.ContainsKey(opName)) + { + opName_SubLine = MIS_BASE.hashtable_OpNameRepair[opName].ToString(); + } + if (opName_SubLine == "") + { + return; + } + + //第二步:获取分线传递机型信号 + MIS_BASE.Read_EngineGetOver_PLC(opName_SubLine, out m_EngineGetOver_PLC_SubLine); + if (!m_EngineGetOver_PLC_SubLine) return;//必须工件同时到位才能进行匹配 + + //第三步:判断合格标志 + MIS_BASE.Read_PalletInfo(opName_SubLine, out PalletInfo); + if (PalletInfo == 2) return; //若不合格则返回不进行匹配 + string OrderForm; + //第四步:获取分线的信息,匹配验证 + MIS_BASE.GetEngineTypeFromPLC(opName_SubLine, out engineTypeID_SubLine, out engineType_SubLine, out engineID_SubLine, out partPallet_Code_SubLine,out OrderForm); + //判断分线数据是否合格 + //if (!BaseDataSystemMES.QulityDataVerify(opName, engineID_SubLine, out AlarmStr) && !BaseDataSystemMES.QualityVerifyStatus_Hash_Read(opName)) + //{ + // SendInfomation("LineoutAlert", AlarmStr, opName); + // return; + //} + + //if (engineTypeID_SubLine == engineTypeID) + //{ + // BaseDataSystemMES.SubLineLoadPartCountMatch_Select(opName, out SubLineLoadPartCountMatch); + // SubLineLoadPartCountMatch = SubLineLoadPartCountMatch + 1; + // BaseDataSystemMES.SubLineLoadPartCountMatch_Update(opName, SubLineLoadPartCountMatch); + + + // BaseDataSystemMES.MailLineAndSubLineData_Insert(engineID, engineTypeID, engineType, engineID_SubLine);//分线上总线数据转移 + // MIS_BASE.Write_Match(opName, true);//匹配结果 + // MIS_BASE.Write_MatchingCompleted(opName, true);//匹配完成 + // if(SubLineLoadPartCountMatch== SubLineLoadPartCount) + // { + // MIS_BASE.Write_FixAllow(opName, true); + // SubLineLoadPartCountMatch = 0; + // BaseDataSystemMES.SubLineLoadPartCountMatch_Update(opName, SubLineLoadPartCountMatch); + + // } + + // SendMessageFun.SendInfomation("MatchSuccess", "1", opName); + // SendMessageFun.SendMessage(opName, 1, "Match");//匹配结果 + //} + //else + //{ + // MIS_BASE.Write_Match(opName, false);//匹配结果 + // MIS_BASE.Write_MatchingCompleted(opName, true);//匹配完成//68:1、取消返修;2、匹配成功 自己监控发送 MES|MatchingCompleted + + // //发送匹配完成和匹配结果信息 + // SendMessageFun.AsyncSendMessage_Notice(opName,"匹配失败,工件型号不匹配!"); + // SendMessageFun.SendInfomation("MatchSuccess", "0", opName); + // SendMessageFun.SendMessage(opName, 0, "Match");//匹配结果 + //} + + } + catch (Exception err) + { + ////ApplicationLog.WriteLog("Match:" + err.ToString()); + + } } + + /// - /// 更新待上料数量 + /// 强制匹配分线和总线 /// - /// - private void UpdateWait_NUM_PLC(object e) + /// + private void ForceMatch(string opName) { + try + { + //bool m_EngineGetOver_PLC_SubLine; + //bool m_EngineGetOver_PLC; + + //int engineTypeID_SubLine; + //int engineTypeID; + //int partPallet_Code_SubLine; + //int partPallet_Code; + + //string opName_SubLine = "";//分线工件信息 + //string engineID_SubLine; + //string engineType_SubLine; + //string engineID; + //string engineType; + //if (MIS_BASE.hashtable_OpNameRepair == null) + //{ + // MIS_BASE.InitHashtable_MesServerCode(); + //} + ////获取分线中间交互工位号 + //if (MIS_BASE.hashtable_OpNameRepair.ContainsKey(opName)) + //{ + // opName_SubLine = MIS_BASE.hashtable_OpNameRepair[opName].ToString(); + //} + //if (opName_SubLine == "") + //{ + // return; + //} + + //MIS_BASE.Read_EngineGetOver_PLC(opName_SubLine, out m_EngineGetOver_PLC_SubLine);//1:读取分线工件到位的传递机型信号。 + + //if (!m_EngineGetOver_PLC_SubLine) return;//必须工件同时到位才能进行匹配 + + //MIS_BASE.Read_EngineGetOver_PLC(opName, out m_EngineGetOver_PLC);//2:读取总线工件到位的传递机型信号。 + + //if (!m_EngineGetOver_PLC) return;//必须工件同时到位才能进行匹配 + //string OrderForm; + //MIS_BASE.GetEngineTypeFromPLC(opName_SubLine, out engineTypeID_SubLine, out engineType_SubLine, out engineID_SubLine, out partPallet_Code_SubLine,out OrderForm);//获取分线的信息 + //MIS_BASE.GetEngineTypeFromPLC(opName, out engineTypeID, out engineType, out engineID, out partPallet_Code, out OrderForm); + + //Mis.MailLineAndSubLineData_Insert(engineID, engineTypeID, engineType, engineID_SubLine);//分线上总线数据转移 + + //MIS_BASE.Write_Match(opName, true);//匹配结果 + //MIS_BASE.Write_MatchingCompleted(opName, true);//匹配完成 + + //SendMessageFun.SendInfomation("MatchSuccess", "1", opName);//界面显示匹配成功 + + //MIS_BASE.Write_FixAllow(opName, true);//允许PLC工作 + + ////发送匹配完成和匹配结果信息 + //sendmessage(opName, 1, "MatchingComplete");//匹配完成 + //sendmessage(opName, 1, "Match");//匹配结果 + } + catch + { + + } } } } diff --git a/MisDataFunction/Function1053/Methods/vssver2.scc b/MisDataFunction/Function1053/Methods/vssver2.scc index 7782f6f..7b1a830 100644 Binary files a/MisDataFunction/Function1053/Methods/vssver2.scc and b/MisDataFunction/Function1053/Methods/vssver2.scc differ diff --git a/MisDataFunction/Function1053/OpcServer/Barcode.cs b/MisDataFunction/Function1053/OpcServer/Barcode.cs index 24a7187..d7549ae 100644 --- a/MisDataFunction/Function1053/OpcServer/Barcode.cs +++ b/MisDataFunction/Function1053/OpcServer/Barcode.cs @@ -1,17 +1,16 @@ using System; -using System.Data; -using System.Windows.Forms; +using System.Threading; +using System.Xml.Linq; + +//using SystemFramework; using MesServerWork; -using MisDataFunDll; namespace MesServerFunctions { partial class FunctionMES { - /// - ///1.扫描配送单号,用于接收物料,扫描单号的时候,将接收的物料信息显示在“物料拉动”Tab区域 - ///2.扫描料箱标签/看板卡,用于追溯物料批次信息 - ///3.扫描零件条码,根据零件图号进行防错 + object lockBarcode = new object(); + ///第一步,判断条码类型,根据条码类型,执行对应的存储过程 ///第二步,条码类型(将扫描的条码保存到对应的表中) ///第三步,扫描完成之后给出允许工作信号 @@ -21,55 +20,213 @@ namespace MesServerFunctions /// public void Barcode(object e) { - + lock(lockBarcode) { try { - DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; - string OpName = Convert.ToString(msgEvent.OpName); - string barcode = Convert.ToString(msgEvent.TagValue); - string AlarmStr = ""; + //DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; + //string OpName = Convert.ToString(msgEvent.OpName); + ////+*************DbName***************** + //string DbName = Convert.ToString(msgEvent.OpName); + //string barcode = Convert.ToString(msgEvent.TagValue); - int IsAllowWork; - bool IsSuccess = false; + //int EngineTypeID;//机型代码 + //string EngineType;//机型 + //string EngineID;//工件编号 - MisDataFun.PartMaterial_DM_Update(OpName, barcode, out IsSuccess); - if (!IsSuccess) - { - SendMessageFun.AsyncSendMessage_Notice(OpName, "条码无效,请确认!"); - return; - } - else - { - SendMessageFun.SendInfomation("MaterialList", "1", OpName);//通知界面更新零件信息 - } + //string OrderForm; + //int Recipe1; + //int Recipe2; - //获取是否允许工作 - MisDataFun.MesServer_Judge_IsCanWork(OpName, out IsAllowWork); + //bool IsNotRepeatedNumber = false; + ////1:获得申请上线信息后,扫描条码才处理业务 + //bool ispartload; + ////(115) + //int PTO; + ////(118)0=不检测;1=24V,2=12V。检测线上线工位扫描总成条码,根据BOM,查出 + //int NgearSwitch; + ////(119)0=不检测;1=24V,2=12V。检测线上线工位扫描总成条码,根据BOM,查出 + //int RgearSwitch; + ////(120)0=不检测;1=检测。检测线上线工位扫描总成条码,根据BOM,查出 + //int SpeedSensor; + ////(121)例如:5S 400。检测线上线工位扫描总成条码,根据BOM,查出 + //string PartTypeMid; + ////(122) 0=不检测;1=24V,2=12V。检测线上线工位扫描总成条码,根据BOM,查出 + //int Tcu_V; + ////判断工件是否到位 + //MIS_BASE.Read_WorkStart(OpName, out ispartload); + //if (!ispartload) + //{ + // SendMessageFun.AsyncSendMessage_Notice(OpName, "请检查设备是否到位(DBX500.1=1)"); + // return; + //} + ////判断设备是否申请上线 + //MIS_BASE.Read_PartLoad(OpName, out ispartload); + //if (!ispartload) + //{ + // SendMessageFun.AsyncSendMessage_Notice(OpName, "请检查设备是否申请上线(DBX500.3=1)"); + // return; + //} + //// 判读条码是变速器序列号条码号还是物料号 小机型*日月年* 流水号(给起始号 + 数量) + //// 选小机型 从北汽福田BOM中选 得先维护BOM + //// 变速器序列号 '1333 050 062*16012023*30000001' - if (IsAllowWork == 1) - { - // 保存物料信息 - MisDataFun.Material_Insert(OpName, 1); + ////扫描完变速器序列号条码号 true + //bool isGetOver_PLC = false; + ////判断上线工位,MES 是否将工件流水号、机型等信息已经写入到PLC了 + // MIS_BASE.Read_EngineGetOver_PLC(OpName, out isGetOver_PLC); - SendMessageFun.SendMessage("24", "11", OpName); + ////如果工件流水号、机型等信息没有写入PLC,扫描的条码按工件流水号进行验证 + ////否则按装配物料进行验证 + //if (!isGetOver_PLC) + //{ - // 物料验证完成 - MIS_BASE.Write_MaterialVerifyOver(OpName, true); - - //通知PLC允许工作,允许工作在保存完成时清空 - MIS_BASE.Write_FixAllow(OpName, true); - } - else - { - SendMessageFun.AsyncSendMessage_Notice(OpName, "条码无效,请确认!"); - } + // if (barcode.Split('*').Length > 2) + // { + // //2: 判断是否重号, 从数据库获得机型、机型代码等信息 + // string partSn = barcode; + // EngineID = barcode; + + // MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineID_MES, EngineID); + + // //Db.GetEngineType( partSn, out EngineTypeID, out EngineType, out EngineID, out IsRepeatedNumber); + // //Db.GetEngineType( partSn, out EngineTypeID, out EngineType, out EngineID, out IsRepeatedNumber); + + // //IsRepeatedNumber true 不重号;false 重号; + // IsNotRepeatedNumber = BaseDataSystemMES.EngineTypeID_IsNotRepeatedNumber(partSn); + // if (IsNotRepeatedNumber) + // { + // BaseDataSystemMES.GetEngineTypeUpLoadOpName(partSn, OpName, out EngineTypeID, out EngineType, out OrderForm, out Recipe1, out Recipe2); + + // //MIS_BASE.Write_EngineID_MES(OpName, EngineID); + // //MIS_BASE.Write_EngineTypeID_MES(OpName, EngineTypeID); + // //MIS_BASE.Write_EngineType_MES(OpName, EngineType); + // //MIS_BASE.Write_OrderForm_MES(OpName, OrderForm); + + + // BaseDataSystemMES.UpLoadPTO(EngineType, out PTO, out NgearSwitch, out RgearSwitch, out SpeedSensor, out PartTypeMid, out Tcu_V); + // //PTO + // MIS_BASE.WritePLC(115, OpName, PTO); + // //空挡开关检测 + // MIS_BASE.WritePLC(95, OpName, NgearSwitch); + // //倒挡开关检测 + // MIS_BASE.WritePLC(96, OpName, RgearSwitch); + // //里程表检测 + // MIS_BASE.WritePLC(97, OpName, SpeedSensor); + // //大机型扩展 + // MIS_BASE.WritePLC(98, OpName, PartTypeMid); + // //TCU + // MIS_BASE.WritePLC(122, OpName, Tcu_V); + // string tagStartAdr;//= "DB411.10"; + + // // 先查询配方号 根据工位号 去moby表查配方号 + // // 根据配方号 去配方表查配方数据 + // // 写入配方数据 + // BaseDataSystemMES.PLCRcipeCurrent(OpName, out byte[] bytes, out tagStartAdr); + // DtWebApi.ReadWritePLC.Write_TagValueByTagTypeID("94", OpName, System.Text.Encoding.ASCII.GetString(bytes)); + // ////将产品信息写入PLC + // MIS_BASE.Write_EngineTypeID_MES(OpName, EngineTypeID); + // MIS_BASE.Write_EngineType_MES(OpName, EngineType); + // MIS_BASE.Write_EngineID_MES(OpName, EngineID); + // MIS_BASE.Write_OrderForm_MES(OpName, OrderForm); + + // //写入到数据库的[北汽福田工位状态监控MOBY]表中 + // //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineTypeID_MES, EngineTypeID.ToString()); + // //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineType_MES, EngineType); + // MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineID_MES, EngineID); + // //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.OrderForm_MES, OrderForm); + + + // // 工位号],[订单号],[产品型号代码],[变速器序列号],[发动机型号],[机型基本代码],[变速器总成号] ,[托盘号] + // // [产品型号代码_MES],[变速器序列号_MES],[发动机型号_MES] + // // [机床上电],[循环开始],[机床故障],[上料无件],[下料堵塞],[工件到位] + // // [传递机型],[申请上件],[允许保存],[保存完成],[合格标志],[前序合格] + // // [工号],[班次],[是否返修件],[合格放行],[不合格放行],[扫描条码] + + // //MisDataFun.OpName_MIS_MOBY_Insert(OpName, "产品型号代码_MES", EngineTypeID.ToString()); + // //MisDataFun.OpName_MIS_MOBY_Insert(OpName, "发动机型号_MES", EngineType); + + // MIS_BASE.Write_EngineTypeGetOver_MES(OpName, true); + + // //Thread.Sleep(5000); + // //MIS_BASE.Write_EngineTypeGetOver_MES(OpName, false); + + // //等待PLC将数据写入RFID;写入PLC的DB块,通知MES验证RFID机型数据是否正确传递 + + // //通知web显示 + // SendMessage.ShowMoby(OpName); + // //SendMessageFun.SendMessage("1235", "1111", OpName); + // } + // else + // { + // SendMessageFun.SendInfomation("EngineIDRepeat", "partSn", OpName); + // } + // } + // else + // { + // SendMessageFun.AsyncSendMessage_Notice(OpName, "变速器序列号格式不正确,请确认!"); + + // } + //} + //else//验证物料 + //{ + // //物料号 + // { + // //读取PLC的传递机型信号 + // bool tagValue; + // MIS_BASE.Read_EngineGetOver_PLC(OpName, out tagValue); + // if (tagValue) + // { + // //验证物料 + // BaseDataSystemMES.PartMaterial_DM_Update(OpName, barcode, out bool IsSuccess); + // if (!IsSuccess)//???? + // { + // SendMessageFun.AsyncSendMessage_Notice(OpName, "条码无效,请确认"); + // return; + // } + // else + // { + // SendMessageFun.SendMessageFun.SendInfomation("MaterialList", "1", OpName);//通知界面更新零件信息 + // } + // //判断物料是否验证完成 + // BaseDataSystemMES.MesServer_Judge_IsCanWork(OpName, out int IsAllowWork); + + + // if (IsSuccess) + // { + // if (IsAllowWork == 1) + // { + // //移到允许保存信号中 + // //BaseDataSystemMES.Material_Insert(OpName, 1); + + // ////更新订单完工数量及物料 + // SendMessageFun.SendMessage("24", "11", OpName); + + // //物料验证完成,通知PLC允许工作,允许工作在保存完成时清空 + // MIS_BASE.Write_FixAllow(OpName, true); + // } + // else + // { + // SendMessageFun.AsyncSendMessage_Notice(OpName, "请扫描物料!"); + // } + // } + // else + // { + // SendMessageFun.AsyncSendMessage_Notice(OpName, "PLC未传递机型"); + // } + // } + // else + // { + // SendMessage.AsyncSendMessage_Notice(OpName, "产品上线后,PLC获得变速器序列号后,再验证物料!"); + // } + + // } + //} } catch (Exception err) { - ////ApplicationLog.WriteLog(err, "Function02:Barcode"); + ////ApplicationLog.WriteLog(err, "Function08:Barcode"); } - } } diff --git a/MisDataFunction/Function1053/OpcServer/EngineGetOver.cs b/MisDataFunction/Function1053/OpcServer/EngineGetOver.cs index f46a8c4..ed7633f 100644 --- a/MisDataFunction/Function1053/OpcServer/EngineGetOver.cs +++ b/MisDataFunction/Function1053/OpcServer/EngineGetOver.cs @@ -1,15 +1,16 @@ using System; using System.Data; -using System.Windows.Forms; -using System.Xml.Linq; -//using SystemFramework; using MesServerWork; using MisDataFunDll; +//using SystemFramework; namespace MesServerFunctions { partial class FunctionMES { + object lockBarcodeEngineTypeGetOver = new object(); + + /// /// PLC传递机型处理 /// @@ -17,56 +18,123 @@ namespace MesServerFunctions /// private void EngineTypeGetOver_PLC(object e) { + string opName = ""; + lock (lockBarcodeEngineTypeGetOver) + { + try { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); - //int tagValue = Convert.ToInt32(msgEvent.TagValue); - if(msgEvent.TagValueUp.ToString() == "6") + opName = OpName; + int tagValue = Convert.ToInt32(msgEvent.TagValue); + //判断PLC机型与MES机型是否一致 + if (tagValue == 1) { - MIS_BASE.Write_FixAllow(OpName, false); - string Program_No = ""; - MisDataFun.GetEngineType_Order(OpName, Program_No, out int EngineTypeID, out string EngineType, out string EngineID, out string OrderForm, out int isCheckOk, out int planCount, out int haveUplaodCount, out int remainingQuantity, out string msg2); - if (isCheckOk == 2) + bool MesRead = false; + + int EngineTypeID;//机型代码 + int PartPallet_Code;//托盘编号 + + string EngineType;//机型 + string EngineID;//工件编号 + + int EngineTypeID_MES;//机型代码 + string EngineType_MES;//机型 + string EngineID_MES;//工件编号 + string OrderForm_MES; + + //上线工位清MES传递机型信号 + MIS_BASE.Write_EngineTypeGetOver_MES(OpName, false); + + MIS_BASE.Read_QualityData_Read_CF(OpName, out MesRead); + //第一步,判断允许保存和保存完成信号是否全部被清空,若未清空,则通知复位MES&PLC + if (MesRead) { - string msg = "【" + OpName + "】" + msg2; - SendMessage.AsyncSendMessage_Notice(OpName, msg); - MyLog4Net.MyLogHelper.Error("PartLoad", msg); + //未能清空信号,请求复位 + string msg = "【" + OpName + "】" + "未能清空MesRead信号,请求复位!"; + SendMessageFun.SendInfomation("AskReset", "1", OpName); + MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); + return; + } + + string OrderForm; + MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + MIS_BASE.GetEngineTypeFromPLC_MES(OpName, out EngineTypeID_MES, out EngineType_MES, out EngineID_MES, out OrderForm_MES); + + // 读取MES区数据 校验MES区数据是否符合 同时判断是否此工件已工作过,若已工作过则弹出弹窗提示 + if (EngineTypeID == EngineTypeID_MES & EngineID == EngineID_MES & EngineType == EngineType_MES & OrderForm == OrderForm_MES) + { + if (EngineTypeID == 0 || EngineID == "" || EngineType == "" || OrderForm == "") + { + string msg = "【" + OpName + "】" + "传递机型数据为空!"; + MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); + SendMessage.AsyncSendMessage_Notice(OpName, msg); + return; + } + + DataTable checkTable = MisDataFun.WorkOrderCheck(OpName, EngineID_MES, OrderForm_MES, EngineType_MES); + int result = Convert.ToInt32(checkTable.Rows[0]["result"]); + string resultMsg = checkTable.Rows[0]["msg"].ToString(); + if (result != 2) + { + + if (result == 3) + { + string msg = "【" + OpName + "】" + resultMsg; + MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); + SendMessage.AsyncSendMessage_Notice(OpName, msg); + } + //写入到数据库的[北汽福田工位状态监控MOBY]表中 + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.EngineTypeID, EngineTypeID.ToString()); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.EngineType, EngineType); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.EngineID, EngineID); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.OrderForm, OrderForm); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.PartPallet_Code, PartPallet_Code.ToString()); + //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineTypeID, EngineTypeID.ToString()); + //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineType, EngineType); + //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineID, EngineID); + //MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.OrderForm, OrderForm); + EngineTypeGetOver_PLC_Work(OpName, EngineTypeID, EngineType, EngineID, PartPallet_Code, OrderForm); + + SendMessageFun.SendMessage("5123", "11111", OpName); + + // 将工序数据转入临时表中 + //BaseDataSystemMES.ProcessDataToTemp(OpName, EngineTypeID, OrderForm, EngineID); + } + else + { + string msg = "【" + OpName + "】" + resultMsg; + MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); + SendMessage.AsyncSendMessage_Notice(OpName, msg); + } return; } else { - MIS_BASE.Write_EngineTypeID_MES(OpName, EngineTypeID); - MIS_BASE.Write_EngineType_MES(OpName, EngineType); - MIS_BASE.Write_EngineID_MES(OpName, EngineID); - MIS_BASE.Write_OrderForm_MES(OpName, OrderForm); - - MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.WorkStartIn, DateTime.Now.ToString()); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineTypeID, EngineTypeID.ToString()); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineType, EngineType); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineID, EngineID); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.OrderForm, OrderForm); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineTypeID_MES, EngineTypeID.ToString()); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineType_MES, EngineType); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.EngineID_MES, EngineID); - MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.OrderForm_MES, OrderForm); - - MIS_BASE.Write_EngineTypeID_MES(OpName, EngineTypeID); - MIS_BASE.Write_EngineType_MES(OpName, EngineType); - MIS_BASE.Write_EngineID_MES(OpName, EngineID); - MIS_BASE.Write_OrderForm_MES(OpName, OrderForm); - - EngineTypeGetOver_PLC_Work(OpName, EngineTypeID, EngineType, EngineID, 0, OrderForm); + string msg = "【" + OpName + "】" + "PLC与MES信息不一致!"; + MyLog4Net.MyLogHelper.Error("EngineTypeGetOver", msg); + SendMessage.AsyncSendMessage_Notice(OpName, msg); } + + } + else + { + MIS_BASE.Write_FixAllow(OpName, false); } } catch (Exception err) { - // 保存出错日志 1.申请上线 2.传递机型 3.允许保存 4.扫码 - MisDataSaveDate.FuntionMesRead.Alarm_SaveFileLog4Error(System.Reflection.MethodBase.GetCurrentMethod().Name, e, "Fun1053", err); - ////ApplicationLog.WriteLog(err, "Function02:EngineTypeGetOver_PLC"); + string logOpName = string.IsNullOrWhiteSpace(opName) ? "Function1051_EngineGetOver" : opName; + string logText = $"EngineTypeGetOver异常:异常={err.Message}"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(logOpName, logText, MisDataSaveDate.Helper.MesLogType.ERROR); + MyLog4Net.MyLogHelper.Error("Function1051_EngineGetOver", $"{logText}{Environment.NewLine}{err}"); } + } + } + + } } diff --git a/MisDataFunction/Function1053/OpcServer/HeartBeat.cs b/MisDataFunction/Function1053/OpcServer/HeartBeat.cs deleted file mode 100644 index b94f253..0000000 --- a/MisDataFunction/Function1053/OpcServer/HeartBeat.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MesServerWork; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MesServerFunctions -{ - partial class FunctionMES - { - /// - /// MES与PLC心跳监听 - /// - /// - /// - private void HeartBeat(object e) - { - try - { - DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; - string OpName = Convert.ToString(msgEvent.OpName); - int tagValue = Convert.ToInt32(msgEvent.TagValue); - - //返写在MES心跳中 - MIS_BASE.WritePLC(15, OpName, tagValue); - } - catch (Exception err) - { - ////ApplicationLog.WriteLog(err, "Function02:FalseGO"); - } - } - } -} diff --git a/MisDataFunction/Function1053/OpcServer/MaterialsVerify.cs b/MisDataFunction/Function1053/OpcServer/MaterialsVerify.cs index 51130ff..043341c 100644 --- a/MisDataFunction/Function1053/OpcServer/MaterialsVerify.cs +++ b/MisDataFunction/Function1053/OpcServer/MaterialsVerify.cs @@ -27,12 +27,33 @@ namespace MesServerFunctions //判断PLC机型与MES机型是否一致 if (tagValue == 1) { - int EngineTypeID;//机型代码 - int PartPallet_Code;//托盘编号 - string EngineType;//机型 - string EngineID;//工件编号 - string OrderForm; - MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + int EngineTypeID = 0;//机型代码 + int PartPallet_Code = 0;//托盘编号 + string EngineType = "";//机型 + string OrderForm = ""; + MIS_BASE.Read_EngineID(OpName, out string PLCEngineID); + MIS_BASE.Read_EngineID_MES(OpName, out string MESEngineID); + string EngineID = string.IsNullOrEmpty(PLCEngineID) ? MESEngineID : PLCEngineID; + + if (string.IsNullOrEmpty(EngineID)) + { + string msg = $"【{OpName}】PLC与MES产品编号点位均为空,继续按空产品信息保存物料扫码记录!"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "MaterialsVerify " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + } + else + { + DataTable planDt = MisDataFun.XD_GetPlanInfoByEngineID(EngineID); + if (planDt.Rows.Count > 0) + { + OrderForm = planDt.Rows[0]["订单号"].ToString(); + EngineType = planDt.Rows[0]["产品型号"].ToString(); + } + else + { + string msg = $"【{OpName}】产品:{EngineID} 未在生产计划_派工订单_执行计划中查询到记录,继续保存物料扫码记录!"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "MaterialsVerify " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + } + } int MaterialsTypeCode = Convert.ToInt32(MIS_BASE.ReadPLC(201, OpName)); string MaterialsCode = MIS_BASE.ReadPLC(40, OpName).ToString(); diff --git a/MisDataFunction/Function1053/OpcServer/MesRead.cs b/MisDataFunction/Function1053/OpcServer/MesRead.cs index af14ba5..248dfea 100644 --- a/MisDataFunction/Function1053/OpcServer/MesRead.cs +++ b/MisDataFunction/Function1053/OpcServer/MesRead.cs @@ -1,88 +1,93 @@ -using MesServerWork; -using MesWork; -using MisDataFunDll; -using System; -using System.Data; +using System; +using System.Collections.Generic; using System.Threading; +using MesServerWork; +using MisDataFunDll; namespace MesServerFunctions { partial class FunctionMES { + object lockMesRead = new object(); /// - /// 允许保存(针对半自动和手动压装工位) + /// 保存完成(针对半自动和手动压装工位) /// /// /// private void MesRead(object e) { + string opName = ""; + string engineID = ""; + string orderForm = ""; + try { - try + int EngineTypeID; + string EngineType; + string EngineID; + int PartPallet_Code; + string OrderForm; + + int EngineTypeID_MES;//机型代码 + string EngineType_MES;//机型 + string EngineID_MES;//工件编号 + string OrderForm_MES; + { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); + opName = OpName; int tagValue = Convert.ToInt32(msgEvent.TagValue); - int EngineTypeID_MES;//机型代码 - string EngineType_MES;//机型 - string EngineID_MES;//工件编号 - string OrderForm_MES; - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesRead, "0"); - Thread.Sleep(500); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesRead, "1"); if (tagValue == 1) { - bool isEngineGetOver; - DataRow mobyData = MisDataFun.GetMobyTableByOpName(OpName).Rows[0]; - EngineTypeID_MES = Convert.ToInt32(mobyData["产品型号代码_MES"]); - EngineType_MES = mobyData["发动机型号_MES"].ToString(); - EngineID_MES = mobyData["变速器序列号_MES"].ToString(); - OrderForm_MES = mobyData["订单号_MES"].ToString(); - isEngineGetOver = Convert.ToBoolean(mobyData["允许工作"]); + int qualityMask; + MIS_BASE.GetEngineTypeFromPLC(OpName, out EngineTypeID, out EngineType, out EngineID, out PartPallet_Code, out OrderForm); + engineID = EngineID; + orderForm = OrderForm; - if (!isEngineGetOver) - { - string msg2 = "【" + OpName + "】" + "请先开始订单生产后再进行保存,当前未允许工作!"; - SendMessage.AsyncSendMessage_Notice(OpName, msg2); - return; - } - - // 存追溯表数据 - MisDataFun.WorkOrderOpWorkOver(OpName, EngineID_MES, OrderForm_MES); + //保存数据到线首表 先保存到 北汽福田变速器序列号总线上线 用于之前判断是否重号 + // 保存质量数据 + qualityMask = MisDataSaveDateMesRead.Funtion.MesRead(OpName, tagValue.ToString(), msgEvent.TagID.ToString()); // 保存物料数据 - MisDataFun.Material_Insert(OpName, 1); + MisDataFun.Material_Insert(OpName, qualityMask); - // 测量数据发动机在线状态 - MisDataFun.WorkStartInsert(OpName, 1); + // 保存过站信息 + MisDataFun.WorkStartInsert(OpName, qualityMask); + // 存追溯表数据 同时质量数据存入 接口表 + MisDataFun.WorkOrderOpWorkOver(OpName, EngineID, OrderForm); + + // 推送质量数据到MES的页面 + SendMessageFun.SendInfomation("ShowTimelyQuality", "1&" + qualityMask.ToString(), OpName); + + //对应手动工位的 + //MIS_BASE.Write_ConfirmOkGo(OpName, true); //通知设备,MES的质量数据(和物料数据)保存完成 + MIS_BASE.Write_MesReadOver(OpName, true); + //MIS_BASE.Write_MaterialVerifyOver(OpName, true); //统计在线产量,在线节拍 SendMessage.SendActuallyCount(OpName, tagValue); - - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesReadOver, "1"); - Thread.Sleep(1000 * 1); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.WorkStart, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.EngineTypeGetOverPLC, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.PartLoad, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesRead, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesReadOver, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.FixAllow, "0"); - - - string msg = "【" + OpName + "】" + "工件数据保存完成!"; - SendMessage.AsyncSendMessage_Notice(OpName, msg); + //调用工厂MES接口报工 + WebApi.CALL_Inerface_DataHandle.CALL_Inerface_JobFinished(OpName, EngineID, OrderForm); } + else + { + MIS_BASE.Write_MesReadOver(OpName, false); + MIS_BASE.Write_MaterialVerifyOver(OpName, false); + } + } - catch (Exception err) - { - // 保存出错日志 1.申请上线 2.传递机型 3.允许保存 4.扫码 - MisDataSaveDate.FuntionMesRead.Alarm_SaveFileLog4Error(System.Reflection.MethodBase.GetCurrentMethod().Name, e, "Fun1053", err); - ////ApplicationLog.WriteLog(err, "Function08:MesReadOver"); - } + + } + catch (Exception err) + { + string logOpName = string.IsNullOrWhiteSpace(opName) ? "Function1051_MesRead" : opName; + string logText = $"MesRead异常:订单号={orderForm}, 工件编号={engineID}, 异常={err.Message}"; + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(logOpName, logText, MisDataSaveDate.Helper.MesLogType.ERROR); + MyLog4Net.MyLogHelper.Error("Function1051_MesRead", $"{logText}{Environment.NewLine}{err}"); } } - } } diff --git a/MisDataFunction/Function1053/OpcServer/PartLoad.cs b/MisDataFunction/Function1053/OpcServer/PartLoad.cs index b51c56a..32c3cbf 100644 --- a/MisDataFunction/Function1053/OpcServer/PartLoad.cs +++ b/MisDataFunction/Function1053/OpcServer/PartLoad.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Data; using System.Threading; //using SystemFramework; using MesServerWork; @@ -20,34 +22,47 @@ namespace MesServerFunctions DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); int tagValue = Convert.ToInt32(msgEvent.TagValue); - - // 清空MOBY表中所有数据 - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.WorkStart, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.EngineTypeGetOverPLC, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.PartLoad, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesRead, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.MesReadOver, "0"); - MisDataFun.MobySendWebAndSaveData(OpName, MisDataFun.MobyTagType.FixAllow, "0"); - Thread.Sleep(500); - // 按照生产排序顺序获取订单相关数据 - // 获取到数据 显示 申请上线、传递机型、允许工作三个点位 - // 显示对应物料信息、 + if (tagValue == 1) { - + // 读取当前选择的计划中的机型,写入PLC + // 获取订单的机型 + MisDataFun.GetEngineType_Order(OpName, out int EngineTypeID, out string EngineType, out string EngineID, out string OrderForm, out int parType, out int isCheckOk,out string msg2); + if (isCheckOk == 2) + { + string msg = "【" + OpName + "】" + msg2; + // 判断到线体上有滞留工件 ,让去管理系统进行处理 + SendMessage.AsyncSendMessage_Notice(OpName, msg); + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "PartLoad " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); + return; + } + else + { + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.EngineTypeID_MES, EngineTypeID.ToString()); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.EngineType_MES, EngineType); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.EngineID_MES, EngineID); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.OrderForm_MES, OrderForm); + + // 写入机型代码 (大机型) 机型 发动机号 订单号 + MIS_BASE.Write_EngineTypeID_MES(OpName, EngineTypeID); + MIS_BASE.Write_EngineType_MES(OpName, EngineType); + MIS_BASE.Write_EngineID_MES(OpName, EngineID); + MIS_BASE.Write_OrderForm_MES(OpName, OrderForm); + MIS_BASE.WritePLC(115, OpName, parType); // 托盘类型 1 静 2 动 3 拐 + + // MES传递机型 + MIS_BASE.Write_EngineTypeGetOver_MES(OpName, true); + } } else { - ////上线工位清MES传递机型信号 - //MIS_BASE.Write_EngineTypeGetOver_MES(OpName, false); - //// 清除报警 + //上线工位清MES传递机型信号 + MIS_BASE.Write_EngineTypeGetOver_MES(OpName, false); } } catch (Exception err) { - // 保存出错日志 1.申请上线 2.传递机型 3.允许保存 4.扫码 - MisDataSaveDate.FuntionMesRead.Alarm_SaveFileLog4Error(System.Reflection.MethodBase.GetCurrentMethod().Name, e, "Fun1053", err); ////ApplicationLog.WriteLog(err, "Function08:MesReadOver"); } } diff --git a/MisDataFunction/Function1053/OpcServer/WebSubmit.cs b/MisDataFunction/Function1053/OpcServer/WebSubmit.cs index 242f6fa..71febbc 100644 --- a/MisDataFunction/Function1053/OpcServer/WebSubmit.cs +++ b/MisDataFunction/Function1053/OpcServer/WebSubmit.cs @@ -3,8 +3,10 @@ using MesServerWork; using System.Threading; using MisDataSaveDate; using System.Collections; +using MisDataFunDll; //using SystemFramework; + namespace MesServerFunctions { partial class FunctionMES @@ -17,41 +19,41 @@ namespace MesServerFunctions private void WebSubmit(object e) { try - { - DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; - string OpName=Convert.ToString(msgEvent.OpName); + { + var msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; + string OpName = Convert.ToString(msgEvent.OpName); string Content = Convert.ToString(msgEvent.TagValue); + string opName_SubLine = ""; + string engineID = "";//工件信息 string[] dataArray = Content.Split('|'); + if (dataArray.Length != 2) return; - //消息类型 - string m_Command = dataArray[0].ToString(); - //消息参数 - string m_Value = dataArray[1].ToString(); - //消息参数数量 - string[] m_Value_array = m_Value.Split('&'); - //消息参数长度 - int m_Value_length = m_Value_array.Length; - //工件信息 - string engineID = ""; + + string m_Command = dataArray[0].ToString();//消息类型 + string m_Value = dataArray[1].ToString();//消息参数 + string[] m_Value_array = m_Value.Split('&');//消息参数数量 + int m_Value_length = m_Value_array.Length; //消息参数长度 + if (MIS_BASE.hashtable_EngineGetOver_EngineTypeID == null) { MIS_BASE.InitHashtable_MesServerCode(); } - if (MIS_BASE.hashtable_EngineGetOver_EngineTypeID == null) - { - return; - } if (MIS_BASE.hashtable_EngineGetOver_EngineID.ContainsKey(OpName)) { engineID = MIS_BASE.hashtable_EngineGetOver_EngineID[OpName].ToString(); } - + if (MIS_BASE.hashtable_OpNameRepair == null) + { + MIS_BASE.InitHashtable_MesServerCode(); + } DeviceDriver_BasicData.CustomeEvetnArgs _e = new DeviceDriver_BasicData.CustomeEvetnArgs(); _e.OpName = OpName; _e.TagValue = m_Value; + string msg; + bool bolVal; //根据请求的命令处理逻辑 switch (m_Command) @@ -60,6 +62,32 @@ namespace MesServerFunctions if (m_Value_length > 1) return; fun_Barcode(_e); break; + case "ConfirmOkGo"://合格放行 + //修改托盘状态 + + //MisDataFun.BaseData_tagTable_Engine_IsNG_Delete(OpName, engineID); + MIS_BASE.Write_ConfirmOkGo(OpName, true); + MIS_BASE.Write_FalseGO(OpName, false); + Thread.Sleep(1000); + MIS_BASE.Write_ConfirmOkGo(OpName, false); + break; + case "FalseGO"://返修放行 + //修改托盘状态 + //BaseDataSystemMES.BaseData_tagTable_Engine_IsNG_Delete(OpName, engineID); + MIS_BASE.Write_FalseGO(OpName, true); + MIS_BASE.Write_ConfirmOkGo(OpName, false); + Thread.Sleep(1000); + MIS_BASE.Write_FalseGO(OpName, false); + break; + case "NgGO"://不合格放行 + //修改托盘状态 + //保存不合格信息(必须保存不合格放行信息,由于B5A的Moby没有不合格标志位) + //BaseDataSystemMES.BaseData_tagTable_Engine_IsNG_Insert(OpName, engineID, "", ""); + MIS_BASE.Write_FalseGO(OpName, true); + MIS_BASE.Write_ConfirmOkGo(OpName, false); + Thread.Sleep(1000); + MIS_BASE.Write_FalseGO(OpName, false); + break; case "OnLineState"://在线0、离线1、屏蔽2 try { @@ -69,6 +97,7 @@ namespace MesServerFunctions { //BaseDataSystemMES.IsOnLine_Update(OpName, m_Value.ToString()); MIS_BASE.Write_OnLineState(OpName, Convert.ToInt32(m_Value)); + if (a == 2) SendMessage.AsyncSendMessage_Notice(OpName, "屏蔽MES!"); if (a == 0) SendMessage.AsyncSendMessage_Notice(OpName, "启用MES!"); } @@ -76,34 +105,47 @@ namespace MesServerFunctions catch { + } + break; + + case "NullWorkGo"://空托盘放行 0不放行 1放行 + try + { + int a = Convert.ToInt32(m_Value); + //修改地址值 + MIS_BASE.Write_PartPalletGoOver(OpName, a); + if (a == 1) + { + SendMessage.AsyncSendMessage_Notice(OpName, "开启空托盘放行!"); + } + else + { + SendMessage.AsyncSendMessage_Notice(OpName, "关闭空托盘放行!"); + } + } + catch + { + } break; case "Reset"://复位,将MES所有的信息都复位了 SetMoby(OpName);//将MES所有信号清空 + break; case "FixAllow"://重新拧紧 - MIS_BASE.Write_FixAllow(OpName, false); - MIS_BASE.Write_FixAllow(OpName, true); break; case "IsAutoGetEngineID"://自动手动申请编号(线首) if (m_Value_length > 1) return; MIS_BASE.Write_IsAutoGetEngineID(OpName, Convert.ToInt32(m_Value)); break; case "PartPalletGoOver"://空托盘放行 - int Is_PartPalletGoOver; - MIS_BASE.Read_PartPalletGoOver(OpName, out Is_PartPalletGoOver); - if (Is_PartPalletGoOver == 1) - { - MIS_BASE.Write_PartPalletGoOver(OpName, 1); - } - else - { - MIS_BASE.Write_PartPalletGoOver(OpName,0); - } + MIS_BASE.Write_RepairUpline_MES(opName_SubLine, true); + //MIS_BASE.Write_PalletInfo(opName_SubLine, 4); + //MIS_BASE.Write_UpdatePalletOK(opName_SubLine, true); + MIS_BASE.Write_MaterialVerifyOver(opName_SubLine, true); break; case "SetMoby"://清空托盘(线首) SetMoby(OpName);//将MES所有信号清空 - //MIS_BASE.Write_PartPalletCode_PLC(OpName, 1); break; case "RepairUplineMES"://返修上线 MIS_BASE.Write_RepairUpline_MES(OpName, true); @@ -116,7 +158,9 @@ namespace MesServerFunctions break; case "WritePartPalletCode"://写入托盘号 if (m_Value_length > 1) return; - MIS_BASE.Write_PalletCode(OpName, Convert.ToInt32(m_Value)); + MIS_BASE.WritePLC(113, OpName, Convert.ToInt32(m_Value)); + Thread.Sleep(500); + MIS_BASE.WritePLC(70, OpName, true); break; case "Normal"://启用正常拧紧工位 MIS_BASE.Write_Normal(OpName, 1); @@ -139,57 +183,87 @@ namespace MesServerFunctions //通知修改成功 MIS_BASE.Write_UpdatePalletOK(OpName, true); IsNeedRepaire_OK(OpName); - } else if (Convert.ToInt32(m_Value) == 0) { - //通知修改成功 - MIS_BASE.Write_UpdatePalletOK(OpName, true); //直接给出工作完成 MIS_BASE.Write_MaterialVerifyOver(OpName, true); } - else - { } + break; + //强制匹配 + case "ForceMatch": + if (Convert.ToInt32(m_Value) == 1) + { + ForceMatch(OpName); + } + break; + case "PalletGO": + if (Convert.ToInt32(m_Value) == 1) + { + //直接给出工作完成 + MIS_BASE.Write_MaterialVerifyOver(opName_SubLine, true); + } break; case "ContinueMatch": //BaseDataSystemMES.QualityVerifyStatus_Hash_Write(OpName, true); + fun_EngineTypeGetOverPLC(_e); break; //初始化网页信号 - case "IniSingalToWeb": + case "IniSingalToWeb": InitializeSingalToWeb(OpName); break; - case "Reset_Engine"://返修上线(返修上线点) - SetMoby(OpName);//将MES所有信号清空 - //fun_EngineTypeGetOverPLC(OpName, 0); - //fun_EngineTypeGetOverPLC(OpName, 1); + // 检查项 检查完成 + case "checkWorkOver": + MIS_BASE.WritePLC(30, OpName,1); + msg = "MES|checkWorkOverIsShow|" + OpName + "|" + 0; + SendMessage.AsyncSendMessage(msg); break; - - case "twoWorkSkip"://重新工作工件跳过工作(重新工作工件) - //工作完成 - EngineTypeGetOver_PLC_Work_Skip(OpName); + // 重新申请上线 + case "againPartLoad": + // 判断是否有工件到位 + MIS_BASE.Read_WorkStart(OpName, out bolVal); + if (bolVal) + { + MIS_BASE.WritePLC(35, OpName, 1); + msg = "【" + OpName + "】" + "重新申请上线完成!"; + SendMessage.AsyncSendMessage_Notice(OpName, msg); + } + else + { + msg = "【" + OpName + "】" + "当前无工件到位信号,请确认是否存在工件!"; + SendMessage.AsyncSendMessage_Notice(OpName, msg); + } break; - case "twoWork"://重新工作工件重新工作(重新工作工件) - //允许工作 - EngineTypeGetOver_PLC_Work_two(OpName); - break; - case "SelectOrderForm"://分线接受前端模拟传递机型 - _e.TagValueUp = "6"; - EngineTypeGetOver_PLC(_e); - break; - case "outLineOpNameWorkOver"://分线接受前端模拟工作完成 - _e.TagValueUp = "6"; - _e.TagValue = 1; - MesRead(_e); + // 跳过交互 + case "skipWork": + // 判断是否有工件到位 + MIS_BASE.Read_WorkStart(OpName, out bolVal); + if (bolVal) + { + MIS_BASE.Write_EngineTypeGetOver_MES(OpName, true); // 传递机型 + MIS_BASE.Write_FixAllow(OpName,true); // 允许工作 + MIS_BASE.WritePLC(30, OpName, 1); // 检查完成 + MIS_BASE.Write_MesReadOver(OpName, true); // 保存完成 + MIS_BASE.Write_MaterialVerifyOver(OpName, true); // 工作完成 + msg = "【" + OpName + "】" + "跳过交互完成!"; + SendMessage.AsyncSendMessage_Notice(OpName, msg); + } + else + { + msg = "【" + OpName + "】" + "当前无工件到位信号,请确认是否存在工件!"; + SendMessage.AsyncSendMessage_Notice(OpName, msg); + } break; default: break; } } catch(Exception err) { - ////ApplicationLog.WriteLog(err, "Function02:WebSubmit"); + ////ApplicationLog.WriteLog(err, "Function08:WebSubmit"); } } + private void SetMoby(string OpName) { try @@ -201,38 +275,38 @@ namespace MesServerFunctions SendMessageFun.SendMessage("5123", "1111", OpName); - MIS_BASE.Write_ResetDevice(OpName, true); System.Threading.Thread.Sleep(1000); - MIS_BASE.Write_ResetDevice(OpName, false); + MIS_BASE.Write_ResetDevice(OpName, false); } catch { } } + + /// /// 网页重现登录,恢复关闭前的页面状态 /// /// 工位号 - private void InitializeSingalToWeb(string OpName) + private void InitializeSingalToWeb(string Opname) { - InitOpPosion(OpName); + InitOpPosion(Opname); - ////3显示操作指导图片 PicShow_String_FirstOpName - //SendMessage.PicShow_FirstOpName(OpOpNamename); - ////1(直接在界面通过选择机型确认工序内容) - //SendMessage.ProcessList_FirstOpName(OpName); - //// MOBY数据 - //SendMessageFun.SendMessage("5", "1", OpName); - //// 物料信息 物料信息 - //SendMessage.MaterialList(OpName); - - SendMessageFun.SendMessage("315", "111", OpName); + //3显示操作指导图片 PicShow_String_FirstOpName + SendMessage.PicShow_FirstOpName(Opname); + //1(直接在界面通过选择机型确认工序内容) + SendMessage.ProcessList_FirstOpName(Opname); + // MOBY数据 + SendMessageFun.SendMessage("5", "1", Opname); + //SendMessageFun.SendMessage("5123", "1111", Opname); + // 物料信息 物料信息 + SendMessage.MaterialList(Opname); // 新增查询PLC直通状态 网页显示 //MIS_BASE.Read_TagTypeID(63, Opname, out S_plcStatus); - InitAlarm(OpName); + InitAlarm(Opname); } //分线发送工件到位信号函数 @@ -308,7 +382,7 @@ namespace MesServerFunctions SendMessageFun.SendInfomation("MesReadOver", Convert.ToString(Convert.ToInt32(S_ReadOver)), Opname); } //---------------------------------------------------- - bool S_MaterialVerifyOver;//工作完成 DBX2.3 + bool S_MaterialVerifyOver;//工作完成 DBX0.3 MIS_BASE.Read_MaterialVerifyOver(Opname, out S_MaterialVerifyOver); if (S_MaterialVerifyOver == true) { diff --git a/MisDataFunction/Function1053/OpcServer/WorkIsOk.cs b/MisDataFunction/Function1053/OpcServer/WorkIsOk.cs deleted file mode 100644 index 3149bce..0000000 --- a/MisDataFunction/Function1053/OpcServer/WorkIsOk.cs +++ /dev/null @@ -1,44 +0,0 @@ -using MesServerWork; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MesServerFunctions -{ - partial class FunctionMES - { - /// - /// 工位合格标志 - /// - /// - /// - private void IsOk(object e) - { - try - { - DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; - string OpName = Convert.ToString(msgEvent.OpName); - int tagValue = Convert.ToInt32(msgEvent.TagValue); - - int qualityMask; - MIS_BASE.Read_QualityMask(OpName, out qualityMask); - //判断是否合格 - if (qualityMask == 1) - { - qualityMask = 1; - } else { - qualityMask = 0; - } - //通知WEB修改状态 - string message = "MES|QualityMask|" + OpName + "|" + qualityMask.ToString(); - SendMessage.AsyncSendMessage(message); - } - catch (Exception err) - { - ////ApplicationLog.WriteLog(err, "Function02:FalseGO"); - } - } - } -} diff --git a/MisDataFunction/Function1053/OpcServer/WorkStart.cs b/MisDataFunction/Function1053/OpcServer/WorkStart.cs index c634017..91e7893 100644 --- a/MisDataFunction/Function1053/OpcServer/WorkStart.cs +++ b/MisDataFunction/Function1053/OpcServer/WorkStart.cs @@ -1,8 +1,10 @@ -using MesServerWork; -using System; -using System.Threading; +using System; +using System.Collections.Generic; +using MesServerWork; +using MisDataFunDll; //using SystemFramework; + namespace MesServerFunctions { partial class FunctionMES @@ -12,38 +14,53 @@ namespace MesServerFunctions /// /// /// - private void WorkStart(object e) + private void WorkStart(object e) { try { DeviceDriver_BasicData.CustomeEvetnArgs msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e; string OpName = Convert.ToString(msgEvent.OpName); int tagValue = Convert.ToInt32(msgEvent.TagValue); - //if (tagValue > 0) - //{ - // MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.WorkStartIn, DateTime.Now.ToString()); - // MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.WorkStart, tagValue.ToString()); - //} - //else - //{ - // MisDataFun.OpName_MIS_MOBY_Insert(OpName,MisDataFun.MobyTagType.WorkStartOut, DateTime.Now.ToString()); - // MIS_BASE.Write_MesReadOver(OpName, false); - // MIS_BASE.Write_ConfirmOkGo(OpName, false); - // MIS_BASE.Write_FixAllow(OpName, false); - // MIS_BASE.Write_EngineTypeGetOver_MES(OpName, false); - // //工作完成 - // MIS_BASE.Write_MaterialVerifyOver(OpName, false); - // MIS_BASE.Write_EngineTypeID_MES(OpName, 0); - // MIS_BASE.Write_EngineType_MES(OpName, ""); - // MIS_BASE.Write_EngineID_MES(OpName, ""); - // MIS_BASE.Write_OrderForm_MES(OpName, ""); - //} + + //线首显示订单信息 + + if (tagValue == 1) + { + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.WorkStartIn, DateTime.Now.ToString()); + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.WorkStart, tagValue.ToString()); + } + else + { + MisDataFun.OpName_MIS_MOBY_Insert(OpName, MisDataFun.MobyTagType.WorkStartOut, DateTime.Now.ToString()); + + // 清除工位数据 + MIS_BASE.Write_EngineTypeID_MES(OpName, 0); + MIS_BASE.Write_EngineType_MES(OpName, ""); + MIS_BASE.Write_EngineID_MES(OpName, ""); + MIS_BASE.Write_OrderForm_MES(OpName, ""); + + MIS_BASE.Write_MesReadOver(OpName, false); + MIS_BASE.Write_ConfirmOkGo(OpName, false); + MIS_BASE.Write_FixAllow(OpName, false); + MIS_BASE.Write_EngineTypeGetOver_MES(OpName, false); + //工作完成 + MIS_BASE.Write_MaterialVerifyOver(OpName, false); + + MIS_BASE.WritePLC(115, OpName, 0); // 清除小机型 + + // 检查项完成 + MIS_BASE.Write_TagTypeID(30, OpName,0); + string message = "MES|checkWorkOverIsShow|" + OpName + "|" + 0; + SendMessage.AsyncSendMessage(message); + + // 重新申请上线 + MIS_BASE.WritePLC(35, OpName, 0); + } } - catch (Exception err) + catch(Exception err) { - ////ApplicationLog.WriteLog(err, "Function02:WorkStart"); + ////ApplicationLog.WriteLog(err, "Function08:WorkStart"); } } - } } diff --git a/MisDataFunction/Function1053/OpcServer/vssver2.scc b/MisDataFunction/Function1053/OpcServer/vssver2.scc index b884d13..e8dac03 100644 Binary files a/MisDataFunction/Function1053/OpcServer/vssver2.scc and b/MisDataFunction/Function1053/OpcServer/vssver2.scc differ diff --git a/MisDataFunction/Function1053/Properties/AssemblyInfo.cs b/MisDataFunction/Function1053/Properties/AssemblyInfo.cs index 0bb79c4..f3608c0 100644 --- a/MisDataFunction/Function1053/Properties/AssemblyInfo.cs +++ b/MisDataFunction/Function1053/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ using System.Runtime.InteropServices; // 有关程序集的常规信息通过以下 // 特性集控制。更改这些特性值可修改 // 与程序集关联的信息。 -[assembly: AssemblyTitle("Function02")] +[assembly: AssemblyTitle("Function08")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("苏州宏软信息技术有限公司")] -[assembly: AssemblyProduct("Function02")] +[assembly: AssemblyProduct("Function08")] [assembly: AssemblyCopyright("Copyright © 苏州宏软信息技术有限公司 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/MisDataFunction/Function1053/Properties/vssver2.scc b/MisDataFunction/Function1053/Properties/vssver2.scc index 14e543b..87eebff 100644 Binary files a/MisDataFunction/Function1053/Properties/vssver2.scc and b/MisDataFunction/Function1053/Properties/vssver2.scc differ diff --git a/MisDataFunction/Function1053/mssccprj.scc b/MisDataFunction/Function1053/mssccprj.scc index 119193d..f184c61 100644 --- a/MisDataFunction/Function1053/mssccprj.scc +++ b/MisDataFunction/Function1053/mssccprj.scc @@ -1,5 +1,5 @@ SCC = This is a Source Code Control file -[Function02.csproj] +[Function08.csproj] SCC_Aux_Path = "\\192.168.0.100\vss\MES4.0" -SCC_Project_Name = "$/MisData/MisData/MisData/MesServer.Function/Function02", ILHAAAAA +SCC_Project_Name = "$/MisData/MisData/MisData/MesServer.Function/Function08", KRHAAAAA diff --git a/MisDataFunction/Function1054/Function1054.csproj b/MisDataFunction/Function1054/Function1054.csproj index c1e7839..d6841df 100644 --- a/MisDataFunction/Function1054/Function1054.csproj +++ b/MisDataFunction/Function1054/Function1054.csproj @@ -102,6 +102,7 @@ + diff --git a/MisDataFunction/Function1054/MesServerFunction/Fun_1054.cs b/MisDataFunction/Function1054/MesServerFunction/Fun_1054.cs index d0e9734..0971bb9 100644 --- a/MisDataFunction/Function1054/MesServerFunction/Fun_1054.cs +++ b/MisDataFunction/Function1054/MesServerFunction/Fun_1054.cs @@ -9,13 +9,12 @@ namespace MesServerFunctions { public partial class FunctionMES { - object lockFunWork; + private readonly object lockFunWork = new object(); //public void FunWork(DeviceDriver_BasicData.CustomeEvetnArgs e) public void FunWork(string recData) { - lockFunWork = new object(); lock (lockFunWork) { List dataArray = MisDataFun.GetCmdStringList(recData); @@ -176,10 +175,17 @@ namespace MesServerFunctions break; // 请求插插头 case "452": - // 需要调用AGV插插头接口 去插 + if (tagValue == "1") + fun_TcsAgvDispatch(e, "插"); + else + MIS_BASE.WritePLC(400, OpName, false); break; // 请求拔插头 case "453": + if (tagValue == "1") + fun_TcsAgvDispatch(e, "拔"); + else + MIS_BASE.WritePLC(401, OpName, false); break; // 开始磨合 case "454": diff --git a/MisDataFunction/Function1054/OpcServer/AllowAGVLower.cs b/MisDataFunction/Function1054/OpcServer/AllowAGVLower.cs index 6d4cf9f..2df0b04 100644 --- a/MisDataFunction/Function1054/OpcServer/AllowAGVLower.cs +++ b/MisDataFunction/Function1054/OpcServer/AllowAGVLower.cs @@ -1,4 +1,4 @@ -using MesServerWork; +using MesServerWork; using MisDataFunDll; using System; diff --git a/MisDataFunction/Function1054/OpcServer/AllowAGVRaise.cs b/MisDataFunction/Function1054/OpcServer/AllowAGVRaise.cs index 09b42c2..e8742d4 100644 --- a/MisDataFunction/Function1054/OpcServer/AllowAGVRaise.cs +++ b/MisDataFunction/Function1054/OpcServer/AllowAGVRaise.cs @@ -1,4 +1,4 @@ -using MesServerWork; +using MesServerWork; using MisDataFunDll; using System; diff --git a/MisDataFunction/Function1054/OpcServer/RequestReturnMaterial.cs b/MisDataFunction/Function1054/OpcServer/RequestReturnMaterial.cs index 2f4088a..221721a 100644 --- a/MisDataFunction/Function1054/OpcServer/RequestReturnMaterial.cs +++ b/MisDataFunction/Function1054/OpcServer/RequestReturnMaterial.cs @@ -42,6 +42,11 @@ namespace MesServerFunctions string targetProcessCode = nextDT.Rows[0]["目标工序号"].ToString(); string targetProcess = nextDT.Rows[0]["目标工序"].ToString(); + if(targetStoreCode == "" || targetProcessCode == "" || targetProcess == "") + { + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "RequestReturnMaterial " + "当前无可用转序目标库位 请确认库位空闲状态!", MisDataSaveDate.Helper.MesLogType.ERROR); + return; + } // 1. 调用AGV转序接口 var agvResult = CALL_Inerface_DataHandle.CALL_Inerface_MaterialTransfer(OpName, targetStoreCode); @@ -97,9 +102,7 @@ namespace MesServerFunctions MIS_BASE.WritePLC(306, OpName, 2); // 任务状态反馈 } - - SendMessage.AsyncSendMessage_Notice(OpName, msg); - MyLog4Net.MyLogHelper.Info("RequestReturnMaterial", msg); + MisDataSaveDate.Helper.ApiLogHelper.SaveMesLog(OpName, "RequestReturnMaterial " + msg, MisDataSaveDate.Helper.MesLogType.ERROR); } else {