news 2026/10/23 14:06:22

3个工厂项目落地总结:C#分布式上位机系统,从单机工位到全厂级统一管控全实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
3个工厂项目落地总结:C#分布式上位机系统,从单机工位到全厂级统一管控全实战

去年一整年,我带着团队啃完了3个汽车零部件工厂的整线上位机改造项目,从最开始单工位的单机版上位机,到车间级分布式管控,再到最终全厂级的统一调度平台,前前后后改了5版架构,踩了不下几十个致命坑——从通信超时、数据丢包,到跨车间网络隔离、多系统数据同步,再到MES对接、全链路权限管控,算是把工业场景下分布式上位机的全链路落地逻辑摸了个透。

很多同行一提到分布式系统,第一反应就是互联网大厂的微服务、高并发架构,直接照搬过来用在工业现场,结果十有八九要翻车。工业场景的分布式上位机,核心从来不是炫技,而是稳定、容错、边缘自治——毕竟工厂里的产线停一分钟,就是几万甚至几十万的损失,互联网那套“服务降级、熔断”的逻辑,在产线24小时不间断运行的需求面前,根本不适用。

这篇文章,我就结合3个工厂项目的实战经验,从架构设计、技术选型、核心代码实现,到现场踩坑与优化,完整拆解一套C#技术栈实现的、从单机工位到全厂级管控的分布式上位机系统,所有内容都是产线验证过的干货,没有空泛的理论,拿来就能用。

一、先搞懂:为什么要放弃单机版,做分布式上位机?

最开始这几个项目,客户用的都是单工位单机版上位机——每个工位一台工控机,装一套上位机软件,直接和工位的PLC、视觉系统、传感器通信,数据存在本地SQLite里。用了不到半年,问题全暴露了:

  1. 数据孤岛严重:车间主任要查当天的产量、设备OEE,得挨个工位跑一遍,手动抄数据,下班汇总要花2个小时,还经常对不上数;
  2. 系统升级维护难:50个工位的产线,软件改个bug、加个功能,要工程师挨个工位跑一遍,更新一次要大半天,产线还不能停,只能半夜加班;
  3. 权限管控混乱:每个工位的上位机自己管用户权限,操作工随便就能改工艺参数,出了质量问题找不到责任人,完全不符合IATF16949的追溯要求;
  4. 系统对接成本极高:客户要上MES系统,需要每个工位的上位机都开接口,光对接调试就花了1个多月,后期加个工位还要重新对接;
  5. 故障排查效率极低:产线出了问题,要挨个工位查日志、看数据,经常错过最佳处理时间,故障停机时间越拉越长。

这些问题,靠单机版上位机根本解决不了,必须做分布式架构——把采集、控制、数据、管控分层解耦,既能保证单工位的独立运行,又能实现全厂级的数据统一和调度管控。

二、核心设计原则:工业分布式上位机的红线,绝对不能碰

在做第一版架构的时候,我们踩了个致命的坑:照搬互联网的微服务架构,把工位的控制逻辑、逻辑判断全放到了服务端,结果车间网络一波动,工位直接停线,客户当场就炸了。

从那之后,我们定了4条工业分布式上位机的核心设计原则,后面所有的架构迭代都严格遵守,再也没出过类似的问题:

  1. 边缘自治第一原则:单工位的实时控制逻辑、急停处理、设备联动,必须全部在边缘端(工位工控机)本地执行,绝对不能依赖服务端。服务端只负责数据汇总、参数下发、非实时调度,哪怕全厂网络断了,每个工位都能正常生产,不受任何影响;
  2. 数据不丢原则:必须做断网续传机制,网络中断时,边缘端采集的所有数据都存在本地缓存,网络恢复后自动补传,绝对不能出现数据丢失、统计断层的情况;
  3. 容错优先原则:任何一个节点、一个服务故障,都不能影响整个系统的运行。单个工位上位机故障,不影响其他工位;单个车间服务故障,不影响其他车间和全厂平台的运行;
  4. 网络适配原则:工厂的网络环境极其复杂,设备网、生产网、办公网三层隔离,防火墙限制极多,系统必须适配这种网络环境,尽量少开端口,优先用边缘端主动外联的方式,避免在设备网开入站端口。

