【工业物联网】西门子PLC数据上云案例

不得不说,工业圈是个比较奇怪的圈子,各种各样的项目需求都有,有的人就希望价格低,功能实现即可,有的人又不在乎价格,就要界面好看。最近有一些小伙伴又提出了这样的需求,用最简单的方式,最低的成本,最少的代码,实现本地的PLC数据上云。我想了一下,如果想实现这种需求,我们就要站在巨人的肩膀上,用现成的轮子,将它们进行组装,变成自己的东西。那么这次,我们就采用S7.NET+Log4Net+SQLSugar+MySQL来实现一个西门子PLC数据上云的案例。1、框架实现关于上面4个组件,有一个共同点,那就是开源免费,这样我们就不用在乎价格和授权的问题了,我们先对这4个组件做一个简单的介绍:组件名称功能说明s7.net西门子PLC的开源通信库Log4Net一款.NET下免费的日志工具SQLSugar一款非常轻量级并且特别强大的ORMMySQL一款开放源代码的关系型数据库这个实现过程分为两部分,首先在阿里云服务器中部署一个MySQL数据库,一侧通过s7.net采集西门子PLC,然后使用Log4Net直接插入到阿里云服务器中,另一侧通过SQLSugar从数据库进行查询解析,再进行显示。2、Iot传输实现1) 首先在PLC中准备好需要传输的数据,最好提前都数据到放到同一个存储区中,并且是连续的N个字节,这里以一个结构体为例,里面包含25个浮点数,占100个字节,如下图所示:

2) 然后创建一个DB块,取名为IotDB,DB号为DB1,添加一个Iot结构体变量,如下图所示:

3) 创建一个控制台应用程序,取名为thinger.cn.IotDataTransfer,该项目用于和PLC通信,并将数据传输到阿里云服务器中的MySQL数据中,这里为了方便,直接将读取的字节数组转换16进制字符串进行传输。4) 首先在Nuget服务器中搜索S7netplus,添加到项目中,如下图所示:

5) 接着搜索log4net,添加到项目中,如下图所示:

6) 最后再搜索mysql,添加到项目中,如下图所示:

7) 添加完成之后,初始化PLC对象,然后连接PLC,连接成功后,开启一个定时器,编写程序如下所示:class Program    {        private static Plc plc;        private static Timer timer = new Timer();        static void Main(string[] args)        {            //创建PLC通信对象            plc = new Plc(CpuType.S71200, "192.168.1.210", 0, 0);            //连接PLC            plc.Open();            if (plc.IsConnected)            {                Console.WriteLine("PLC连接成功");                timer.Interval = 1000;                timer.Elapsed += Timer_Elapsed;                timer.Start();            }            else            {                Console.WriteLine("PLC连接失败");            }            Console.ReadLine();        }8) 定时器定时读取PLC数据,然后通过Log4Net直接存储到数据中,如下图所示:private static void Timer_Elapsed(object sender, ElapsedEventArgs e)        {            byte[] res = plc.ReadBytes(DataType.DataBlock, 1, 0, 100);            string msg = BitConverter.ToString(res);            LogHelper.Info(msg);            Console.WriteLine(msg);        }9) 运行程序后,结果如下所示:

10) 使用SQLyog查看服务器数据库数据, 如下所示:

11) 通过这种方式,我们可以很轻松实现PLC数据读取并存储到云端数据库中,初步实现了数据上云,接下来我们可以通过创建一个上位机程序,实现数据的查询、解析及显示。3、Iot接收实现1) 创建一个Windows窗体应用程序,取名为thinger.cn.IotDataReceiver,该项目用于从云服务器的MySQL数据库中查询数据,并将数据解析成需要的数值,然后进行显示。2) 由于参数类型各种情况都有,因此针对参数创建了一个参数实体类,如下所示:public enum DataType    {        Bool,        Byte,        Short,        UShort,        Int,        UInt,        Float,        Double,        String    }    public class IotParam    {        public IotParam(string paramName, int start, int bitLength, DataType paramType)        {            this.ParamName = paramName;            this.Start = start;            this.BitLength = bitLength;            this.ParamType = paramType;        }        public string ParamName { get; set; }        public int Start { get; set; }        public int BitLength { get; set; }        public DataType ParamType { get; set; }        public object ParamValue { get; set; }    }3) UI界面设计如下图所示:

4) 这里采用多线程的方式,持续从数据库中进行数据查询,如果查询到数据,进行解析赋值,否则进行状态显示,代码如下所示:private void GetNewIotValue()        {            while (!cts.IsCancellationRequested)            {                result = IotQueryService.GetIotDB();                if (result != null)                {                    if (AnalysisData(result.Message))                    {                        this.Invoke(new Action(() =>                        {                            foreach (Control ctrl in this.Controls)                            {                                if (ctrl is DialPlate dp)                                {                                    if (dp.Title.Length > 0)                                    {                                        dp.CurrentValue = Convert.ToSingle(ParamList.FirstOrDefault(c => c.ParamName == dp.Title).ParamValue);                                    }                                }                            }                            this.lbl_State.Text = result.DATE.ToString("yyyy-MM-dd HH:mm:ss");                        }));                    }                    else                    {                        this.Invoke(new Action(() =>                        {                            this.lbl_State.Text = "数据解析错误";                        }));                    }                }                else                {                    this.Invoke(new Action(() =>                    {                        this.lbl_State.Text = "未查询到数据";                    }));                }                Thread.Sleep(1000);            }        }5) 最终运行结果如下所示:

(0)

相关推荐