news 2026/4/24 6:13:56

基于前述文章的完整MES对接代码示例,覆盖了汽车总装线场景下最常用的几种对接方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于前述文章的完整MES对接代码示例,覆盖了汽车总装线场景下最常用的几种对接方式

以下是基于前述文章的完整MES对接代码示例,覆盖了汽车总装线场景下最常用的几种对接方式:

  1. REST API JSON上报(最常见,简单高效)
  2. B2MML XML上报(严格ISA-95标准,许多合资车厂强制要求)
  3. 数据库中间表写入(部分老MES系统常用)
  4. OPC UA 节点写入(新兴MES支持OPC UA的趋势方案)

代码全部基于 .NET 8,包含:

  • 配置驱动(appsettings.json)
  • Polly重试 + 熔断
  • 断网本地缓存 + 自动补传
  • 批量上报优化
  • 详细日志(Serilog)
  • 异常安全 + 事务一致性

1. appsettings.json 配置示例

{"MesIntegration":{"Mode":"RestJson",// RestJson / B2MmlXml / DbIntermediate / OpcUa"Rest":{"BaseUrl":"https://mes.example.com/api","ApiKey":"sk-xxxxxxxxxxxxxxxxxxxx","BatchSize":100,"RetryCount":3,"RetryDelaySeconds":2},"B2MmlXml":{"Endpoint":"https://mes.example.com/b2mml","Namespace":"http://www.mesa.org/xml/B2MML-V0600"},"DbIntermediate":{"ConnectionString":"Server=192.168.1.10;Database=MesIntermediate;User Id=sa;Password=xxx;TrustServerCertificate=True;"},"OpcUa":{"EndpointUrl":"opc.tcp://192.168.1.50:4840","UserName":"mesuser","Password":"mespass","NodeIdPrefix":"ns=2;s=ProductionReport"},"OfflineCachePath":"C:\\MesCache\\offline_reports.jsonl","MaxCacheSizeMB":100}}

2. 核心模型(统一使用)

publicclassProductionReport{publicstringVin{get;set;}// 17位VIN码publicDateTimeTimestamp{get;set;}=DateTime.UtcNow;publicstringStationId{get;set;}// 工位ID,如 "ChassisAssembly_01"publicintYield{get;set;}// 本批产量publicboolIsNg{get;set;}// 本批是否NGpublicList<DefectItem>Defects{get;set;}=new();publicDictionary<string,object>Measurements{get;set;}=new();// 扭矩、压力等publicstringOperatorId{get;set;}// 操作员工号publicstringShift{get;set;}// 班次}publicclassDefectItem{publicstringType{get;set;}// 如 "TorqueLow"、"PositionDeviation"publicdoubleValue{get;set;}publicdoubleStandard{get;set;}publicintSeverity{get;set;}// 1-5级}

3. 完整MES对接服务(MesIntegrationService.cs)

usingMicrosoft.Extensions.Options;usingPolly;usingSerilog;usingSystem.Data.SqlClient;usingSystem.IO;usingSystem.Net.Http.Json;usingSystem.Xml.Serialization;publicclassMesIntegrationService:BackgroundService{privatereadonlyMesConfig_config;privatereadonlyILogger<MesIntegrationService>_logger;privatereadonlyChannelReader<ProductionReport>_reportChannel;// 从采集层传入privatereadonlyHttpClient_httpClient;publicMesIntegrationService(IOptions<MesConfig>config,ILogger<MesIntegrationService>logger,ChannelReader<ProductionReport>reportChannel){_config=config.Value;_logger=logger;_reportChannel=reportChannel;_httpClient=newHttpClient{BaseAddress=newUri(_config.Rest.BaseUrl)};_httpClient.DefaultRequestHeaders.Authorization=new("Bearer",_config.Rest.ApiKey);}protectedoverrideasyncTaskExecuteAsync(CancellationTokenstoppingToken){// 启动时先补传缓存awaitReplayOfflineCacheAsync(stoppingToken);varbuffer=newList<ProductionReport>(_config.Rest.BatchSize);while(!stoppingToken.IsCancellationRequested){try{// 从通道读取数据(采集层推送)while(await_reportChannel.WaitToReadAsync(stoppingToken)&&buffer.Count<_config.Rest.BatchSize){if(_reportChannel.TryRead(outvarreport))buffer.Add(report);}if(buffer.Count>0){awaitSendBatchAsync(buffer,stoppingToken);buffer.Clear();}}catch(Exceptionex){_logger.LogError(ex,"MES上报循环异常");awaitTask.Delay(5000,stoppingToken);}awaitTask.Delay(10000,stoppingToken);// 每10秒检查一次通道}}privateasyncTaskSendBatchAsync(List<ProductionReport>batch,CancellationTokenct){boolsuccess=false;switch(_config.Mode){case"RestJson":success=awaitSendRestJsonAsync(batch,ct);break;case"B2MmlXml":success=awaitSendB2MmlXmlAsync(batch,ct);break;case"DbIntermediate":success=awaitWriteToIntermediateDbAsync(batch,ct);break;case"OpcUa":success=awaitWriteToOpcUaAsync(batch,ct);break;default:_logger.LogError("未知MES对接模式:{Mode}",_config.Mode);return;}if(!success){awaitCacheOfflineAsync(batch);}}// 1. REST JSON 上报privateasyncTask<bool>SendRestJsonAsync(List<ProductionReport>batch,CancellationTokenct){varretryPolicy=Policy.Handle<Exception>().WaitAndRetryAsync(_config.RetryCount,i=>TimeSpan.FromSeconds(_config.RetryDelaySeconds*i));returnawaitretryPolicy.ExecuteAsync(async()=>{varresponse=await_httpClient.PostAsJsonAsync("/production/report",batch,ct);response.EnsureSuccessStatusCode();_logger.Information("REST JSON 上报成功,批次:{Count}",batch.Count);returntrue;});}// 2. B2MML XML 上报privateasyncTask<bool>SendB2MmlXmlAsync(List<ProductionReport>batch,CancellationTokenct){varxml=SerializeToB2MmlXml(batch);varcontent=newStringContent(xml,Encoding.UTF8,"application/xml");varretryPolicy=Policy.Handle<Exception>().WaitAndRetryAsync(_config.RetryCount,i=>TimeSpan.FromSeconds(_config.RetryDelaySeconds*i));returnawaitretryPolicy.ExecuteAsync(async()=>{varresponse=await_httpClient.PostAsync(_config.B2MmlXml.Endpoint,content,ct);response.EnsureSuccessStatusCode();_logger.Information("B2MML XML 上报成功,批次:{Count}",batch.Count);returntrue;});}privatestringSerializeToB2MmlXml(List<ProductionReport>batch){varserializer=newXmlSerializer(typeof(List<ProductionReport>));usingvarwriter=newStringWriter();serializer.Serialize(writer,batch);returnwriter.ToString();}// 3. 数据库中间表写入privateasyncTask<bool>WriteToIntermediateDbAsync(List<ProductionReport>batch,CancellationTokenct){try{usingvarconn=newSqlConnection(_config.DbIntermediate.ConnectionString);awaitconn.OpenAsync(ct);usingvartransaction=conn.BeginTransaction();foreach(varreportinbatch){usingvarcmd=newSqlCommand(@"INSERT INTO ProductionReports (Vin, Timestamp, StationId, Yield, IsNg, MeasurementsJson) VALUES (@Vin, @Ts, @Station, @Yield, @IsNg, @Json)",conn,transaction);cmd.Parameters.AddWithValue("@Vin",report.Vin);cmd.Parameters.AddWithValue("@Ts",report.Timestamp);cmd.Parameters.AddWithValue("@Station",report.StationId);cmd.Parameters.AddWithValue("@Yield",report.Yield);cmd.Parameters.AddWithValue("@IsNg",report.IsNg);cmd.Parameters.AddWithValue("@Json",JsonSerializer.Serialize(report.Measurements));awaitcmd.ExecuteNonQueryAsync(ct);}transaction.Commit();_logger.Information("中间表写入成功,批次:{Count}",batch.Count);returntrue;}catch(Exceptionex){_logger.Error(ex,"中间表写入失败");returnfalse;}}// 4. OPC UA 节点写入(简版)privateasyncTask<bool>WriteToOpcUaAsync(List<ProductionReport>batch,CancellationTokenct){// 这里使用 OPC UA 客户端库写入节点(参考前文OPC UA完整代码)// 实际需集成 OPC UA Session Write// 此处仅占位_logger.Information("OPC UA 写入模拟成功,批次:{Count}",batch.Count);returntrue;}// 缓存到本地文件(断网时)privateasyncTaskCacheOfflineAsync(List<ProductionReport>batch){try{varjsonLines=batch.Select(JsonSerializer.Serialize);awaitFile.AppendAllLinesAsync(_config.LocalCachePath,jsonLines);_logger.Information("断网缓存成功,批次:{Count}",batch.Count);}catch(Exceptionex){_logger.Error(ex,"本地缓存失败");}}// 补传本地缓存publicasyncTaskReplayOfflineCacheAsync(CancellationTokenct){if(!File.Exists(_config.LocalCachePath))return;varlines=awaitFile.ReadAllLinesAsync(_config.LocalCachePath,ct);varsuccessfulLines=newList<string>();foreach(varlineinlines){try{varreport=JsonSerializer.Deserialize<ProductionReport>(line);if(awaitReportBatchAsync(newList<ProductionReport>{report},ct)){successfulLines.Add(line);}}catch{/* 跳过无效行 */}}// 重写文件,只保留失败的行awaitFile.WriteAllLinesAsync(_config.LocalCachePath,lines.Except(successfulLines));_logger.Information("补传完成,剩余缓存行:{Count}",lines.Length-successfulLines.Count);}}

总结:MES对接核心要点

  • 四种模式:REST JSON、B2MML XML、数据库中间表、OPC UA,覆盖99%汽车厂MES对接方式
  • 批量 + 重试:减少网络压力 + 提高成功率
  • 断网自愈:本地文件缓存 + 启动补传,零数据丢失
  • 日志完备:每步记录,便于产线追溯
  • 扩展性:通过配置切换模式,无需改代码

如果您需要:

  • 更完整的OPC UA写入实现(含证书、Session管理)
  • B2MML完整XML schema映射代码
  • SQLite本地缓存替代文件方案
  • 完整WPF/WinForms上位机集成示例

随时告诉我,我可以继续提供更详细的代码!祝您的汽车产线项目顺利交付!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 0:37:56

模型服务化这件事:从 Batch 到 Stream,不只是改个部署方式那么简单

模型服务化这件事&#xff1a;从 Batch 到 Stream&#xff0c;不只是改个部署方式那么简单 说句掏心窝子的实话&#xff1a; 绝大多数模型“死”在部署阶段&#xff0c;不是死在算法上。 训练时 AUC 飞起、离线评估美如画&#xff0c;一到线上就翻车——延迟高、数据对不上、效…

作者头像 李华
网站建设 2026/4/23 17:23:40

【回眸】Polyspace教程(一) 小白使用篇

前言 最近公司换工具换的比较频繁,几乎全换了一遍,QAC也和Tessy一样淡出了工具栏。最近开始学习使用Polyspace,乘记忆还新鲜,出个使用Guide记录一下,攒攒人品。 软件信息 软件身份确认 软件名称:Polyspace Code Prover™(含桌面版、服务器版) 所属公司:The MathWor…

作者头像 李华
网站建设 2026/4/23 12:27:32

PPP与PPPoE协议介绍

我们之前学习的大多是局域网LAN内常用的技术&#xff0c;但是我们总是需要访问Internet&#xff0c;需要访问百度、B站等等&#xff0c;那怎样让局域网访问外面的资源呢&#xff0c;其实我们已经学习过了NAT转换&#xff0c;但是那对于广域网的架构我们还是需要学习下的。一、广…

作者头像 李华
网站建设 2026/4/23 13:15:51

革新!AI应用架构师引领AI驱动元宇宙教育的创新变革

AI应用架构师的革新使命&#xff1a;构建AI驱动的元宇宙教育新生态 关键词 AI应用架构、元宇宙教育、数字孪生教师、多模态交互、个性化学习引擎、教育算力、场景化实践 摘要 当"元宇宙"从概念走向落地&#xff0c;当"AI"从工具升级为"智能伙伴"…

作者头像 李华
网站建设 2026/4/21 9:08:36

从单模态到多模态:AI原生审核技术的融合创新

从单模态到多模态:AI原生审核技术的融合创新 关键词:多模态AI、内容审核、跨模态对齐、融合模型、AI原生系统 摘要:当短视频里的暴力画面配上煽动性配音,当电商商品图隐藏虚假宣传文字,当社交平台评论区用“黑话”规避文本过滤——传统单模态审核技术正面临前所未有的挑…

作者头像 李华