轻松搞定IEC104协议-源码分享

这篇文章适合对IEC104协议有所了解的开发者。文中概念性的介绍比较少,以干货为主;对IEC104协议了解较少,可以先参考这篇文章电力IEC104规约协议解读(含源码下载)_104协议-CSDN博客 

其实网络通信协议很简单,就是两部分组成(网络通信+协议),IEC104也不例外,简单来说就是IEC104=Socket+协议,搞懂这个,你就能搞懂大部分的网络通信协议。

为了方便理解,这里把协议分成两部分:协议组成和工作流程。

那么,我们只需要搞懂以下三点就能轻松掌握(程序解析在最后)。

1. Socket

2. 协议组成

3. 流程

Socket

网络通信底层采用TCP/IP通信方式,不管你用什么编程语言,对于网络通信编程,Socket是绕不开的。

【IO密集型用异步,计算密集型用并行】

图片

对于Socket通信编程,如果是一对多IO密集型,最好使用异步而不是多线程;如果是一对一,那就无所谓了。

private void ContinueReadBuffer()
{
    try
    {
        _stream.BeginRead(
            _receiveBuffer,
            _receiveBufferOffset,
            _receiveBuffer.Length - _receiveBufferOffset,
            HandleDataReceived,
            _stream);
    }
    catch (Exception ex) 
    {
        HandleReceiveOperationException(ex);
        throw;
    }
}

源码中采用了异步回调的方式BeginRead和EndRead相结合,异步可以更高效的利用CPU系统资源,软件不卡顿,用户体验也更好。

在一对多的情况下,怎么能最大化利用系统资源做到高并发通信,答案肯定不是多线程,看了源码你就知道了。

协议组成

需要搞懂这几个名词:APCI、ASDU、APDU、U帧、S帧、I帧。

图片

APCI:控制信息部分,类似于帧头,由1个byte 的起始字节0x68 + 1 byte的长度 + 4个byte控制位域(CF)组成。

ASDU:存储数据部分。

APDU:等于APCI+ASDU,长度等于APCI+ASDU-2,减去起始字节和APDU长度字节。

图片

U帧:控制报文帧(只包括APCI部分),主要有启动帧、停止帧、测试帧。

图片

S帧:监视帧(只包括APCI部分),接收序号。

图片

I帧:信息传输帧(包括APCI+ASDU部分)。

  • 发送序号和接收序列号是保证数据完整性的条件。

  • 类型标识定义发送数据的格式。

遥测常用类型标识

09—带品质描述的测量值,每个遥测值占3个字节

0d—带品质描述的浮点值,每个遥测值占5个字节

遥信常用类型标识

01—不带时标的单点遥信,每个遥信占1个字节

  • 可变结构体定义发送数据信息是有序还是无序,有序即一个信息体地址,元素的对应地址会在此信息地址基础上依次加1。无序即1个地址对应一个元素。

  • 传输原因定义记录传送的原因以及上行下行方向等。

更详细的解释请参考 

电力IEC104规约协议解读(含源码下载)_104协议-CSDN博客

流程

1. 由客户端(主站)向服务端(从站)发起TCP连接。

2. 连接成功后,向服务端发送链路启动帧。

3. 服务端收到启动帧以后,向客户端回应启动确认帧。

4. 客户端收到启动确认帧,向服务端发送总召唤命令帧。

5. 服务端收到总召唤命令数据请求后,发送总召唤命令数据响应帧,然后继续发送总召唤命令数据。总召唤命令数据发送完成后,发送总召唤命令数据结束帧。

6. 客户端在收到总召唤命令数据结束帧后,发送对时请求帧。

7. 服务器收到对时请求帧后,发送对时响应帧。

8. 由服务器主动向客户端发送变化数据帧。同时,收到客户端发送的控制类命令,回复相应的操作结果。

9. 客户端等到下一个数据总召唤命令数据周期,重复第5步之后的流程。

源码中是针对逆变器进行数据采集,每5分钟发送一次总召,没有涉及对时操作;总召时间间隔可根据需要调整。

程序解析

采用的C#编程语言,Windows Form窗体程序

图片

启动后的窗体

图片

Visual studio开发工具,Common文件夹存放公用类,IEC104文件夹存放104协议逻辑实体,Tools为工具,ZZH是Socket相关类,Form1是主窗体。

图片

主程序流程图

图片

loopTimer定时任务

图片

controlTimer定时任务


void HandleData(int typeId, InformationObject[] infoObjs)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < infoObjs.Length; i++)
    {
        //浮点遥测值
        if (typeId == 13)
        {
            int firstAddress = infoObjs[i].GetInformationObjectAddress();  // 信息地址起始位
            int len = infoObjs[i].GetInformationElements().Length / 2;
            for (int j = 0; j < len; j++)
            {
                int address = firstAddress + j;
                if (address < 16385 || address > 17000)
                {
                    Console.WriteLine("遥测信息地址超出定义范围");
                }
                var value = infoObjs[i].GetInformationElements()[j, 0];

                var kv = "k:" + address + ",v:" + value + "\r\n";
                sb.Append(kv);
                Config104.InsertHash(address, ((EShortFloat)value).GetValue());

            }
        }
        //单点遥信
        else if (typeId == 1)
        {
            int firstAddress = infoObjs[i].GetInformationObjectAddress();  // 信息地址起始位
            int len = infoObjs[i].GetInformationElements().Length;   // 所有信息值长度
            for (int j = 0; j < len; j++)
            {
                int address = firstAddress + j;
                if (address > 500 || address < 0)
                {
                    Console.WriteLine("遥信信息超出定义范围:" + address);
                }
                var value = infoObjs[i].GetInformationElements()[j, 0];

                var kv = "k:" + address + ",v:" + value + "\r\n";
                sb.Append(kv);
                Config104.InsertHash(address, ((ESinglePointWithQuality)value).IsOn());
            }
        }
    }
    if(checkBox1.Checked)
        WriteLog.WriteLogs(sb.ToString());
}

上面代码是数据解析方法,由于没有数据库操作,解析之后的数据存放在Hashtable中,如果想扩展数据库操作,可以在这里修改或直接从Hashtable中获取。

Gitee源码地址:https://gitee.com/zhangzhenhuaO/iec104.git

也可以加作者微(xiaoyiyz)获取源码

  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值