三、整体架构设计:从单机到全厂级的三层分布式架构

基于上面的4条原则,我们最终落地了一套三层分布式架构,从边缘采集到车间级汇聚,再到工厂级管控,层层解耦,既能满足单工位的实时控制需求,又能实现全厂级的统一管控,目前已经在5个工厂项目里稳定运行,最长的已经不间断运行了11个月。

整体架构分层

【工厂级管控层】:全厂统一管控平台、可视化大屏、MES/ERP对接、统一权限管理、报表中心 ↓↑(企业内网/防火墙单向放行,MQTT/gRPC通信) 【车间级服务层】:车间数据汇聚服务、MQTT Broker、配方管理服务、报警中心、历史数据存储 ↓↑(生产网工业交换机,MQTT/gRPC通信) 【边缘采集层】:工位上位机(WPF)、边缘采集服务、PLC/传感器/视觉通信、本地控制逻辑、本地缓存

每层核心职责与C#技术选型

工业场景的技术选型,核心是稳定、兼容、易维护,优先选微软生态的成熟技术,避免用太新、太冷门的框架,不然现场出了问题,连排查的资料都找不到。

架构分层核心职责C#技术栈选型
边缘采集层单工位设备通信、实时数据采集、本地控制逻辑、人机交互、断网本地缓存、数据上报.NET 8 WPF(工位人机界面)、BackgroundService(后台采集服务)、MQTTnet(消息通信)、S7.NET/NModbus(PLC通信)、SQLite(本地缓存)、CommunityToolkit.Mvvm(MVVM框架)
车间级服务层车间内数据汇聚、消息转发、配方下发、报警汇总、历史数据存储、边缘端管理ASP.NET Core 8(WebAPI/gRPC)、MQTTnet(MQTT Broker)、Serilog(统一日志)、InfluxDB(时序数据存储)、Redis(实时数据缓存)、SQL Server(关系型数据)
工厂级管控层全厂数据汇总、统一权限管控、跨车间调度、MES/ERP系统对接、可视化大屏、报表统计、全局报警管理ASP.NET Core 8(后端服务)、Blazor(Web管控端/大屏)、Identity Framework(RBAC权限)、Quartz.NET(定时任务)、EFCore(ORM框架)

这里重点提两个选型的原因:

  1. 为什么用MQTT做核心通信协议?工厂里设备网和生产网是隔离的,防火墙只允许边缘端主动外联,不允许外网主动访问设备网。MQTT是客户端主动连接Broker,只需要开一个1883(加密用8883)端口,完全适配工厂的网络隔离要求,而且协议轻量,开销极小,断连重连机制成熟,完美适配工业网络波动的场景;
  2. 为什么用时序数据库InfluxDB?一个车间50个工位,每个工位每秒上报100个工艺参数,一天就是4亿多条数据,用SQL Server存历史数据,查询报表直接卡崩。InfluxDB是专门为时序数据设计的,针对工业采集的时间序列数据做了极致优化,同样的数据量,查询速度比SQL Server快上百倍,还支持自动降采样,完美解决工业大数据的存储和查询问题。

四、核心模块C#代码实现:拿来就能用的产线级代码

整个系统的模块非常多,这里我挑4个最核心、最容易踩坑的模块,分享产线验证过的完整代码,都是我们在项目里用了大半年的,稳定性完全有保障。

4.1 边缘采集服务:边缘自治+断网续传的核心实现

边缘采集服务是整个系统的基石,核心要实现两个功能:一是不间断采集PLC数据,本地执行控制逻辑,保证边缘自治;二是断网时本地缓存数据,网络恢复后自动补传,保证数据不丢。

我们用.NET 8的BackgroundService实现后台托管服务,配合SQLite做本地缓存,代码如下:

