第一次接触BACnet ip,开发语言使用java,网上搜了下,都是推荐使用BACnet4j,但是找不到完整的demo,折腾了一段时间,勉强跑通了自己写的demo,读取到的设备模拟器上的数据。
链接: https://pan.baidu.com/s/1OK1uq-tfU-XoOH10h4Otag 提取码: 4eu4
安装后
打开太阳的图标
这是设备模拟器,Yabe还提供了一个客户端,打开放大镜图标
可以在client端看到相关的数据信息。
https://github.com/infiniteautomation/BACnet4J
下载需要的版本,本博文的代码使用的是5.0.2版本,然后本地安装 mvn install -Dmaven.test.skip=true
创建maven项目,pom.xml引入BACnet4j(上面下载安装的),比如
com.infiniteautomation
bacnet4j
5.0.2
注意:1.Yabe和代码在同一台电脑少,跨网段的话暂时不知道该怎样解决。
2.运行代码的时候,必须先关闭Yabe的客户端(explorer),否则代码会提示地址被占用了
ReadTest01.java
package com.fei;
import java.util.Arrays;
import java.util.List;
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.RemoteDevice;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
import com.serotonin.bacnet4j.transport.DefaultTransport;
import com.serotonin.bacnet4j.type.Encodable;
import com.serotonin.bacnet4j.type.enumerated.ObjectType;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.type.primitive.UnsignedInteger;
import com.serotonin.bacnet4j.util.PropertyValues;
import com.serotonin.bacnet4j.util.ReadListener;
import com.serotonin.bacnet4j.util.RequestUtils;
/**
* 启动Yabe的天气模拟
* @author Jfei
*
*/
public class ReadTest01 {
/**
* Yabe在本地电脑上启动
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
LocalDevice d = null;
try {
//创建网络对象
IpNetwork ipNetwork = new IpNetworkBuilder()
.withLocalBindAddress("192.168.1.114")//本机的ip
.withSubnet("255.255.255.0", 24)
.withPort(47808) //Yabe默认的UDP端口
.withReuseAddress(true)
.build();
//创建虚拟的本地设备,deviceNumber随意
d = new LocalDevice(123, new DefaultTransport(ipNetwork));
d.initialize();
d.startRemoteDeviceDiscovery();
RemoteDevice rd = d.getRemoteDeviceBlocking(3);//获取远程设备,instanceNumber 是设备的device id
System.out.println("modelName=" + rd.getDeviceProperty( PropertyIdentifier.modelName));
System.out.println("analogInput2= " +RequestUtils.readProperty(d, rd, new ObjectIdentifier(ObjectType.analogInput, 2), PropertyIdentifier.presentValue, null));
List objectList = RequestUtils.getObjectList(d, rd).getValues();
//打印所有的Object 名称
for(ObjectIdentifier o : objectList){
System.out.println(o);
}
ObjectIdentifier oid = new ObjectIdentifier(ObjectType.analogInput, 0);
ObjectIdentifier oid1 = new ObjectIdentifier(ObjectType.analogInput, 1);
ObjectIdentifier oid2 = new ObjectIdentifier(ObjectType.analogInput, 2);
//获取指定的presentValue
PropertyValues pvs = RequestUtils.readOidPresentValues(d, rd,Arrays.asList(oid,oid1,oid2), new ReadListener(){
@Override
public boolean progress(double progress, int deviceId,
ObjectIdentifier oid, PropertyIdentifier pid,
UnsignedInteger pin, Encodable value) {
System.out.println("========");
System.out.println("progress=" + progress);
System.out.println("deviceId=" + deviceId);
System.out.println("oid="+oid.toString());
System.out.println("pid="+pid.toString());
System.out.println("UnsignedInteger="+pin);
System.out.println("value="+value.toString() + " getClass =" +value.getClass());
return false;
}
});
Thread.sleep(3000);
System.out.println("analogInput:0 == " + pvs.get(oid, PropertyIdentifier.presentValue));
//获取指定的presentValue
PropertyValues pvs2 = RequestUtils.readOidPresentValues(d, rd,Arrays.asList(oid,oid1,oid2),null);
System.out.println("analogInput:1 == " + pvs2.get(oid1, PropertyIdentifier.presentValue));
d.terminate();
} catch (Exception e) {
e.printStackTrace();
if(d != null){
d.terminate();
}
}
}
}
执行结果
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
modelName=Room_FC_2014
analogInput2= 12.0
device 3
analog-input 0
analog-input 1
analog-input 2
analog-value 0
analog-value 1
analog-value 2
analog-value 3
characterstring-value 1
characterstring-value 2
characterstring-value 3
binary-value 0
binary-value 1
multi-state-value 0
multi-state-value 1
========
progress=0.3333333333333333
deviceId=3
oid=analog-input 0
pid=present-value
UnsignedInteger=null
value=27.8 getClass =class com.serotonin.bacnet4j.type.primitive.Real
========
progress=0.6666666666666666
deviceId=3
oid=analog-input 1
pid=present-value
UnsignedInteger=null
value=39.7 getClass =class com.serotonin.bacnet4j.type.primitive.Real
========
progress=1.0
deviceId=3
oid=analog-input 2
pid=present-value
UnsignedInteger=null
value=12.0 getClass =class com.serotonin.bacnet4j.type.primitive.Real
analogInput:0 == 27.8
analogInput:1 == 39.5
WriteTest01.java
package com.fei;
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.RemoteDevice;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
import com.serotonin.bacnet4j.transport.DefaultTransport;
import com.serotonin.bacnet4j.type.enumerated.ObjectType;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.primitive.Boolean;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.type.primitive.Real;
import com.serotonin.bacnet4j.util.RequestUtils;
public class WriteTest01 {
public static void main(String[] args) throws Exception {
LocalDevice d = null;
try {
IpNetwork ipNetwork = new IpNetworkBuilder()
.withLocalBindAddress("192.168.1.114")
.withSubnet("255.255.255.0", 24)
.withPort(47808)
.withReuseAddress(true)
.build();
d = new LocalDevice(123, new DefaultTransport(ipNetwork));
d.initialize();
d.startRemoteDeviceDiscovery();
RemoteDevice rd = d.getRemoteDevice(3).get();//获取远程设备
//必须先修改out of service为true
RequestUtils.writeProperty(d, rd, new ObjectIdentifier(ObjectType.analogValue, 0),PropertyIdentifier.outOfService, Boolean.TRUE);
Thread.sleep(1000);
//修改属性值
RequestUtils.writePresentValue(d, rd, new ObjectIdentifier(ObjectType.analogValue, 0), new Real(77));
Thread.sleep(2000);
System.out.println("analogValue0= " +RequestUtils.readProperty(d, rd, new ObjectIdentifier(ObjectType.analogValue, 0), PropertyIdentifier.presentValue, null));
Thread.sleep(1000);
d.terminate();
} catch (Exception e) {
e.printStackTrace();
if(d != null){
d.terminate();
}
}
}
}
执行结果
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
analogValue0= 77.0
注意:修改的话,必须是设备端运行被修改的才行,否则会报异常,拒绝写。可以使用Yabe的客户端(expoler)进行测试确认哪个只能被修改.