1. 前言
最近在研究广东电网的101与104规约,也就是DL/T634.5101-2002和DL/T634.5104-2009。因为要做一个规约解析的软件(基于Android平台的),刚开始接触的也是一头雾水,因为没有接触过这方面的知识,所以就在网上搜索各种技术帖,大神经验什么的。
后来在网上找到了一个软件–IEC8705(报文翻译工具).exe,这个可以解析一些101(平衡式)的实例,效果图贴一下。
但有些还是解析不了,并且在网上也找不到他的源码,所以就很苦恼。也找到一些C++的源码,但是由于技术有限,我看不懂。下面就和大家来看看我写的这个简单的Java语言的规约解析。先贴一下效果图(我就在控制台简单演示一下,没有做可视化界面)。
2. Java版效果图
3. 规约详细解释
先看一下我总结的关于规约解析的几个图
101的规约总结
104规约总结
4. 名词解释
这里所说的名词解释,并不是对一些名词的定义的解释,因为这不是我的专业领域,下面我主要针对报文所代表的名词在代码里怎样解释(解析)说一下。
控制域(平衡式)
在报文解析中,我就是按照图里面的取值方法对对应的字节进行取值,然后进行逻辑判断,将结果加到解析结果里面,由于后四位所代表的平衡链路功能码在这里是固定的,所以可以采取枚举或者反射(常量)的方式进行解析
地址域 (以104的信息体地址为例)
在规约中地址才用的低前高后(低位在前高位在后)的规则
例如:68 10 08 00 02 00 09 01 03 00 01 00 01 40 00 2B 02 00(黄色部分为信息体地址)
所以 这个信息体的地址为01 40 00 >> 0x004001=16385
时标CP56Time2a
解析代码如下
/**
* 时标CP56Time2a解析
*
* @param b 时标CP56Time2a(长度为7 的int数组)
* @return 解析结果
*/
public static String TimeScale(int b[]) {
StringBuilder result = new StringBuilder();
int year = b[6] & 0x7F;
int month = b[5] & 0x0F;
int day = b[4] & 0x1F;
int week = (b[4] & 0xE0) / 32;
int hour = b[3] & 0x1F;
int minute = b[2] & 0x3F;
int second = (b[1] << 8) + b[0];
result.append("时标CP56Time2a:20");
result.append(year).append("-");
result.append(String.format("%02d", month)).append("-");
result.append(String.format("%02d", day)).append(",");
result.append(hour).append(":").append(minute).append(":");
result.append(second / 1000 + "." + second % 1000).append("\n");
return result.toString();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
遥测量的解析
在101的遥测中定义到有三种类型的值,分别是归一化值,标度值,短浮点数,具体的定义大家可以参考“电力101/104规约中遥测量类型转换”,下面我说一下在Java中怎么解析这三种类型的值。直接上代码了。
public class Main {
public static void main(String[] args) {
Telemetry telemetry = new Telemetry();
System.out.println(telemetry.Bytes2Float_NVA(0xa4, 0x6a));// 报文数据的为A4 6A(低位在前,高位在后) ,为0x6AA4
System.out.println(telemetry.Bytes2Float_SVA(0xa4, 0x6a));// 报文数据的为A4 6A(低位在前,高位在后) ,为0x6AA4
System.out.println(telemetry.Bytes2Float_IEEE754("3e0779a6"));
//报文数据 A6 79 07 3E = 0x3e0779a6 = 0.1323(IEEE754 短浮点数)http://lostphp.com/hexconvert/
}
}
/**
* 遥测量解析
*
* @author zhangyu
*/
public class Telemetry {
/**
* 归一化值
*/
public static float Bytes2Float_NVA(int low, int high) {
float fVal;
int nva = (high << 8) + low;
// 符号位1位,0为正数,1为负数,后面的为补码表示,
// 正数的补码和原码相同不需要转换。对于负数,先取反码再加1得到补码的补码,就是原码了。
int symbol = (high & 0x80);//符号位:0表示正数,1表示负数
if (symbol == 0x80)
fVal = -1 * (((nva ^ 0xffff) + 1) & 0x7fff);// (nva ^ 0xffff) + 1 :补码的补码 ,取出后面的15位数据乘上-1得到值
else fVal = nva;
return fVal / 32767;//这里的32767值的是一个量纲,一般这个参数是主站和从站商定的
}
/**
* 标度化值
*/
public static float Bytes2Float_SVA(int low, int high) {
float fVal;
int nva = (high << 8) + low;
int symbol = (high & 0x80);//0表示正数,1表示负数
if (symbol == 0x80)
fVal = -1 * (((nva ^ 0xffff) + 1) & 0x7fff);
else fVal = nva;
return fVal;
}
/**
* 短浮点数
*
* @param data 从低位到高位按顺序
* @return
*/
public static float Bytes2Float_IEEE754(String data) {
return Float.intBitsToFloat(Integer.valueOf(data, 16));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
对于短浮点数的计算,在Java的文档里有这样的说明。
还有一些ASDU里的信息体的解析过程代码,有点多,就不一一贴出来了,代码我已经上传了,有想参考的直接下载,代码还有很多地方需要优化,这只是提供大家一个方法。另外代码我只是上传了101部分的,如果有需要104部分的,可以在我的置顶博客里加我微信
---------------------
原文:https://blog.csdn.net/ZhangYu971014/article/details/79841555