/// <summary>/// 工位边缘采集托管服务,24小时不间断运行/// </summary>publicclassEdgeCollectService:BackgroundService{privatereadonlyIPlcCommService_plcCommService;// PLC通信服务privatereadonlyIMqttClientService_mqttClientService;// MQTT通信服务privatereadonlyILocalCacheService_localCacheService;// 本地SQLite缓存服务privatereadonlyILogger<EdgeCollectService>_logger;privatereadonlyint_collectInterval=100;// 采集周期100msprivatebool_isNetworkConnected=>_mqttClientService.IsConnected;publicEdgeCollectService(IPlcCommServiceplcCommService,IMqttClientServicemqttClientService,ILocalCacheServicelocalCacheService,ILogger<EdgeCollectService>logger){_plcCommService=plcCommService;_mqttClientService=mqttClientService;_localCacheService=localCacheService;_logger=logger;}protectedoverrideasyncTaskExecuteAsync(CancellationTokenstoppingToken){_logger.LogInformation("边缘采集服务启动,工位编号:{StationId}",AppConfig.StationId);// 启动时先执行补传逻辑:把上次断网未上传的数据补传await_mqttClientService.WaitForConnectionAsync(stoppingToken);awaitReUploadLocalCacheDataAsync(stoppingToken);// 主采集循环while(!stoppingToken.IsCancellationRequested){try{// 1. 核心:本地采集PLC数据,执行控制逻辑,不依赖网络varcollectData=await_plcCommService.CollectRealTimeDataAsync(stoppingToken);if(collectData==null){_logger.LogWarning("PLC数据采集失败,跳过本次循环");awaitTask.Delay(_collectInterval,stoppingToken);continue;}// 2. 数据写入WPF界面绑定的缓存,实时刷新界面AppData.RealTimeData.UpdateData(collectData);// 3. 网络正常:上报数据,同时写入本地备份;网络异常:只写入本地缓存if(_isNetworkConnected){// 先上报实时数据varuploadResult=await_mqttClientService.PublishDataAsync(collectData,stoppingToken);if(!uploadResult){// 上报失败,写入本地缓存,后续补传await_localCacheService.WriteCacheDataAsync(collectData,stoppingToken);_logger.LogWarning("数据上报失败,已写入本地缓存");}else{// 上报成功,触发一次补传逻辑,把之前缓存的数据传上去awaitReUploadLocalCacheDataAsync(stoppingToken);}}else{// 网络断开,只写入本地缓存,不影响本地采集和控制await_localCacheService.WriteCacheDataAsync(collectData,stoppingToken);_logger.LogDebug("网络断开,数据已写入本地缓存");}}catch(Exceptionex){_logger.LogError(ex,"采集循环执行异常");}finally{// 保证采集周期稳定,不受单次循环执行时间影响awaitTask.Delay(_collectInterval,stoppingToken);}}_logger.LogInformation("边缘采集服务已停止");}/// <summary>/// 补传本地缓存的数据,上报成功后删除本地记录/// </summary>privateasyncTaskReUploadLocalCacheDataAsync(CancellationTokenstoppingToken){if(!_isNetworkConnected)return;try{// 每次取100条批量上报,避免单次上报数据量过大varcacheList=await_localCacheService.GetTopCacheDataAsync(100,stoppingToken);if(cacheList==null||cacheList.Count==0)return;varuploadResult=await_mqttClientService.BatchPublishDataAsync(cacheList,stoppingToken);if(uploadResult){// 上报成功,删除已上传的缓存数据varuploadedIds=cacheList.Select(x=>x.Id).ToList();await_localCacheService.DeleteCacheDataAsync(uploadedIds,stoppingToken);_logger.LogInformation("本地缓存数据补传成功,数量:{Count}",uploadedIds.Count);}}catch(Exceptionex){_logger.LogError(ex,"本地缓存数据补传异常");}}}

这段代码的核心,就是把本地采集控制和网络上报完全解耦,哪怕网络完全断开,采集和控制逻辑也能正常执行,不会影响工位生产,同时数据不会丢失,网络恢复后自动补传,完美符合工业场景的需求。

4.2 MQTT通信模块:边缘端与服务端的通信封装

我们用MQTTnet这个成熟的开源库,封装了边缘端的MQTT客户端,核心实现自动重连、消息发布、订阅指令的功能,适配工业网络波动的场景:

