java中使用openmuc j60870库实现IEC104协议的主从站

阅读数:253 评论数:0

跳转到新版页面

分类

python/Java

正文

一、前置内容

1、openmuc帮助文档

https://www.openmuc.org/iec-60870-5-104/javadoc/

2、pom依赖包

<!-- 104协议 -->
<dependency>
    <groupId>org.openmuc</groupId>
    <artifactId>j60870</artifactId>
    <version>1.6.4</version>
</dependency>

二、相关知识点

1、遥测地址

// 发送包含多个浮点数的ASDU (短浮点数)
connection.send(new ASdu(
    ASduType.M_ME_NC_1, // ASDU类型为浮点数
    true,
    CauseOfTransmission.INTERROGATED_BY_STATION,
    false,
    false,
    0,
    aSdu.getCommonAddress(),
    new InformationObject[] {
        new InformationObject(1, new InformationElement[][] {
            { new IeShortFloat(123.45f), new IeQuality(false, false, false, false, false) }
        }),
        // ... 添加更多的 InformationObject 以发送更多的浮点数
    }
));

// 发送包含多个整数的ASDU (标度化值)
connection.send(new ASdu(
    ASduType.M_ME_NB_1, // ASDU类型为标度化值
    true,
    CauseOfTransmission.INTERROGATED_BY_STATION,
    false,
    false,
    0,
    aSdu.getCommonAddress(),
    new InformationObject[] {
        new InformationObject(2, new InformationElement[][] {
            { new IeScaledValue(-32768), new IeQuality(false, false, false, false, false) },
            { new IeScaledValue(10), new IeQuality(false, false, false, false, false) }
        }),
        // ... 添加更多的 InformationObject 以发送更多的整数
    }
));

请注意,每个InformationObject通常对应于一个遥测地址。

遥测地址(也称为信息对象地址)是用来唯一标识子站中的每个数据点的。每个InformationObject实例都有一个关联的地址,这个地址在ASDU中的所有信息对象中应该是唯一的,以便主站可以区分来自子站的不同测量值、状态或计数器。

如果所有的数据都来自同一个子站,它们的公共地址(Common Address)通常是相同的,因为公共地址用于标识整个子站或者逻辑设备。然而,即使这些数据点来自同一个子站,它们的遥测地址也应该是不同的,因为你需要区分子站内部的不同数据点。

例如,假设一个子站有多个传感器,每个传感器测量不同的物理量(如温度、压力、湿度等),那么即使这些传感器都在同一个子站内,每个传感器的读数都应该有一个独特的遥测地址。这样,当主站收到数据时,它可以通过遥测地址知道每个数据点对应于子站中的哪个传感器。

这里是一个简化的例子:

  • 子站A的公共地址:1
    • 温度传感器的遥测地址:101
    • 压力传感器的遥测地址:102
    • 湿度传感器的遥测地址:103

2、IeQuality

IeQuality 类表示信息元素的质量描述符。质量描述符提供了有关遥测或遥信数据质量的附加信息,这对于评估数据的可靠性和采取相应的控制或显示措施至关重要。

IeQuality 的构造函数通常接受几个布尔参数,每个参数代表了质量描述符的一个特定方面。以下是这些参数的典型含义:

  1. 无效 (Invalid):数据是否有效。如果为 true,则表示这个信息元素的值不可信。
  2. 未使用 (Not Used):这个参数在标准中保留,通常不使用。
  3. 溢出 (Overflow):是否发生了溢出。如果为 true,则表示测量值超出了可表示的范围。
  4. 被取代 (Substituted):数据是否被取代。如果为 true,则表示这个值是由自动装置以外的设备或手动输入的。
  5. 非当前值 (Non-topical):数据是否为非当前值。如果为 true,则表示这个值不是最新的测量值,而是过去的某个值。

一个正常的有效测量值可能会使用 new IeQuality(false, false, false, false, false)

3、一次发送多个InformationObject

// 假设您有一个包含多个遥测数据的List<TelemetryDTO> telemetryDTOs
List<TelemetryDTO> telemetryDTOs = ...;

