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通讯时如何处理字节序问题?数据库连接池怎么优化?点我主页找完整视频教程,连异常处理时的祖传代码都给你瞅瞅。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