/// <summary>/// MQTT客户端服务封装,适配工业网络波动场景/// </summary>publicclassMqttClientService:IMqttClientService{privatereadonlyIMqttClient_mqttClient;privatereadonlyMqttClientOptions_clientOptions;privatereadonlyILogger<MqttClientService>_logger;privatereadonlyCancellationToken_stoppingToken;publicboolIsConnected=>_mqttClient.IsConnected;publicMqttClientService(ILogger<MqttClientService>logger,IHostApplicationLifetimeappLifetime){_logger=logger;_stoppingToken=appLifetime.ApplicationStopping;// 初始化MQTT客户端配置_clientOptions=newMqttClientOptionsBuilder().WithTcpServer(AppConfig.MqttBrokerIp,AppConfig.MqttBrokerPort).WithCredentials(AppConfig.MqttUserName,AppConfig.MqttPassword).WithClientId($"Station_{AppConfig.StationId}_{Guid.NewGuid():N}")// 客户端ID唯一,避免重复连接被踢.WithCleanSession(false)// 保留会话,断连重连后能收到离线消息.WithKeepAlivePeriod(TimeSpan.FromSeconds(5))// 心跳包5秒.WithTimeout(TimeSpan.FromSeconds(3)).Build();_mqttClient=newMqttFactory().CreateMqttClient();// 注册事件_mqttClient.ConnectedAsync+=OnConnectedAsync;_mqttClient.DisconnectedAsync+=OnDisconnectedAsync;_mqttClient.ApplicationMessageReceivedAsync+=OnMessageReceivedAsync;}/// <summary>/// 启动客户端连接/// </summary>publicasyncTaskStartAsync(CancellationTokencancellationToken){try{await_mqttClient.ConnectAsync(_clientOptions,cancellationToken);_logger.LogInformation("MQTT客户端连接成功,Broker地址:{Ip}:{Port}",AppConfig.MqttBrokerIp,AppConfig.MqttBrokerPort);}catch(Exceptionex){_logger.LogError(ex,"MQTT客户端连接失败");}}/// <summary>/// 等待连接成功,超时时间30秒/// </summary>publicasyncTaskWaitForConnectionAsync(CancellationTokencancellationToken){varwaitCount=0;while(!IsConnected&&waitCount<30&&!cancellationToken.IsCancellationRequested){awaitTask.Delay(1000,cancellationToken);waitCount++;}}/// <summary>/// 发布单条采集数据/// </summary>publicasyncTask<bool>PublishDataAsync(CollectDataModeldata,CancellationTokencancellationToken){if(!IsConnected)returnfalse;try{varmessage=newMqttApplicationMessageBuilder().WithTopic($"Factory/Workshop/{AppConfig.WorkshopId}/Station/{AppConfig.StationId}/Data").WithPayload(JsonSerializer.Serialize(data)).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)// QoS1,保证消息至少送达一次.WithRetainFlag(false).Build();varresult=await_mqttClient.PublishAsync(message,cancellationToken);returnresult.ReasonCode==MqttClientPublishReasonCode.Success;}catch(Exceptionex){_logger.LogError(ex,"MQTT消息发布失败");returnfalse;}}/// <summary>/// 断连自动重连/// </summary>privateasyncTaskOnDisconnectedAsync(MqttClientDisconnectedEventArgsargs){_logger.LogWarning("MQTT客户端断开连接,原因:{Reason}",args.Reason);if(_stoppingToken.IsCancellationRequested)return;// 断连后自动重连,间隔1秒,无限重试while(!_stoppingToken.IsCancellationRequested){try{awaitTask.Delay(1000,_stoppingToken);varresult=await_mqttClient.ConnectAsync(_clientOptions,_stoppingToken);if(result.ResultCode==MqttClientConnectResultCode.Success){_logger.LogInformation("MQTT客户端重连成功");break;}}catch(Exceptionex){_logger.LogError(ex,"MQTT客户端重连失败,继续重试");}}}// 其他方法:批量发布、订阅指令处理、连接成功事件等,篇幅原因不全部展示}

