同时支持串口和网络通讯,如开发一套设备驱动

1.C#跨平台物联网通信框架ServerSuperIO(SSIO卡塔尔介绍

《物联网框架ServerSuperIO教程》-4.如开荒风流罗曼蒂克套设备驱动,同期补助串口和网络通信。附:现在支撑Windows 10 IOT,win10iot

1.C#跨平台物联网通信框架ServerSuperIO(SSIO卡塔尔介绍

《连载 | 物联网框架ServerSuperIO教程》1.4种简报情势机制。

《连载 | 物联网框架ServerSuperIO教程》2.劳动实例的陈设参数表明

《连载 | 物联网框架ServerSuperIO教程》- 3.设施驱动介绍

 

注:ServerSuperIO有十分大大概被移植到Windows 10
IOT上,那么今后有十分大希望开垦后生可畏套装置驱动,能够分段在服务端、嵌入式设备中,将形成完全的缓和方案。

     
现在曾经调节和测量检验通过一些代码,还得须求后生可畏段时间,平日都是夜里干,时间也轻易。如下图:

澳门太阳娱乐官方网站 1

 

目       录

4.如开辟生机勃勃套装置驱动,同一时候帮助串口和网络通信… 2

4.1           概述… 2

4.2           通信合同规定… 2

4.2.1    发送读实时数据命令合同… 2

4.2.2    深入分析实时数据公约… 3

4.2.3    发送和接受数据事例… 3

4.3           开采设备驱动… 3