// 创建一个InformationObject数组,大小为telemetryDTOs的大小
InformationObject[] informationObjects = new InformationObject[telemetryDTOs.size()];

// 填充InformationObject数组
for (int i = 0; i < telemetryDTOs.size(); i++) {
    TelemetryDTO telemetryDTO = telemetryDTOs.get(i);
    informationObjects[i] = new InformationObject(i + 1, new InformationElement[][]{
            {
                new IeScaledValue(telemetryDTO.getOrder()),
                new IeQuality(false, false, false, false, false),
                new IeTime56(telemetryDTO.getDetectTime().getTime())
            }
    });
}

// 创建ASdu并包含所有的InformationObject
ASdu aSdu = new ASdu(
        ASduType.M_ME_TE_1, 
        true,
        CauseOfTransmission.INTERROGATED_BY_STATION,
        false, 
        false, 
        0, 
        commonAddress, // 确保这是正确的公共地址
        informationObjects
);

// 发送ASdu
try {
    connection.send(aSdu);
    System.out.println("Sent ASDU with multiple InformationObjects.");
} catch (IOException e) {
    System.err.println("Failed to send ASDU: " + e.getMessage());
}

4、ASdu

// 创建ASdu时指定originatorAddress和commonAddress
ASdu aSdu = new ASdu(
    ASduType.M_SP_TB_1, // 例如,带时间标签的单点信息ASDU类型
    false, // f false then the ASDU contains a sequence of information
    CauseOfTransmission.SPONTANEOUS, // 传输原因,这里是自发的
    false, // 测试标志
    false, // 负确认标志
    originatorAddress, // 发起者地址,通常设置为0
    commonAddress, // 公共地址,根据你的网络配置来设置
    informationObjects // 包含信息对象的数组
);

// 发送ASdu
connection.send(aSdu);

(1)orginatorAddress

是用来标识发送ASDU的设备或者系统的地址。在很多实现中,这个字段通常被设置为0,因为在点对点连接中,通信的发起者是已知的。然而,在一些特定的应用场景中,特别是在网络可能包含多个控制中心或者主站的情况下,originatorAddress 可能会被用来指定发送命令的主站。

(2)commonAddress

这通常是指定给子站的地址。

5、布尔值的上报

在IEC 60870-5-104协议中,布尔值通常通过遥信(Telesignalisation)信息对象来上报。遥信用于表示开关量,例如设备的开/关状态,这些状态可以用布尔值表示。以下是一些常用的信息对象类型,用于上报布尔值:

(1)M_SP_NA_1 (单点信息) - 这是最简单的类型,用于上报单个布尔值,例如一个开关的状态。每个信息元素代表一个二进制状态,通常用于表示开或关。

(2)M_DP_NA_1 (双点信息) - 这个类型用于上报包含两种稳态的布尔值,例如一个断路器的状态,它可以是开、关或不确定。

对于单点信息,布尔值通常是这样表示的:

  • 0 表示OFF或逻辑FALSE
  • 1 表示ON或逻辑TRUE
// 创建一个InformationObject数组,包含一个单点信息对象
InformationObject[] informationObjects = new InformationObject[]{
    new InformationObject(
        objectAddress, // 信息对象地址
        new InformationElement[][]{
            {
                new IeSinglePointWithQuality(
                    booleanValue, // 布尔值
                    false, // 不带时标
                    false, // 不带品质描述符
                    false, // 非当前值
                    false  // 非被取代的值
                )
            }
        }
    )
};

// 创建ASdu并包含信息对象
ASdu aSdu = new ASdu(
    ASduType.M_SP_NA_1, // 单点信息类型
    false, // 是否需要确认
    CauseOfTransmission.SPONTANEOUS, // 传输原因
    false, // 测试标志
    false, // 负确认标志
    0, // 发起者地址,通常设置为0
    commonAddress, // 公共地址
    informationObjects // 包含信息对象的数组
);

// 发送ASdu
connection.send(aSdu);



相关推荐