这里有两个关键细节,是我们踩坑后优化的:

  1. 客户端ID必须唯一,加上工位号和GUID,避免多个工位用同一个客户端ID,导致连接被Broker踢下线;
  2. QoS等级用AtLeastOnce,保证消息至少送达一次,配合本地消息ID去重,既不会丢数据,也不会重复上报。

4.3 全厂级分布式权限管控:RBAC权限系统实现

工厂级管控的核心,就是统一的权限管理,不能每个工位自己管自己的用户。我们基于ASP.NET Core Identity,实现了一套RBAC(基于角色的访问控制)权限系统,支持工位级、车间级、工厂级三级权限隔离,完全适配工厂的组织架构。

核心权限设计:

  • 超管:全厂所有权限,系统配置、用户管理
  • 厂长:全厂所有数据查看、报表统计、全局调度
  • 车间主任:对应车间的所有数据查看、报警处理、报表统计
  • 工艺员:配方管理、工艺参数下发、工艺数据查看
  • 设备工程师:设备数据查看、故障处理、设备维护记录
  • 操作工:对应工位的界面查看、设备启停操作,无参数修改权限

核心代码实现了权限校验过滤器,所有API接口都能通过特性标注权限,自动校验:

/// <summary>/// 自定义权限校验特性/// </summary>[AttributeUsage(AttributeTargets.Method|AttributeTargets.Class)]publicclassPermissionAttribute:AuthorizeAttribute,IAsyncAuthorizationFilter{privatereadonlystring_permissionCode;privatereadonlyint_dataLevel;// 数据权限等级:1-工位级 2-车间级 3-工厂级publicPermissionAttribute(stringpermissionCode,intdataLevel=3){_permissionCode=permissionCode;_dataLevel=dataLevel;}publicasyncTaskOnAuthorizationAsync(AuthorizationFilterContextcontext){varuser=context.HttpContext.User;if(!user.Identity.IsAuthenticated){context.Result=newUnauthorizedResult();return;}// 获取用户服务varuserService=context.HttpContext.RequestServices.GetRequiredService<IUserService>();varuserId=user.FindFirstValue(ClaimTypes.NameIdentifier);// 1. 校验功能权限varhasPermission=awaituserService.CheckUserPermissionAsync(userId,_permissionCode);if(!hasPermission){context.Result=newForbidResult();return;}// 2. 校验数据权限varuserDataLevel=awaituserService.GetUserDataLevelAsync(userId);if(userDataLevel<_dataLevel){context.Result=newForbidResult();return;}// 3. 把用户的车间、工位权限写入HttpContext,后续业务逻辑直接用varuserWorkshops=awaituserService.GetUserWorkshopIdsAsync(userId);context.HttpContext.Items["UserWorkshopIds"]=userWorkshops;}}// API接口使用示例[ApiController][Route("api/[controller]")]publicclassWorkshopDataController:ControllerBase{/// <summary>/// 获取车间产量数据,需要车间级以上数据权限/// </summary>[HttpGet("output")][Permission("WorkshopData:View",dataLevel:2)]publicasyncTask<IActionResult>GetWorkshopOutput([FromQuery]intworkshopId,[FromQuery]DateTimestartTime,[FromQuery]DateTimeendTime){// 校验用户是否有该车间的权限varuserWorkshops=HttpContext.Items["UserWorkshopIds"]asList<int>;if(!userWorkshops.Contains(workshopId)){returnForbid();}// 业务逻辑vardata=await_workshopDataService.GetWorkshopOutputAsync(workshopId,startTime,endTime);returnOk(data);}}

这套权限系统,实现了功能权限和数据权限的双重管控,用户在全厂任意一个终端登录,都只能看到自己权限范围内的内容,完全满足工厂的管理要求和合规要求。

4.4 分布式报警中心:全链路报警闭环处理

工厂里的报警管理,绝对不是简单的弹窗提示,而是要实现边缘端本地报警、车间级汇总、工厂级全局推送、报警确认、处理记录、闭环追溯的全流程管理。

