Java通过BACnet协议读取和写入设备信息

在Java中通过BACnet协议读取和写入设备信息,主要依赖BACnet4J库实现。该库支持BACnet/IP通信,提供设备发现、属性读写、事件订阅等功能,适用于楼宇自动化系统开发。以下是具体实现步骤和代码示例:

一、环境准备

  1. 添加依赖

    在Maven项目的pom.xml中引入BACnet4J库(以6.0.1版本为例):

    复制代码
    <dependency>
        <groupId>com.infiniteautomation</groupId>
        <artifactId>bacnet4j</artifactId>
        <version>6.0.1</version>
    </dependency>

    同时需引入其他必要依赖(如日志库):

    复制代码
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.32</version>
    </dependency>
  2. 模拟器准备

    使用**Yabe(Yet Another BACnet Explorer)**模拟设备:

二、核心代码实现

1. 初始化本地设备与网络
java 复制代码
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
import com.serotonin.bacnet4j.transport.DefaultTransport;

public class BACnetInitializer {
    public static LocalDevice initializeLocalDevice(String localIp, int localPort) throws Exception {
        IpNetwork ipNetwork = new IpNetworkBuilder()
                .withLocalBindAddress(localIp) // 本机IP
                .withSubnet("255.255.255.0", 24) // 子网掩码
                .withPort(localPort) // BACnet默认端口47808
                .withReuseAddress(true)
                .build();
        LocalDevice localDevice = new LocalDevice(1234, new DefaultTransport(ipNetwork)); // 本地设备ID
        localDevice.initialize();
        return localDevice;
    }
}
2. 发现远程设备
复制代码
`import com.serotonin.bacnet4j.RemoteDevice;
import java.util.List;

public class DeviceDiscovery {
    public static List<RemoteDevice> discoverDevices(LocalDevice localDevice) {
        localDevice.startRemoteDeviceDiscovery(); // 启动设备发现
        try {
            Thread.sleep(3000); // 等待发现完成(实际项目中建议用监听器)
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return localDevice.getRemoteDevices(); // 获取设备列表
    }
}`
3. 读取设备属性(仅监测)
java 复制代码
import com.serotonin.bacnet4j.type.Encodable;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.util.RequestUtils;

public class PropertyReader {
    public static Encodable readProperty(LocalDevice localDevice, RemoteDevice remoteDevice, 
                                        ObjectIdentifier objectId, PropertyIdentifier property) throws Exception {
        return RequestUtils.getProperty(localDevice, remoteDevice, objectId, property);
    }

    // 示例:读取模拟输入(AI)对象的当前值
    public static void readAnalogInput(LocalDevice localDevice, RemoteDevice remoteDevice, int instanceNumber) throws Exception {
        ObjectIdentifier aiId = new ObjectIdentifier(ObjectIdentifier.ObjectType.analogInput, instanceNumber);
        Encodable value = readProperty(localDevice, remoteDevice, aiId, PropertyIdentifier.presentValue);
        System.out.println("AI值: " + value);
    }
}
4. 写入设备属性(需控制权限)
java 复制代码
import com.serotonin.bacnet4j.service.confirmed.WritePropertyRequest;
import com.serotonin.bacnet4j.service.confirmed.WritePropertyResponse;
import com.serotonin.bacnet4j.type.primitive.Primitive;
import com.serotonin.bacnet4j.type.primitive.Real;

public class PropertyWriter {
    public static WritePropertyResponse writeProperty(LocalDevice localDevice, RemoteDevice remoteDevice, 
                                                    ObjectIdentifier objectId, PropertyIdentifier property, 
                                                    Primitive value) throws Exception {
        WritePropertyRequest request = new WritePropertyRequest(objectId, property, null, value, null);
        return (WritePropertyResponse) localDevice.send(remoteDevice, request);
    }

    // 示例:修改模拟输出(AO)对象的设定值
    public static void writeAnalogOutput(LocalDevice localDevice, RemoteDevice remoteDevice, int instanceNumber, float newValue) throws Exception {
        ObjectIdentifier aoId = new ObjectIdentifier(ObjectIdentifier.ObjectType.analogOutput, instanceNumber);
        WritePropertyResponse response = writeProperty(localDevice, remoteDevice, aoId, 
                PropertyIdentifier.presentValue, new Real(newValue));
        System.out.println("写入结果: " + (response.isPositiveAcknowledgement() ? "成功" : "失败"));
    }
}

三、完整示例:读取温度并写入设定值

java 复制代码
public class BACnetDemo {
    public static void main(String[] args) {
        try {
            // 1. 初始化本地设备
            LocalDevice localDevice = BACnetInitializer.initializeLocalDevice("192.168.1.100", 47808);

            // 2. 发现远程设备
            List<RemoteDevice> remoteDevices = DeviceDiscovery.discoverDevices(localDevice);
            if (remoteDevices.isEmpty()) {
                System.out.println("未发现设备!");
                return;
            }
            RemoteDevice remoteDevice = remoteDevices.get(0); // 取第一个设备

            // 3. 读取温度传感器(AI)值
            PropertyReader.readAnalogInput(localDevice, remoteDevice, 0); // 假设实例号为0

            // 4. 写入温控器(AO)设定值(需确保有写入权限)
            PropertyWriter.writeAnalogOutput(localDevice, remoteDevice, 1, 25.0f); // 假设实例号为1,设定25℃

            // 5. 终止本地设备
            localDevice.terminate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

四、关键注意事项

  1. 跨网段通信 :BACnet/IP默认不支持跨网段,需配置**BBMD(BACnet Broadcast Management Device)**或使用VPN。
  2. 权限控制 :写入操作需设备支持且配置了正确的访问权限(如Write Access属性)。
  3. 异常处理 :捕获BACnetException处理网络超时、设备离线等问题。
  4. 性能优化 :批量读取属性时使用ReadPropertyMultipleRequest减少网络开销。

五、替代方案

  • Yabe工具:直接通过GUI查看/修改设备属性,适合快速测试。
  • 其他库 :如BACnet Stack for Java(开源实现),但功能较BACnet4J简陋。

通过上述方法,您可实现Java对BACnet设备的安全监测(只读)可控写入(需权限),满足楼宇自动化系统的多样化需求。

相关推荐
老华带你飞2 小时前
校务管理|基于springboot 校务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
利刃大大2 小时前
【JavaSE】十一、Stack && Queue && Deque && PriorityQueue && Map && Set
java·数据结构·优先级队列··哈希表·队列·集合类
油丶酸萝卜别吃2 小时前
springboot项目中与接口文档有关的注解
java·spring boot·后端
小码哥0682 小时前
家政服务管理-家政服务管理平台-家政服务管理平台源码-家政服务管理平台java代码-基于springboot的家政服务管理平台
java·开发语言·spring boot·家政服务·家政服务平台·家政服务系统·家政服务管理平台源码
Java爱好狂.2 小时前
复杂知识简单学!Springboot加载配置文件源码分析
java·spring boot·后端·spring·java面试·后端开发·java程序员
Array*2 小时前
java实现word中插入附件(支持所有文件格式)
java·开发语言·word·poi·ole
Donald_brian2 小时前
线程同步
java·开发语言·jvm
全靠bug跑2 小时前
Nacos 入门实战:部署、服务注册与发现全指南
java·spring cloud·docker·nacos
郑州光合科技余经理2 小时前
技术视角:海外版一站式同城生活服务平台源码解析
java·开发语言·uni-app·php·排序算法·objective-c·生活