4.3.1    构建实时数据长久对象(不是必须卡塔尔… 3

4.3.2    营造参数数据持久对象… 5

4.3.3    营造发送和剖析合同命令对象… 5

4.3.4    营造筑组织商驱动对象… 6

4.3.5    营造设备驱动对象… 8

4.4           营造宿主程序… 12

4.5           运转效果… 15

 

 

《连载 |
物联网框架ServerSuperIO教程》1.4种简报方式机制。

4.如开辟生龙活虎套装置驱动,同一时候援助串口和网络通讯

《连载 |
物联网框架ServerSuperIO教程》2.劳务实例的配置参数表明

4.1    概述

    
作为物联网通信框架,确定要协助各个简报链路,在种种简报链路的底子上到位二种广播发表公约的竞相,举例:Modbus、自定义合计等等。不过,有三个难点:针对同豆蔻年华台硬件装置或传感器,实现串口和网络两种简报格局的多寡收罗和垄断,是还是不是要分别写代码?假如从实际角度剖判,同意气风发硬件,它要做到的事体逻辑料定是生龙活虎致的,所以ServerSuperIO物联网框架,允许开垦风流倜傥套装置驱动,同不经常间支持串口和网络二种简报情势的互相。

    
通信很简短、交互作用一点也不细略、业务非常粗大略……如果把无数轻巧易行的主题素材合在一起,那么就变得不简单了,所以要有三个框架性的事物,重新把不知凡几难题变得简单。

《连载 | 物联网框架ServerSuperIO教程》-
3.设备驱动介绍

4.2    通信左券规定

   
在成就贰个配备驱动的成本以前,首先要通晓它的通信公约,好比多个人沟通的语言同样。针对报导合同,大家自定义三个粗略交互作用情势,只是发送命令,提取数额新闻。

 

4.2.1    发送读实时数据命令左券

    
计算机发送0x61限令为读实时数据命令,共发送6个字节,校验和为从“从机地址”起首的增加和,不蕴涵“数据报头”、“校验和”和“公约甘休”。

     发送指令数据帧如下:

帧结构

数量报头

从机地址

命令代码

校验和

共谋甘休

0x55

0xAA

 

0x61

 

0x0D

字节数

1

1

1

1

1

1

  

注:ServerSuperIO有相当的大希望被移植到Windows
10
IOT上,那么今后有不小希望付出生机勃勃套设备驱动,能够分段在服务端、嵌入式设备中,将变成总体的缓慢解决方案。

4.2.2    解析实时数据左券

   
下位机接纳到读实时数据命令后,并校验成功,再次来到实时数据,校验和为从“从机地址”伊始的充分和,不富含“数据报头”、“校验和”和“公约甘休”。

    选拔数据帧如下:

帧结构

数据报头

从机地址

命令代码

流量

信号

校验和

磋商结束

0x55

澳门太阳娱乐官方网站,0xAA

 

0x61

浮点型

浮点型

 

0x0D

字节数

1

1

1

1

4

 

4

1

1

     
以后曾经调节和测量检验通过一些代码,还得供给生龙活虎段时间,平日都以深夜干,时间也可能有数。如下图:

4.2.3    发送和选取数据事例

出殡(十四进制卡塔尔国:0x55 0xaa 0x00 0x61 0x61 0x0d

收起(十五进制卡塔尔:0x55 0xaa 0x00 0x61 0x43 0x7a 0x00 0x00 0x43 0xb4 0x15
0x0d

流量数据为:250.00

确定性信号数据为:360.00

澳门太阳娱乐官方网站 2

4.3    开荒设备驱动

 

4.3.1    营造实时数据悠久对象(不是必得卡塔 尔(阿拉伯语:قطر‎

1.因而再次来到数据的报纸发表公约,有流量和时限信号几个动态变量,大家供给成立叁个动态目的实体类,首要用以左券驱动与设施驱动之间的多寡人机联作。代码如下:

public class Dyn
{
        private float _Flow = 0.0f;
        /// <summary>
        /// 流量
        /// </summary>
        public float Flow
        {
            get { return _Flow; }
            set { _Flow = value; }
        }
        private float _Signal = 0.0f;
        /// <summary>
        /// 信号
        /// </summary>
        public float Signal
        {
            get { return _Signal; }
            set { _Signal = value; }
        }
}

 
2.大家注重的行事是要创立二个实时数据持久对象类,实时缓存数据新闻,也能够把该实时数据音讯保存到数据库中或别的存款和储蓄介质。实时数据长久对象类的代码如下:

public class DeviceDyn:DeviceDynamic
{
        public DeviceDyn() : base()
        {
            Dyn=new Dyn();
        }
        public override string GetAlertState()
        {
            throw new NotImplementedException("无报警信息");
        }
        public override object Repair()
        {
            return new DeviceDyn();
        }
        public Dyn Dyn { get; set; }
}

     DeviceDyn
类世袭自DeviceDynamic,因为每一个硬件装置的告警新闻有十分大可能率不等同,所以GetAlertState函数能够实该功能,可是SSIO框架并未一向援用;那一个类精气神上是一个足以系列化,在不加互斥的境况下也许产生文件损坏,所以Repair能够完成修复功能,在DeviceDynamic基类里金玉锦绣了该意义;其余,完结DeviceDynamic基类自带四个函数,Save函数用于持久化(类别化卡塔尔此类的新闻,Load用于获取(反系列化卡塔 尔(阿拉伯语:قطر‎此类的消息,在设备驱动中可以运用。

目       录

4.3.2    创设参数数据长久对象

   
日常的话硬件配备会有读参数的命令,那么重返来的参数也急需张开长久化存款和储蓄,并且每台设备的参数都恐怕不后生可畏致,在那提供二个可扩展的接口。在这里个报纸发表左券中并从未关联到设备参数相关的协商表达,不过大家也亟需成立一个参数数据长久对象类,能够不写任何扩张的参数属性,在SSIO框架对参数的接口实行了援用,那是必需举办了办事。代码如下:

public class DevicePara:ServerSuperIO.Device.DeviceParameter
{
        public override object Repair()
        {
            return new DevicePara();
        }
}

    
DevicePara世襲自DeviceParameter类,情况与实时数据漫长对象相通,能够参数。

4.如开垦黄金年代套设备驱动,同不时候支持串口和网络通信… 2

4.3.3    创设发送和剖析左券命令对象

   
与设施实行交互作用会涉及到多数人机联作式的一声令下或指令代码,而这几个命令在SSIO框架内是以协商命令对象的样式存在,概况包蕴多个部:推行命令接口、打包发送数据接口、分析接纳数据接口等。

   
针对地点的电视发表协议,有一个61限令,那么我们就足以依靠61下令为命名创设七个共谋命令对象,富含发送数据和分析数据部分。假使有任何命令代码,触类旁通。代码如下:

internal class DeviceCommand:ProtocolCommand
{
        public override string Name
        {
            get { return "61"; }
        }

        public override void ExcuteCommand<T>(T t)
        {
            throw new NotImplementedException();
        }

        public override byte[] Package<T> (string code, T1 t1,T2 t2)
        {
            //发送:0x55 0xaa 0x00 0x61 0x61 0x0d
            byte[] data = new byte[6];
            data[0] = 0x55;
            data[1] = 0xaa;
            data[2] = byte.Parse(code);
            data[3] = 0x61;
            data[4] = this.ProtocolDriver.GetCheckData(data)[0];
            data[5] = 0x0d;
            return data;
        }

        public override dynamic Analysis<T>(byte[] data, T t)
        {
            Dyn dyn = new Dyn()
            //一般下位机是单片的话,接收到数据的高低位需要互换,才能正常解析。
            byte[] flow = BinaryUtil.SubBytes(data, 4, 4, true);
            dyn.Flow = BitConverter.ToSingle(flow, 0);
            byte[] signal = BinaryUtil.SubBytes(data, 8, 4, true);
            dyn.Signal = BitConverter.ToSingle(signal, 0);
            return dyn;
        }

}

    
塑造筑组织议命令必要全方位持续自ProtocolCommand,根据电视发表公约规定,Name属性重临61,作为尤为重要字;Package是包装要送的数量新闻;Analysis对应着选拔数据之后张开剖释操作。仿佛此二个简约的协商命令驱动就创设完毕了。

4.1           概述… 2

4.3.4    创设筑协会谈商讨驱动对象

   
有了契约命令之后,我们需求构建筑组织商驱动对象,SSIO框架扶植自定义磋商也在于此,並且与器材驱动的接口相关联,在SSIO框架的尖端应用中也张开了引用,塑造那引对象很关键。代码如下:

internal class DeviceProtocol:ProtocolDriver
{
        public override bool CheckData(byte[] data)
        {
            if (data[0] == 0x55 && data[1] == 0xaa && data[data.Length - 1] == 0x0d)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override byte[] GetCommand(byte[] data)
        {
            return new byte[] { data[3] };
        }

        public override int GetAddress(byte[] data)
        {
            return data[2];
        }

        public override byte[] GetHead(byte[] data)
        {
            return new byte[] { data[0], data[1] };
        }

        public override byte[] GetEnd(byte[] data)
        {
            return new byte[] { data[data.Length - 1] };
        }

        public override byte[] GetCheckData(byte[] data)
        {
            byte checkSum = 0;
            for (int i = 2; i < data.Length - 2; i++)
            {
                checkSum += data[i];
            }
            return new byte[] { checkSum };
        }

        public override string GetCode(byte[] data)
        {
            throw new NotImplementedException();
        }

        public override int GetPackageLength(byte[] data, IChannel channel, ref int readTimeout)
        {
           throw new NotImplementedException();
        }
}

     DeviceProtocol 协议驱动袭承自ProtocolDriver
,叁个配备驱动只存在多个共谋驱动,一个共谋驱动能够存在两个契约命令(如61限令卡塔 尔(阿拉伯语:قطر‎。该类中的CheckData函数比较重要,SSIO框架中的设备驱动基类引用了,首借使到位校验选用数据的完事性,是或不是切合公约,进而调节了通信状态:通信常常、通信中断、通信忧虑、以至通信未知,不相同的通信状态也调整了调用设备驱动中的哪个函数接口:Communicate、CommunicateInterrupt、CommunicateError和CommunicateNone。

4.2           通信合同鲜明… 2

4.3.5    创设设备驱动对象

    
上面包车型大巴底蕴职业都做完之后,将来就营造设备驱动的骨干部分,相当于SSIO框架与设备驱动对接、协调、调节的独步天下接口,写完这几个接口,设备驱动即可在SSIO上直接运转了,并且与硬件配备开展互相。直接上代码:

public class DeviceDriver:RunDevice
{
        private DeviceDyn _deviceDyn;
        private DevicePara _devicePara;
        private DeviceProtocol _protocol;
        public DeviceDriver() : base()
        {
            _devicePara = new DevicePara();
            _deviceDyn = new DeviceDyn();
            _protocol = new DeviceProtocol();
        }

        public override void Initialize(string devid)
        {
            this.Protocol.InitDriver(this.GetType(),null);
            //初始化设备参数信息
            _devicePara.DeviceID = devid;//设备的ID必须先赋值,因为要查找对应的参数文件。
            if (System.IO.File.Exists(_devicePara.SavePath))
            {
                //如果参数文件存在,则获得参数实例
                _devicePara = _devicePara.Load<DevicePara>();
            }
            else
            {
                //如果参数文件不存在,则序列化一个文件
                _devicePara.Save<DevicePara>(_devicePara);
            }

            //初始化设备实时数据信息
            _deviceDyn.DeviceID = devid;//设备的ID必须先赋值,因为要查找对应的实时数据文件。
            if (System.IO.File.Exists(_deviceDyn.SavePath))
            {
                //参数文件存在,则获得参数实例
                _deviceDyn = _deviceDyn.Load<DeviceDyn>();
            }
            else
            {
                //如果参数文件不存在,则序列化一个文件
                _deviceDyn.Save<DeviceDyn>(_deviceDyn);
            }
        }

        public override byte[] GetConstantCommand()
        {
            return this.Protocol.DriverPackage<String>("0", "61", null);
        }

        public override void Communicate(ServerSuperIO.Communicate.IRequestInfo info)
        {
            Dyn dyn = this.Protocol.DriverAnalysis<String>("61", info.Data, null);
            if (dyn != null)
            {
                _deviceDyn.Dyn = dyn;
            }
            OnDeviceRuningLog("通讯正常");
        }

        public override void CommunicateInterrupt(ServerSuperIO.Communicate.IRequestInfo info)
        {
            OnDeviceRuningLog("通讯中断");
        }

        public override void CommunicateError(ServerSuperIO.Communicate.IRequestInfo info)
        {
            OnDeviceRuningLog("通讯干扰");
        }

        public override void CommunicateNone()
        {
            OnDeviceRuningLog("通讯未知");
        }

        public override void Alert()
        {
            return;
        }

        public override void Save()
        {
            try
            {
                _deviceDyn.Save<DeviceDyn>(_deviceDyn);
            }
            catch (Exception ex)
            {
                OnDeviceRuningLog(ex.Message);
            }
        }

        public override void Show()
        {
            List<string> list=new List<string>();
            list.Add(_devicePara.DeviceName);
            list.Add(_deviceDyn.Dyn.Flow.ToString());
            list.Add(_deviceDyn.Dyn.Signal.ToString());
            OnDeviceObjectChanged(list.ToArray());
        }

        public override void UnknownIO()
        {
            OnDeviceRuningLog("未知通讯接口");
        }

        public override void CommunicateStateChanged(ServerSuperIO.Communicate.CommunicateState comState)
        {
            OnDeviceRuningLog("通讯状态改变");
        }

        public override void ChannelStateChanged(ServerSuperIO.Communicate.ChannelState channelState)
        {
            OnDeviceRuningLog("通道状态改变");
        }

        public override void Exit()
        {
            OnDeviceRuningLog("退出设备");
        }

        public override void Delete()
        {
            OnDeviceRuningLog("删除设备");
        }

        public override object GetObject()
        {
            throw new NotImplementedException();
        }

        public override void ShowContextMenu()
        {
            throw new NotImplementedException();
        }

        public override IDeviceDynamic DeviceDynamic
        {
            get { return _deviceDyn; }
        }

        public override IDeviceParameter DeviceParameter
        {
            get { return _devicePara; }
        }

        public override IProtocolDriver Protocol
       {
            get { return _protocol;}
        }

        public override DeviceType DeviceType
        {
            get { return DeviceType.Common; }
        }

        public override string ModelNumber
        {
            get { return "serversuperio"; }
        }

        public override System.Windows.Forms.Control DeviceGraphics
        {
            get { throw new NotImplementedException(); }
        }
}

   
实时动态数据对象_deviceDyn、参数数据对象_devicePara、合同驱动对象_protocol分别提须要接口:DeviceDynamic、DeviceParameter和Protocol,为SSIO提供可援用的底蕴属性参数。

    
Initialize是设备驱动开端化的函数接口,在这里个接口完毕四个根本办事:开始化公约驱动和参数性的新闻。通过this.Protocol.InitDriver(this.GetType(),null);代码能够加载全部合同命令到协商驱动的缓存中,以便实时调用。当然这里边也得以开展此外地点的行事,但是注意对丰富的拍卖。

    
DeviceType这一个是设备的品类,日常钦定为Common就好了。别的函数接口功用已经在《物联网框架ServerSuperIO教程-3.设备驱动介绍》中详细介绍了,请参照他事他说加以考察。

4.2.1    发送读实时数据命令左券… 2

4.4    创设宿主程序

    
二个简单易行的设施驱动就已经付出好了,光有驱动还不行,那么大家遵照SSIO框架再写几行代码,完毕三个宿主程序,把设备驱动实例化,放SSIO的服务实例中运作,达成串口和互联网二种艺术的简报人机联作,代码也极度简单。代码如下:

class Program
{
        static void Main(string[] args)
        {
            DeviceDriver dev1 = new DeviceDriver();
            dev1.DeviceParameter.DeviceName = "串口设备1";
            dev1.DeviceParameter.DeviceAddr = 0;
            dev1.DeviceParameter.DeviceID = "0";
            dev1.DeviceDynamic.DeviceID = "0";
            dev1.DeviceParameter.COM.Port = 1;
            dev1.DeviceParameter.COM.Baud = 9600;
            dev1.CommunicateType = CommunicateType.COM;
            dev1.Initialize("0");

            DeviceDriver dev4 = new DeviceDriver();
            dev4.DeviceParameter.DeviceName = "网络设备2";
            dev4.DeviceParameter.DeviceAddr = 0;
            dev4.DeviceParameter.DeviceID = "3";
            dev4.DeviceDynamic.DeviceID = "3";
            dev4.DeviceParameter.NET.RemoteIP = "127.0.0.1";
            dev4.DeviceParameter.NET.RemotePort = 9600;
            dev4.CommunicateType = CommunicateType.NET;
            dev4.Initialize("3");

            IServer server = new ServerFactory().CreateServer(new ServerConfig()
            {
                ServerName = "服务实例1",
                SocketMode = SocketMode.Tcp,
                ControlMode = ControlMode.Loop,
                CheckSameSocketSession = false,
                StartCheckPackageLength = false,
            });

            server.AddDeviceCompleted += server_AddDeviceCompleted;
            server.DeleteDeviceCompleted += server_DeleteDeviceCompleted;
            server.SocketConnected+=server_SocketConnected;
            server.SocketClosed+=server_SocketClosed;
            server.Start();

            server.AddDevice(dev1);
            server.AddDevice(dev4);

            while ("exit"==Console.ReadLine())
            {
                 server.Stop();
            }
        }

        private static void server_SocketClosed(string ip, int port)
        {
            Console.WriteLine(String.Format("断开:{0}-{1} 成功", ip, port));
        }

        private static void server_SocketConnected(string ip, int port)
        {
            Console.WriteLine(String.Format("连接:{0}-{1} 成功",ip, port));
        }

        private static void server_AddDeviceCompleted(string devid, string devName, bool isSuccess)

        {
            Console.WriteLine(devName+",增加:"+isSuccess.ToString());
        }

        private static void server_DeleteDeviceCompleted(string devid, string devName, bool isSuccess)
        {
            Console.WriteLine(devName + ",删除:" + isSuccess.ToString());
        }
    }
}

    
那个代码大家都能看精通,具体的垄断形式大家接下去会挨个介绍。在营造宿主程序的时候,切忌对劳务实例那样援引:server.ChannelManager、server.ControllerManager、server.DeviceManager。就算提供了那般的接口,首假设为着SSIO框架之中使用的,无需大家单独去操作这一个接口。有的网上亲密的朋友是如此的写的,那么就改成了二个纯的通讯IO框架,那么就错失了SSIO框架本人的价值。作为三回开辟者,只须求设置设备驱动的参数,以致向劳动实例中追加或删除设备就能够了,其余兼具的周转总体付出SSIO框架来完结。

4.2.2    深入分析实时数据左券… 3

4.5    运维效果

 澳门太阳娱乐官方网站 3

 

1.[连载]《C#通信(串口和互联网卡塔 尔(阿拉伯语:قطر‎框架的安插与落到实处》

2.[开源]C#跨平台物联网通信框架ServerSuperIO(SSIO卡塔尔介绍

2.施用SuperIO(SIO卡塔 尔(英语:State of Qatar)和开源跨平台物联网框架ServerSuperIO(SSIO卡塔尔国营造系统的完整方案

3.C#工业物联网和集成系统施工方案的工夫路径(数据源、数据搜集、数据上传与吸纳、ActiveMQ、Mongodb、WebApi、手提式有线电话机App卡塔尔

5.ServerSuperIO开源地址:

物联网&集成本事(.NET) QQ群54256083

10 IOT,win10iot 1.C#跨平台物联网通讯框…

4.2.3    发送和选取数据事例… 3

4.3           开采设备驱动… 3

4.3.1    构建实时数据持久对象(不是必需卡塔 尔(阿拉伯语:قطر‎… 3

4.3.2    构建参数数据长久对象… 5

4.3.3    塑造发送和分析合同命令对象… 5

4.3.4    创设筑组织商驱动对象… 6

4.3.5    创设设备驱动对象… 8

4.4           营造宿主程序… 12

4.5           运维作效果果… 15

 

 

4.如开垦生龙活虎套设备驱动,同一时候帮忙串口和互连网通讯

4.1    概述

    
作为物联网通信框架,料定要帮忙两种通信链路,在多样简报链路的基础上成功各类报纸发表左券的相互作用,比方:Modbus、自定义协商等等。但是,有二个主题素材:针对同黄金年代台硬件装置或传感器,实现串口和互连网二种简报方式的多寡搜罗和垄断(monopoly卡塔 尔(英语:State of Qatar),是或不是要分别写代码?设若从现实角度深入深入分析,同风度翩翩硬件,它要做到的事体逻辑确定是同等的,所以ServerSuperIO物联网框架,允许开辟生龙活虎套装置驱动,同有时常间协助串口和互联网二种简报模式的相互。

    
通信很粗大略、交互异常的粗略、业务非常轻松……倘使把众多简易的主题材料合在一同,那么就变得不轻便了,所以要有叁个框架性的东西,重新把过多难点变得轻松。

4.2    通信合同规定

   
在做到叁个设施驱动的付出早前,首先要驾驭它的报纸发表左券,好比三人交换的语言相似。针对报纸发表公约,我们自定义叁个差不离人机联作形式,只是发送命令,提取数额消息。

4.2.1    发送读实时数据命令公约

    
计算机发送0x61命令为读实时数据命令,共发送6个字节,校验和为从“从机地址”最初的增进和,不饱含“数据报头”、“校验和”和“左券结束”。

     发送指令数据帧如下:

帧结构

多少报头

从机地址

指令代码

校验和

斟酌结束

0x55

0xAA

 

0x61

 

0x0D

字节数

1

1

1

1

1

1

  

4.2.2    拆解深入分析实时数据合同

   
下位机选拔到读实时数据命令后,并校验成功,重返实时数据,校验和为从“从机地址”初始的丰盛和,不包涵“数据报头”、“校验和”和“左券甘休”。

    选择数据帧如下:

帧结构

数码报头

从机地址

一声令下代码

流量

信号

校验和

情商甘休

0x55

0xAA

 

0x61

浮点型

浮点型

 

0x0D

字节数

1

1

1

1

4

 

4

1

1

4.2.3    发送和选拔数据事例

发送(十四进制卡塔尔国:0x55 0xaa 0x00 0x61 0x61 0x0d

收受(十一进制卡塔尔:0x55 0xaa 0x00 0x61 0x43 0x7a 0x00 0x00 0x43 0xb4 0x15
0x0d

流量数据为:250.00

实信号数据为:360.00

4.3    开采设备驱动

4.3.1    塑造实时数据悠久对象(不是必需卡塔 尔(英语:State of Qatar)

1.通过再次回到数据的通信合同,有流量和非确定性信号多个动态变量,大家须求创建多少个动态目标实体类,主要用以合同驱动与设施驱动之间的多少交互。代码如下:

public class Dyn
{
        private float _Flow = 0.0f;
        /// <summary>
        /// 流量
        /// </summary>
        public float Flow
        {
            get { return _Flow; }
            set { _Flow = value; }
        }
        private float _Signal = 0.0f;
        /// <summary>
        /// 信号
        /// </summary>
        public float Signal
        {
            get { return _Signal; }
            set { _Signal = value; }
        }
}

 
2.大家入眼的干活是要创设七个实时数据长久对象类,实时缓存数据信息,也得以把该实时数据消息保存到数据库中或任何存款和储蓄介质媒质。实时数量漫长对象类的代码如下:

public class DeviceDyn:DeviceDynamic
{
        public DeviceDyn() : base()
        {
            Dyn=new Dyn();
        }
        public override string GetAlertState()
        {
            throw new NotImplementedException("无报警信息");
        }
        public override object Repair()
        {
            return new DeviceDyn();
        }
        public Dyn Dyn { get; set; }
}

     DeviceDyn
类继承自DeviceDynamic,因为各类硬件装置的报告急察方新闻有望分裂等,所以GetAlertState函数能够实该成效,不过SSIO框架并未一向援引;那么些类精气神上是一个能够类别化,在不加互斥的动静下可能以致文件损坏,所以Repair能够成功修复功用,在DeviceDynamic基类里实现了该功效;别的,完毕DeviceDynamic基类自带多个函数,Save函数用于悠久化(系列化卡塔尔国此类的音信,Load用于获取(反体系化卡塔 尔(英语:State of Qatar)此类的音信,在设施驱动中得以动用。

4.3.2    构建参数数据持久对象

   
日常的话硬件装置会有读参数的下令,那么再次回到来的参数也急需举行持久化存储,並且每台器械的参数都大概不等同,在那提供二个可扩展的接口。在这里个通讯合同中并未关联到设备参数相关的协商表明,可是大家也亟需创建一个参数数据持久对象类,能够不写任何扩大的参数属性,在SSIO框架对参数的接口实行了引用,这是必须进行了办事。代码如下:

public class DevicePara:ServerSuperIO.Device.DeviceParameter
{
        public override object Repair()
        {
            return new DevicePara();
        }
}

    
DevicePara世襲自DeviceParameter类,景况与实时数据持久对象相符,能够参数。

4.3.3    营造发送和解析合同命令对象

   
与设备举行交互作用会涉及到好些个交互作用式的指令或指令代码,而那么些命令在SSIO框架内是以议和命令对象的花样存在,大意包含多少个部:试行命令接口、打包发送数据接口、深入分析接受数据接口等。

   
针对地点的电视发表左券,有三个61下令,那么我们就能够依照61命令为命名构建一个会谈命令对象,包蕴发送数据和分析数据部分。如若有此外命令代码,推而广之。代码如下:

internal class DeviceCommand:ProtocolCommand
{
        public override string Name
        {
            get { return "61"; }
        }

        public override void ExcuteCommand<T>(T t)
        {
            throw new NotImplementedException();
        }

        public override byte[] Package<T> (string code, T1 t1,T2 t2)
        {
            //发送:0x55 0xaa 0x00 0x61 0x61 0x0d
            byte[] data = new byte[6];
            data[0] = 0x55;
            data[1] = 0xaa;
            data[2] = byte.Parse(code);
            data[3] = 0x61;
            data[4] = this.ProtocolDriver.GetCheckData(data)[0];
            data[5] = 0x0d;
            return data;
        }

        public override dynamic Analysis<T>(byte[] data, T t)
        {
            Dyn dyn = new Dyn()
            //一般下位机是单片的话,接收到数据的高低位需要互换,才能正常解析。
            byte[] flow = BinaryUtil.SubBytes(data, 4, 4, true);
            dyn.Flow = BitConverter.ToSingle(flow, 0);
            byte[] signal = BinaryUtil.SubBytes(data, 8, 4, true);
            dyn.Signal = BitConverter.ToSingle(signal, 0);
            return dyn;
        }

}

    
营造筑组织议命令需要全部袭承自ProtocolCommand,根据电视发表协议规定,Name属性再次来到61,作为根本字;Package是包装要送的数额新闻;Analysis对应着选用数据之后进行深入分析操作。就那样多个轻巧易行的说道命令驱动就营造形成了。

4.3.4    创设筑组织商驱动对象

   
有了和煦命令之后,大家必要创设协商驱动对象,SSIO框架扶助自定义协调也在于此,而且与设备驱动的接口相关联,在SSIO框架的高档应用中也進展了援引,创设那引对象比较重大。代码如下:

internal class DeviceProtocol:ProtocolDriver
{
        public override bool CheckData(byte[] data)
        {
            if (data[0] == 0x55 && data[1] == 0xaa && data[data.Length - 1] == 0x0d)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override byte[] GetCommand(byte[] data)
        {
            return new byte[] { data[3] };
        }

        public override int GetAddress(byte[] data)
        {
            return data[2];
        }

        public override byte[] GetHead(byte[] data)
        {
            return new byte[] { data[0], data[1] };
        }

        public override byte[] GetEnd(byte[] data)
        {
            return new byte[] { data[data.Length - 1] };
        }

        public override byte[] GetCheckData(byte[] data)
        {
            byte checkSum = 0;
            for (int i = 2; i < data.Length - 2; i++)
            {
                checkSum += data[i];
            }
            return new byte[] { checkSum };
        }

        public override string GetCode(byte[] data)
        {
            throw new NotImplementedException();
        }

        public override int GetPackageLength(byte[] data, IChannel channel, ref int readTimeout)
        {
           throw new NotImplementedException();
        }
}

     DeviceProtocol 契约驱动世襲自ProtocolDriver
,一个设备驱动只存在七个商谈驱动,多个争论驱动能够存在八个合同命令(如61指令)。该类中的CheckData函数很珍视,SSIO框架中的设备驱动基类援用了,首借使水到渠成校验接受数据的完事性,是还是不是契合合同,进而调整了通信状态:通信寻常、通信中断、通信忧虑、乃至通信未知,不一样的通信状态也调控了调用设备驱动中的哪个函数接口:Communicate、CommunicateInterrupt、CommunicateError和CommunicateNone。

4.3.5    创设设备驱动对象

    
上边包车型大巴根底蕴作都做完事后,现在就营造设备驱动的主旨部分,也正是SSIO框架与道具驱动对接、和睦、调节的独占鳌头接口,写完那几个接口,设备驱动就能够在SSIO上一直运营了,而且与硬件道具进行人机联作。间接上代码:

public class DeviceDriver:RunDevice
{
        private DeviceDyn _deviceDyn;
        private DevicePara _devicePara;
        private DeviceProtocol _protocol;
        public DeviceDriver() : base()
        {
            _devicePara = new DevicePara();
            _deviceDyn = new DeviceDyn();
            _protocol = new DeviceProtocol();
        }

        public override void Initialize(string devid)
        {
            this.Protocol.InitDriver(this.GetType(),null);
            //初始化设备参数信息
            _devicePara.DeviceID = devid;//设备的ID必须先赋值,因为要查找对应的参数文件。
            if (System.IO.File.Exists(_devicePara.SavePath))
            {
                //如果参数文件存在,则获得参数实例
                _devicePara = _devicePara.Load<DevicePara>();
            }
            else
            {
                //如果参数文件不存在,则序列化一个文件
                _devicePara.Save<DevicePara>(_devicePara);
            }

            //初始化设备实时数据信息
            _deviceDyn.DeviceID = devid;//设备的ID必须先赋值,因为要查找对应的实时数据文件。
            if (System.IO.File.Exists(_deviceDyn.SavePath))
            {
                //参数文件存在,则获得参数实例
                _deviceDyn = _deviceDyn.Load<DeviceDyn>();
            }
            else
            {
                //如果参数文件不存在,则序列化一个文件
                _deviceDyn.Save<DeviceDyn>(_deviceDyn);
            }
        }

        public override byte[] GetConstantCommand()
        {
            return this.Protocol.DriverPackage<String>("0", "61", null);
        }

        public override void Communicate(ServerSuperIO.Communicate.IRequestInfo info)
        {
            Dyn dyn = this.Protocol.DriverAnalysis<String>("61", info.Data, null);
            if (dyn != null)
            {
                _deviceDyn.Dyn = dyn;
            }
            OnDeviceRuningLog("通讯正常");
        }

        public override void CommunicateInterrupt(ServerSuperIO.Communicate.IRequestInfo info)
        {
            OnDeviceRuningLog("通讯中断");
        }

        public override void CommunicateError(ServerSuperIO.Communicate.IRequestInfo info)
        {
            OnDeviceRuningLog("通讯干扰");
        }

        public override void CommunicateNone()
        {
            OnDeviceRuningLog("通讯未知");
        }

        public override void Alert()
        {
            return;
        }

        public override void Save()
        {
            try
            {
                _deviceDyn.Save<DeviceDyn>(_deviceDyn);
            }
            catch (Exception ex)
            {
                OnDeviceRuningLog(ex.Message);
            }
        }

        public override void Show()
        {
            List<string> list=new List<string>();
            list.Add(_devicePara.DeviceName);
            list.Add(_deviceDyn.Dyn.Flow.ToString());
            list.Add(_deviceDyn.Dyn.Signal.ToString());
            OnDeviceObjectChanged(list.ToArray());
        }

        public override void UnknownIO()
        {
            OnDeviceRuningLog("未知通讯接口");
        }

        public override void CommunicateStateChanged(ServerSuperIO.Communicate.CommunicateState comState)
        {
            OnDeviceRuningLog("通讯状态改变");
        }

        public override void ChannelStateChanged(ServerSuperIO.Communicate.ChannelState channelState)
        {
            OnDeviceRuningLog("通道状态改变");
        }

        public override void Exit()
        {
            OnDeviceRuningLog("退出设备");
        }

        public override void Delete()
        {
            OnDeviceRuningLog("删除设备");
        }

        public override object GetObject()
        {
            throw new NotImplementedException();
        }

        public override void ShowContextMenu()
        {
            throw new NotImplementedException();
        }

        public override IDeviceDynamic DeviceDynamic
        {
            get { return _deviceDyn; }
        }

        public override IDeviceParameter DeviceParameter
        {
            get { return _devicePara; }
        }

        public override IProtocolDriver Protocol
       {
            get { return _protocol;}
        }

        public override DeviceType DeviceType
        {
            get { return DeviceType.Common; }
        }

        public override string ModelNumber
        {
            get { return "serversuperio"; }
        }

        public override System.Windows.Forms.Control DeviceGraphics
        {
            get { throw new NotImplementedException(); }
        }
}

   
实时动态数据对象_deviceDyn、参数数据对象_devicePara、左券驱动对象_protocol分别提需要接口:DeviceDynamic、DeviceParameter和Protocol,为SSIO提供可援用的底蕴属性参数。

    
Initialize是设备驱动伊始化的函数接口,在这里个接口实现八个重大办事:发轫化左券驱动和参数性的新闻。通过this.Protocol.InitDriver(this.GetType(),null);代码能够加载全部公约命令到协商驱动的缓存中,以便实时调用。当然这里边也可以开展另一方面包车型地铁劳作,但是注意对丰富的管理。

    
DeviceType那几个是器械的种类,通常钦定为Common就好了。其余函数接口功效已经在《物联网框架ServerSuperIO教程-3.设备驱动介绍》中详细介绍了,请参照他事他说加以考查。

4.4    创设宿主程序

    
二个简练的道具驱动就已经支付好了,光有驱动还百般,那么大家依据SSIO框架再写几行代码,完结贰个宿主程序,把器材驱动实例化,放SSIO的劳动实例中运行,达成串口和互联网三种艺术的简报人机联作,代码也特轻松。代码如下:

class Program
{
        static void Main(string[] args)
        {
            DeviceDriver dev1 = new DeviceDriver();
            dev1.DeviceParameter.DeviceName = "串口设备1";
            dev1.DeviceParameter.DeviceAddr = 0;
            dev1.DeviceParameter.DeviceID = "0";
            dev1.DeviceDynamic.DeviceID = "0";
            dev1.DeviceParameter.COM.Port = 1;
            dev1.DeviceParameter.COM.Baud = 9600;
            dev1.CommunicateType = CommunicateType.COM;
            dev1.Initialize("0");

            DeviceDriver dev4 = new DeviceDriver();
            dev4.DeviceParameter.DeviceName = "网络设备2";
            dev4.DeviceParameter.DeviceAddr = 0;
            dev4.DeviceParameter.DeviceID = "3";
            dev4.DeviceDynamic.DeviceID = "3";
            dev4.DeviceParameter.NET.RemoteIP = "127.0.0.1";
            dev4.DeviceParameter.NET.RemotePort = 9600;
            dev4.CommunicateType = CommunicateType.NET;
            dev4.Initialize("3");

            IServer server = new ServerFactory().CreateServer(new ServerConfig()
            {
                ServerName = "服务实例1",
                SocketMode = SocketMode.Tcp,
                ControlMode = ControlMode.Loop,
                CheckSameSocketSession = false,
                StartCheckPackageLength = false,
            });

            server.AddDeviceCompleted += server_AddDeviceCompleted;
            server.DeleteDeviceCompleted += server_DeleteDeviceCompleted;
            server.SocketConnected+=server_SocketConnected;
            server.SocketClosed+=server_SocketClosed;
            server.Start();

            server.AddDevice(dev1);
            server.AddDevice(dev4);

            while ("exit"==Console.ReadLine())
            {
                 server.Stop();
            }
        }

        private static void server_SocketClosed(string ip, int port)
        {
            Console.WriteLine(String.Format("断开:{0}-{1} 成功", ip, port));
        }

        private static void server_SocketConnected(string ip, int port)
        {
            Console.WriteLine(String.Format("连接:{0}-{1} 成功",ip, port));
        }

        private static void server_AddDeviceCompleted(string devid, string devName, bool isSuccess)

        {
            Console.WriteLine(devName+",增加:"+isSuccess.ToString());
        }

        private static void server_DeleteDeviceCompleted(string devid, string devName, bool isSuccess)
        {
            Console.WriteLine(devName + ",删除:" + isSuccess.ToString());
        }
    }
}

    
这么些代码大家都能看精通,具体的调节方式咱们接下去会相继介绍。在创设宿主程序的时候,切忌对劳务实例那样援用:server.ChannelManager、server.ControllerManager、server.DeviceManager。就算提供了那样的接口,首若是为着SSIO框架之中接纳的,无需我们单独去操作这个接口。有的网上朋友是如此的写的,那么就改为了一个纯的通讯IO框架,那么就失去了SSIO框架自个儿的价值。作为二回开荒者,只需求设置设备驱动的参数,以至向劳动实例中扩大或删除设备就能够了,别的兼具的周转总体交付SSIO框架来造成。

4.5    运转作效果果

 澳门太阳娱乐官方网站 4

 

1.[连载]《C#电视发表(串口和网络卡塔 尔(阿拉伯语:قطر‎框架的规划与得以达成》

2.[开源]C#跨平台物联网通讯框架ServerSuperIO(SSIO卡塔 尔(英语:State of Qatar)介绍

2.利用SuperIO(SIO卡塔 尔(英语:State of Qatar)和开源跨平台物联网框架ServerSuperIO(SSIO卡塔尔国创设系统的完好方案

3.C#工业物联网和集成系统技术方案的技术路线(数据源、数据搜聚、数据上传与摄取、ActiveMQ、Mongodb、WebApi、手机App卡塔尔国

5.ServerSuperIO开源地址:

物联网&集成技能(.NET) QQ群54256083