核心实现逻辑:

  1. 边缘端采集到报警信号,本地立即弹窗+声光报警,同时通过MQTT上报到车间服务;
  2. 车间服务收到报警,根据报警等级,推送给对应的负责人(比如设备故障推给设备工程师,质量报警推给工艺员);
  3. 工厂级平台实时展示所有车间的报警数据,统计报警次数、故障停机时间,生成报表;
  4. 报警处理完成后,处理人填写处理记录,系统闭环归档,实现全流程追溯。

五、项目落地踩过的那些致命坑,每一个都导致过停线

这部分是整篇文章最有价值的内容,都是我们用停线的代价踩出来的坑,每一个都能帮你避开项目里的致命问题。

坑1:把控制逻辑放到服务端,网络波动直接停线

这是我们最开始犯的最致命的错误,把工位的工艺逻辑判断、设备联动控制放到了车间服务端,边缘端只负责采集数据和执行指令。结果车间的工业交换机出了故障,网络断了5分钟,整个车间的工位全停了,客户当场就发了火,停线1小时损失了十几万。

解决方案:严格遵守边缘自治第一原则,所有实时控制逻辑、设备联动、急停处理,全部在边缘端本地执行,服务端只负责非实时的参数下发、数据汇总、配方管理,哪怕网络完全断开,工位也能正常生产。

坑2:用SQL Server存时序数据,报表查询直接卡崩

最开始我们把所有的采集数据都存在SQL Server里,一个车间50个工位,一天就产生4亿多条数据,客户要查一个月的产量报表,直接查了10分钟都没出来,数据库CPU直接拉满,整个系统都卡了。

解决方案:用时序数据库InfluxDB存储历史采集数据,针对高频采集数据做降采样:

  • 原始100ms采集的数据,保留7天;
  • 1分钟级降采样数据(最大值、最小值、平均值),保留1年;
  • 1小时级降采样数据,保留3年;
    优化后,同样的报表查询,响应时间从10分钟降到了200ms以内,性能提升了3000倍。

坑3:全厂设备时间不同步,数据统计完全对不上

项目上线初期,客户经常投诉两个车间的产量统计对不上,同一个产品的生产时间,在两个工位差了5分钟,追溯的时候完全对不上。查了好久才发现,各个工位的工控机、PLC、服务端的时间都不一样,最多的差了十几分钟。

解决方案:在工厂机房搭建一台NTP时间服务器,全厂所有的工控机、PLC、服务器、交换机,全部统一同步这台NTP服务器的时间,误差控制在100ms以内,彻底解决了时间不同步的问题。

坑4:网络隔离导致的对接失败,被IT部门打回3次

工厂的网络是三层隔离的:设备网(工位PLC、工控机)、生产网(车间服务)、办公网(工厂平台、MES),防火墙默认拒绝所有跨网访问,只允许白名单端口。最开始我们用WebAPI做对接,要在设备网开一堆入站端口,被客户的IT部门连续打回3次,说不符合网络安全规范。

解决方案:全部改用MQTT协议,边缘端(设备网)主动连接生产网的MQTT Broker,只需要在生产网开一个1883端口,设备网不需要开任何入站端口,完美适配了工厂的网络隔离要求,一次性通过了IT部门的安全审核。

坑5:程序升级要挨个工位跑,50个工位要一下午

最开始的单机版,程序升级要工程师带着U盘,挨个工位跑一遍,50个工位要一下午,还只能半夜产线停了才能升级,非常麻烦。

解决方案:做了自动升级功能,在服务端搭建升级包管理服务,边缘端上位机启动的时候,自动检查服务端的最新版本,有新版本就自动下载升级包,静默安装升级,不需要人工干预。后来我们还加了灰度升级功能,先给2个测试工位升级,没问题再全车间推送,彻底解决了升级难的问题。

六、最终落地效果

