C#上位机与西门子PLC通讯,读取数据,存储数据库,形成报表可查询,报警历史查询,变量自定义配置。 每一步都有视频讲解(详细视频教程) 案例:涉及多线程,数据库存储,与PLC通讯等技术
通讯连接才是硬道理
Sharp7库的DLL扔进项目,连PLC跟找对象似的得先对上暗号:
var plc = new S7Client(); int result = plc.ConnectTo("192.168.0.1", 0, 1); //IP,机架,槽号 if (result == 0) { Console.WriteLine("握手成功!PLC型号:" + plc.GetCpuType()); }遇到过最邪门的bug是网线水晶头氧化导致随机掉线,后来加了个心跳检测线程:
Task.Run(() => { while (true) { if (!plc.GetPlcStatus()) { _logger.Warning("PLC失联!尝试重连..."); plc.ForceReconnect(); } Thread.Sleep(3000); } });数据入库要玩出花
用EF Core搞批量插入比单条写入快20倍不止:
var buffer = new ConcurrentQueue<PlcData>(); //多线程缓冲队列 using var context = new DataContext(); context.ChangeTracker.AutoDetectChangesEnabled = false; while (!token.IsCancellationRequested) { if (buffer.TryDequeue(out var data)) { context.Add(data); if (++count % 500 == 0) //每500条提交 { context.SaveChanges(); context.Dispose(); context = new DataContext(); } } }注意这个坑:DbContext实例不是线程安全的,每个写入线程得单独实例化。
报警处理得像急诊室
C#上位机与西门子PLC通讯,读取数据,存储数据库,形成报表可查询,报警历史查询,变量自定义配置。 每一步都有视频讲解(详细视频教程) 案例:涉及多线程,数据库存储,与PLC通讯等技术
报警触发时除了写库,还得实时弹窗:
public class AlarmDispatcher { private readonly BlockingCollection<Alarm> _alarms = new(); public void RaiseAlarm(string msg) { _alarms.Add(new Alarm(msg)); PlaySound("alert.wav"); //蜂鸣器模拟 } void ProcessAlarms() { foreach (var alarm in _alarms.GetConsumingEnumerable()) { using var popup = new AlarmWindow(alarm); popup.ShowDialog(); } } }用BlockingCollection实现生产者-消费者模型,比手动lock省心多了。
报表生成别当老实人
别傻乎乎自己写SQL统计,用LINQ分组查询真香:
var dailyReport = context.HistoricalData .Where(d => d.Time.Date == DateTime.Today) .GroupBy(d => d.TagName) .Select(g => new { Tag = g.Key, Avg = g.Average(d => d.Value), Max = g.Max(d => d.Value), Min = g.Min(d => d.Value) }).ToList();搭配ClosedXML导出Excel,比Interop方式快还不依赖Office:
using var workbook = new XLWorkbook(); var ws = workbook.AddWorksheet("日报"); ws.Cell(1, 1).Value = "今日设备心跳全记录"; ws.Range("A1:D1").Merge().Style.Font.Bold = true;变量配置得会七十二变
用JSON动态配置点位表才是王道:
{ "DataPoints": [ { "Name": "烘箱温度", "DB": 10, "Offset": 12, "DataType": "Real" }, { "Name": "传送带速度", "DB": 12, "Offset": 8, "DataType": "Int" } ] }解析时上反射大法:
var config = JsonConvert.DeserializeObject<PlcConfig>(File.ReadAllText("points.json")); foreach (var point in config.DataPoints) { var reader = typeof(S7Client).GetMethod($"Read{point.DataType}"); object value = reader.Invoke(plc, new object[] { point.DB, point.Offset }); }这套系统上线三个月后,老张的枸杞茶终于凉透了——他现在有更多时间盯着大盘指数而不是设备屏了。想看PLC通讯时如何处理字节序问题?数据库连接池怎么优化?点我主页找完整视频教程,连异常处理时的祖传代码都给你瞅瞅。