最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】java的com.iec.analysis.解析104出错:类型标识出错,无法解析信息对象

Java crifan 189浏览 0评论
折腾:
【未解决】用Java代码解析104协议收到的数据
期间,继续调试:
68 0E 4E 14 7C 00 65 01 0A 00 0C 00 00 00 00 05 --->>>
*APCI应用规约控制信息*
启动字符[1 byte]: 0x68
应用规约数据单元(APDU)长度[2 byte]:14字节
控制域[3 byte - 6 byte]:
(I格式控制域标志)
发送序列号:2599
接受序列号:62
*ASDU应用服务数据单元*
类属性标识符[7 byte]:Counter interrogation command
可变结构限定词[8 byte]:可变结构限定词:0x01 SQ=0 信息元素地址非顺序 信息元素个数:1
传送原因[9 byte - 10 byte]:[T(test) bit7:0 未实验][P/N bit6:0 肯定确认][原因 bit5~bit0:激活终止 ]
应用服务数据单元公共地址[11 byte - 12 byte]:000CH
类型标识出错,无法解析信息对象!
========================================
68 12 E6 B7 00 00 0F 81 05 00 05 00 01 0C 00 95 42 03 00 00 --->>>
*APCI应用规约控制信息*
启动字符[1 byte]: 0x68
应用规约数据单元(APDU)长度[2 byte]:18字节
控制域[3 byte - 6 byte]:
(I格式控制域标志)
发送序列号:23539
接受序列号:0
*ASDU应用服务数据单元*
类属性标识符[7 byte]:Integrated totals
可变结构限定词[8 byte]:可变结构限定词:0x81 SQ=1 信息元素地址顺序 信息元素个数:1
传送原因[9 byte - 10 byte]:[T(test) bit7:0 未实验][P/N bit6:0 肯定确认][原因 bit5~bit0:请求或者被请求]
应用服务数据单元公共地址[11 byte - 12 byte]:0005H
类型标识出错,无法解析信息对象!
即:
2个sample data,都是后续部分无法解析:类型标识出错,无法解析信息对象!
所以需要继续去解决此问题
找到报错位置的代码
src/refer/java/xxx/src/main/java/com/iec/analysis/protocol104/ASDU.java
    /**
     * @param info 信息地址+信息元素+限定词+(时标)
     * @param i    类型标识
     * @param j    SQ
     * @param k    信息体个数
     * @return
     * @throws Exception
     */
    private static String Infoanalysis(int[] info, int i, int j, int k) {
        String s = "";
        switch (i) {
            case 1:
                s += new Telemetry104().NoTime_Point(info, k, i, j);
                break;
。。。
            case 136:
                s += new ParamePreset104().activate_multi_parmeter(info, k, i, j);
                break;
            default:
                s = "类型标识出错,无法解析信息对象!";
                break;
        }
去看看源码和研究研究协议。
iec 104 Info analysis
CPSS_2018.pdf
期间去:
【已解决】把IEC 104的Cause of Transmission COT的全部定义添加到com.iec.analysis的TransferReason
接着,只能去研究协议,看看如何解析这个:类型标识 101 了。
期间:
【已解决】Java中如何枚举的值返回对应枚举变量本身
TR-IEC104.pdf
The ASDU contains two main sections: the data unit identifier (with the fixed length of six bytes), and the data itself, made up of one or more information objects. The data unit identifier defines the specific type of data, provides addressing to identify the specific identity of the data, and includes additional information as cause of transmission. Each ASDU can transmit maximum 127 objects. The format of ASDU is in Fig. 8
在此期间,需要去:
【已解决】java中获取int数组的其中一部分作为子数组
然后此处暂时加了,几个额外的类型的解析,不过都是很简单的,比如15,21等,最后如下:
src/xxx/src/main/java/com/iec/analysis/protocol104/ASDU.java
    /**
     * @param info 信息地址+信息元素+限定词+(时标)
     * @param typeId    类型标识
     * @param sq    SQ
     * @param objNum    信息体个数
     * @return
     * @throws Exception
     */
    private static String InfoAnalysis(int[] info, int typeId, int sq, int objNum) {
        String s = "";
        switch (typeId) {
            case 1:
                s += new Telemetry104().NoTime_Point(info, objNum, typeId, sq, "SIQ");
                break;
            case 3:
                s += new Telemetry104().NoTime_Point(info, objNum, typeId, sq, "DIQ");
                break;
            case 9:// 测量值,归一化值(遥测)*
                s += new Telesignalling104().normalization(info, objNum, typeId, sq);
                break;
            case 11:// 测量值,标度化值(遥测)
                s += new Telesignalling104().standardization(info, objNum, typeId, sq);
                break;
            case 13:// 测量值,短浮点数(遥测)
                s += new Telesignalling104().short_float(info, objNum, typeId, sq);
                break;
            case 15:
                s += new Telemetry104().pureValue(info, sq, objNum, "BCR", 5);
                break;
            case 21:
                s += new Telemetry104().pureValue(info, sq, objNum, "NVA", 2);
                break;
            case 30:
                s += new Telemetry104().Time_Point(info, objNum, typeId, sq);
                break;
            case 31:
                s += new Telemetry104().Time_Point(info, objNum, typeId, sq);
                break;
            case 45:// 单命令(遥控)
                s = new Telecontrol104().Single_command(info, objNum, typeId);
                break;
            case 46:// 双命令(遥控)
                s = new Telecontrol104().Double_command(info, objNum, typeId);
                break;
            case 48:
                s += new ParamePreset104().activate_single_parmeter(info, objNum, typeId, sq);
                break;
            case 70:
                s += "信息对象地址:";
                s += InfoAddress(info[0], info[1], info[2]);
                s += "\n";
                s += "初始化原因:" + (info[3]) + " ";
                s += (info[3] == 0) ? "当地电源合上" : (info[3] == 1) ? "当地手动复位"
                        : (info[3] == 2) ? "远方复位" : "使用保留";
                break;
            case 100:
                s += "信息对象地址:";
                s += InfoAddress(info[0], info[1], info[2]);
                s += "\n";
                if (info[3] == 20) {
                    s += "召唤限定词QOI:20";
                } else {
                    s += "召唤限定词出错!当前值为0x"
                            + ((info[3] < 10) ? "0" + Integer.toString(info[3], 16)
                            : Integer.toString(info[3], 16))
                            + ",正确值应为0x14!";
                }
                break;
            case 101:
                s += "信息对象地址:";
                s += InfoAddress(info[0], info[1], info[2]);
                s += "\n";
                // QCC=Qualifier of counter interrogation command
                s += String.format("QCC: %d", info[3]);
                break;
            case 102:
                s += new ParamePreset104().single_parmeter(info, objNum, typeId, sq);
                break;
            case 103:
                s += "信息对象地址:";
                s += InfoAddress(info[0], info[1], info[2]);
                s += "\n";
                int[] time = new int[7];
                for (int l = 0; l < time.length; l++) {
                    time[l] = info[3 + l];
                }
                s += TimeScale(time);
                break;


            case 105:
                s += "信息对象地址:";
                s += InfoAddress(info[0], info[1], info[2]);
                s += "\n";
                if (info[3] == 1) {
                    s += "复位进程限定词:1";
                } else {
                    s += "复位进程限定词出错!当前值为0x"
                            + ((info[3] < 10) ? "0" + Integer.toString(info[3], 16)
                            : Integer.toString(info[3], 16))
                            + ",正确值应为0x01!";
                }
                break;
            case 132:
                s += new ParamePreset104().multi_parmeter(info, objNum, typeId, sq);
                break;
            case 136:
                s += new ParamePreset104().activate_multi_parmeter(info, objNum, typeId, sq);
                break;
            default:
                // s = "类型标识出错,无法解析信息对象!";
                s = String.format("无法解析信息对象, 无法识别类型标识:%s", typeId);
                break;
        }


        return s;
    }
如此,目前测试的几个个数据,至少都可以解析了:
至此,至少此处的报错,就解决了。
【总结】
此处之前代码
src/refer/java/xxx/src/main/java/com/iec/analysis/protocol104/ASDU.java
中报错,是因为,不能识别部分的类型。
去加上对应的类型的解析,就可以了。
至少对于此处输入的50个左右的sample data的解析,就支持了,不报错了。

转载请注明:在路上 » 【已解决】java的com.iec.analysis.解析104出错:类型标识出错,无法解析信息对象

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
88 queries in 0.131 seconds, using 21.19MB memory