这套分布式上位机系统,我们在3个汽车零部件工厂落地后,给客户带来的提升是肉眼可见的:

  1. 数据统计效率提升100倍:原来车间主任每天下班要花2小时手动汇总数据,现在实时报表自动生成,点开就能看,数据准确率100%;
  2. 故障处理时间缩短60%:原来出了故障要挨个工位查问题,现在报警实时推送给对应负责人,平台直接展示故障点位和原因,平均故障处理时间从40分钟降到了15分钟;
  3. 设备OEE提升15%:通过全厂级的设备数据监控和分析,优化了设备的换型时间和停机等待时间,设备综合效率从原来的75%提升到了90%;
  4. 系统维护成本降低80%:原来升级一次系统要大半天,现在远程一键推送,10分钟就能完成全车间升级,不用再跑现场;
  5. MES对接成本降低90%:原来MES要和每个工位的上位机对接,现在只需要对接工厂级平台的统一接口,对接时间从1个多月降到了3天。

结尾

很多人一提到分布式上位机,就觉得是很复杂、很高大上的东西,其实不然。工业场景的分布式系统,核心从来不是架构有多炫酷,技术有多先进,而是能不能经得住产线24小时不间断运行的考验,能不能解决工厂的实际问题。

这套系统我们现在已经用到了5个工厂项目里,踩过的坑都填平了,稳定性完全经得住考验。后面我会陆续更新这个系列的文章,包括WPF工位上位机的完整工程、MQTT Broker的搭建与优化、InfluxDB时序数据的查询实战、Blazor工厂管控大屏的实现,感兴趣的朋友可以关注一下。

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

深圳视达数码科技有限公司 - 安卓系统软件工程师 面试指南

深圳视达数码科技有限公司 安卓系统软件工程师 职位信息 岗位职责: 1.负责MTK、海思、AML、全志等平台Android系统的framework及HAL层需求开发、维护、优化 2.解决在研发和使用中出现的各类Android设备的性能和稳定性问题,如死机、异常重启、异常关机、冻屏、IO配置等; 3.优…

作者头像 李华
网站建设 2026/10/5 23:34:57

Qwen3-VL:30B一键部署教程:基于Git的私有化本地环境搭建

Qwen3-VL:30B一键部署教程&#xff1a;基于Git的私有化本地环境搭建 1. 为什么你需要这个部署方案 你是不是也遇到过这样的情况&#xff1a;想在公司内网跑一个真正能“看图说话”的大模型&#xff0c;但发现云服务API调用受限、数据出不去&#xff0c;自己搭环境又卡在CUDA版…

作者头像 李华
网站建设 2026/10/5 23:34:57

手把手教你用Qwen3-ASR-0.6B搭建语音转文字系统

手把手教你用Qwen3-ASR-0.6B搭建语音转文字系统 语音转文字技术正在改变我们处理音频内容的方式&#xff0c;无论是会议记录、视频字幕生成还是语音助手开发&#xff0c;都需要高效准确的语音识别能力。今天我将带你从零开始&#xff0c;用Qwen3-ASR-0.6B搭建一个功能强大的语…

作者头像 李华
网站建设 2026/10/5 23:34:58

星图平台新手入门:快速部署Qwen3-VL:30B多模态大模型

星图平台新手入门&#xff1a;快速部署Qwen3-VL:30B多模态大模型 1. 为什么选择Qwen3-VL:30B搭建智能助手 你是不是也遇到过这样的情况&#xff1a;想要一个既能看懂图片内容&#xff0c;又能流畅对话的智能助手&#xff0c;但市面上的方案要么功能单一&#xff0c;要么价格昂…

作者头像 李华
网站建设 2026/10/22 15:50:58

Hunyuan-MT-7B实战落地:集成Hunyuan-MT-Chimera提升翻译质量的完整流程

Hunyuan-MT-7B实战落地&#xff1a;集成Hunyuan-MT-Chimera提升翻译质量的完整流程 1. 引言&#xff1a;为什么需要更好的翻译模型&#xff1f; 你有没有遇到过这样的场景&#xff1f;用翻译工具处理一段专业文档&#xff0c;结果出来的句子生硬别扭&#xff0c;甚至词不达意…

作者头像 李华
网站建设 2026/10/12 3:19:06

【图像去噪】基于块状低秩纹理表征的卡通纹理图像分解的Matlab实现

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和…

作者头像 李华