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设备的安全监测(只读)可控写入(需权限),满足楼宇自动化系统的多样化需求。

相关推荐
廋到被风吹走15 小时前
【Spring】AOP深度解析:代理机制、拦截器链与事务失效全解
java·spring·缓存
没有天赋那就反复15 小时前
JAVA length
java·开发语言·算法
步步为营DotNet16 小时前
深度探索.NET 中ValueTask:优化异步性能的轻量级利器
java·spring·.net
栈与堆16 小时前
LeetCode-88-合并两个有序数组
java·开发语言·数据结构·python·算法·leetcode·rust
董世昌4116 小时前
添加、删除、替换、插入元素的全方法指南
java·开发语言·前端
小当家.10516 小时前
JVM八股详解(上部):核心原理与内存管理
java·jvm·学习·面试
heartbeat..16 小时前
Spring 声明式事务:原理、使用及失效场景详解
java·spring·面试·事务
寻星探路16 小时前
【Python 全栈测开之路】Python 基础语法精讲(三):函数、容器类型与文件处理
java·开发语言·c++·人工智能·python·ai·c#
xiaolyuh12316 小时前
【XXL-JOB】执行器 Netty服务 & Tomcat 进程+资源共用详解
java·tomcat
jasnet_u16 小时前
SpringCloudAlibaba的web微服务快速搭建
java·springboot·springlcoud