public static final long MIN_BACKOFF = 1000L;
public static final long MAX_BACKOFF = 30 * 1000L; // 30 seconds
public static final long DEFAULT_BACKOFF = 1000L;
值得注意的是,建议在断线重连后,在建链成功回调中进行设备订阅,以免重连后订阅丢失。
public class MessageSample implements ConnectListener {
private static final IoTDevice device = new IoTDevice("tcp://XXXXX:1883", "deviceId", "secret", null);
public static void main(String[] args) throws InterruptedException, IOException {
// 默认使用不校验时间戳,若要校验则需设置对应的参数选择密钥加密算法
device.getClient().getClientConf().setCheckStamp(Constants.CHECK_STAMP_SHA256_OFF);
if (device.init() != 0) {
return;
}
@Override
public void connectionLost(Throwable cause) {
log.error("connectionLost");
}
@Override
public void connectComplete(boolean reconnect, String serverURI) {
String topic = "$oc/devices/" + device.getDeviceId() + "/user/wpy";
device.getClient().subscribeTopic(topic, new ActionListener() {
@Override
public void onSuccess(Object context) {
log.info("subscribe success topic = {}", topic);
}
@Override
public void onFailure(Object context, Throwable var2) {
log.error("subscribe failed topic = {}", topic);
}
}, 0);
}
}
simpleGateway = new SimpleGateway(new SubDevicesFilePersistence(),
"ssl://iot-acc.cn-north-4.myhuaweicloud.com:8883",
"5e06bfee334dd4f33759f5b3_demo", "mysecret");
在平台上看到该网关在线后,添加子设备。
此时网关上日志打印:
2024-04-16 21:00:01 INFO SubDevicesFilePersistence:112 - add subdev, the nodeId is subdev
运行TcpDevice类,建立连接后,输入步骤3中注册的子设备的nodeId,如subdev。
此时网关设备日志打印:
2024-04-16 21:00:54 INFO StringTcpServer:196 - initChannel: /127.0.0.1:21889
2024-04-16 21:01:00 INFO StringTcpServer:137 - channelRead0 is /127.0.0.1:21889, the msg is subdev
2024-04-16 21:01:00 INFO SimpleGateway:100 - create new session ok, the session is Session{nodeId='subdev', channel=[id: 0xf9b89f78, L:/127.0.0.1:8080 - R:/127.0.0.1:21889], deviceId='subdev_deviceId'}
在平台上看到子设备上线。
子设备上报消息
在子设备控制台TcpDevice输入上报的消息”hello”
查看日志看到上报成功
2024-04-16 21:02:36 INFO StringTcpServer:137 - channelRead0 is /127.0.0.1:21889, the msg is hello
2024-04-16 21:02:36 INFO MqttConnection:299 - publish message topic is $oc/devices/5e06bfee334dd4f33759f5b3_demo/sys/messages/up, msg = {"name":null,"id":null,"content":"hello","object_device_id":"subdev_deviceId"]
2024-04-16 21:02:36 INFO MqttConnection:299 - publish message topic is $oc/devices/5e06bfee334dd4f33759f5b3_demo/sys/gateway/sub_devices/properties/report, msg = {"devices":[{"services":[{"properties":{"temprature":2,"alarm":1},"service_id":"parameter","event_time":null}],"device_id":"subdev_deviceId"}]]
public int getHumidity() {
//模拟从传感器读取数据
humidity = new Random().nextInt(100);
return humidity;
}
public void setHumidity(int humidity) {
//humidity是只读的,不需要实现
}
public float getTemperature() {
//模拟从传感器读取数据
temperature = new Random().nextInt(100);
return temperature;
}
public void setTemperature(float temperature) {
//只读字段不需要实现set接口
}
public float getConcentration() {
//模拟从传感器读取数据
concentration = new Random().nextFloat()*100.0f;
return concentration;
}
public void setConcentration(float concentration) {
//只读字段不需要实现set接口
}
public int getSmokeAlarm() {
return smokeAlarm;
}
public void setSmokeAlarm(int smokeAlarm) {
this.smokeAlarm = smokeAlarm;
if (smokeAlarm == 0){
log.info("alarm is cleared by app");
}
}
定义服务的命令:
命令的入参和返回值类型固定不能修改。
@DeviceCommand(name = "ringAlarm")
public CommandRsp alarm(Map<String, Object> paras) {
int duration = (int) paras.get("duration");
log.info("ringAlarm duration = " + duration);
return new CommandRsp(0);
}
上面完成了服务的定义
接下来创建设备,注册烟感服务,然后初始化设备:
//创建设备
// 用户请替换为自己的接入地址。
IoTDevice device = new IoTDevice("ssl://xxx.st1.iotda-device.cn-north-4.myhuaweicloud.com:8883", "5e06bfee334dd4f33759f5b3_demo", "mysecret", file);
//创建设备服务
SmokeDetectorService smokeDetectorService = new SmokeDetectorService();
device.addService("smokeDetector", smokeDetectorService);
if (device.init() != 0) {
return;
}
English | 简体中文
huaweicloud-iot-device-sdk-java
huaweicloud-iot-device-sdk-java提供设备接入华为云IoT物联网平台的Java版本的SDK,提供设备和平台之间通讯能力,以及设备服务、网关服务、OTA等高级服务,并且针对各种场景提供了丰富的demo代码。IoT设备开发者使用SDK可以大大简化开发复杂度,快速的接入平台。
0.版本更新说明
2、更新Samples中的ca.jks为包含平台各区域实例设备侧证书的所有权威根CA证书的证书文件;
3、修复部分拼写错误;
4、paho升级;
5、修复退避重连长时间后不再重试问题
2、网关刷新子设备状态
3、修改默认订阅topic的qos、修改重连新链路挤老链路、修改重连时间
如果设备使用老域名(iot-acc.cn-north-4.myhuaweicloud.com)接入,请使用 v0.6.0及以下版本的SDK
1.前言
huaweicloud-iot-device-sdk-java提供设备接入华为云IoT物联网平台的Java版本的SDK,提供设备和平台之间通讯能力,以及设备服务、网关服务、OTA等高级服务,并且针对各种场景提供了丰富的demo代码。IoT设备开发者使用SDK可以大大简化开发复杂度,快速的接入平台。
2.SDK简介
2.1 功能支持
SDK面向运算、存储能力较强的嵌入式终端设备,开发者通过调用SDK接口,便可实现设备与物联网平台的上下行通讯。SDK当前支持的功能有:
相比直接调用客户端接口和平台进行通讯,面向物模型编程简化了设备侧代码的复杂度,让设备代码只需要关注业务,而不用关注和平台的通讯过程。
3.SDK功能
依赖的版本:
3.0 设备初始化
创建设备并初始化,当前已支持国密通信,启用国密前请参考[BGMProvider安装指南](https://gitee.com/openeuler/bgmprovider/wikis/%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3/BGMProvider%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97)进行配置。首选读取证书,如果是pem格式的证书:
如果是keystore格式证书:
如果是国密场景下的设备接入,需要导入双证书:
然后使用证书创建设备
完整代码参见X509CertificateDeviceSample.java
3.1 自定义选项
设备初始化前,可以通过CustomOptions类配置自定义断线重连、离线最大缓存消息数量、正在传输但还未收到确认的消息数量等功能。3.2 断线重连
在SDK中内置了一个断线重连,若需要自定义断线重连,可以重写SDK:com.huaweicloud.sdk.iot.device.client.handler.CustomBackoffHandler中backoffHandler方法。自定义断线重连可见demo:src/main/java/com/huaweicloud/sdk/iot/device/demo/device/connect/ReConnect.java。默认断线重连为每隔一段时间进行一次重连。主要参数如下,可以通过修改最大、最小重连间隔时间实现重连控制。
值得注意的是,建议在断线重连后,在建链成功回调中进行设备订阅,以免重连后订阅丢失。
3.3 消息上报、下发
示例代码可见:MessageSample.java。 自定义topic示例可见:CustomizeTopicSample.java。上报设备消息
上报自定义topic消息(非$oc开头,可用设备topic策略控制权限)
上报自定义topic消息($oc开头,注意需要先在平台配置自定义topic)
设备收到平台下发的消息
订阅自定义topic, 系统topic由SDK自动订阅,此接口只能用于订阅自定义topic
3.4 属性上报、设置、查询
示例代码可见:PropertySample.java。设备属性上报
平台设置设备属性和查询设备属性
3.5 命令下发
示例代码可见SDK:CommandSample.java。3.6 获取设备影子
示例代码可见SDK:ShadowSample.java。3.7 软固件(OTA)升级
示例代码可见SDK: OTASample.java和OTAV2Sample.java3.8 时间同步
示例代码可见SDK:NtpSample.java3.9 网关与子设备
此功能参考[网关与子设备](https://support.huaweicloud.com/usermanual-iothub/iot_01_0052.html)。网关与子设备管理的demo代码在/iot-gateway-demo下。此demo演示如何使用网关来实现TCP协议设备接入。 网关和平台只建立一个MQTT连接,使用网关的身份和平台进行通讯。
此demo有两个可运行的.java文件, 分别是/iot-gateway-demo/StringTcpServer.java和/iot-gateway-demo/TcpDevice.java, 分别是网关和tcp设备的代码。
此demo可以演示:
3.9.1 iot-gateway-demo的使用
创建子设备的产品,步骤可参考创建产品。
在创建的产品中定义模型,添加服务,服务ID为parameter。并且新增alarm和temperature两个属性,如下图所示
修改StringTcpServer的main函数,替换构造参数,然后运行该类。
在平台上看到该网关在线后,添加子设备。
此时网关上日志打印:
运行TcpDevice类,建立连接后,输入步骤3中注册的子设备的nodeId,如subdev。
此时网关设备日志打印:
在平台上看到子设备上线。
子设备上报消息
在子设备控制台TcpDevice输入上报的消息”hello”
查看日志看到上报成功
查看消息跟踪
在平台上找到网关,选择 设备详情-消息跟踪,打开消息跟踪。继续让子设备发送数据,等待片刻后看到消息跟踪:
网关删除子设备
在网关控制台输入delete 设备ID,将删除网关的子设备

在平台上看网关子设备已经被删除

网关添加子设备
在网关控制台输入add 产品ID nodeId,将增加网关子设备

在平台看到网关已经增加了子设备

3.9.2 接口说明
示例代码可见SDK:AbstractGateway.java和SimpleGateway.java
3.10 文件上传、下载
示例代码可见SDK:FileManagerSample.java3.10 端侧引擎
平台创建端侧规则,设备可以通过client.setCommandListener响应命令,也可以自定义处理器处理规则动作。示例代码可见SDK:DeviceRuleSample.java和CustomDeviceRuleSample.java。
3.12 设备发放
设备发放功能,可以将设备发放到不同的region,参考文档:[设备发放示例](https://support.huaweicloud.com/qs-iotps/iot_03_0006.html)。注意:流程可参考“快速入门”中的各种接入示例,SDK已自动实现示例中的“引导设备”。详细的步骤可参考链接中的“用户指南”。设备发放主要分为两种发放方式,分别为手动注册发放与注册组发放。相关代码示例可见SDK:BootstrapSelfRegGroupPasswordSample.java和BootstrapSelfRegSample.java3.13 面向物模型编程
面向物模型编程指的是,基于SDK提供的物模型抽象能力,设备代码只需要按照物模型定义设备服务,SDK就能自动的和平台通讯,完成属性的同步和命令的调用。 相比直接调用客户端接口和平台进行通讯,面向物模型编程简化了设备侧代码的复杂度,让设备代码只需要关注业务,而不用关注和平台的通讯过程。首先定义一个烟感服务类,继承自AbstractService。
定义服务属性,属性和产品模型保持一致。writeable用来标识属性是否可写
定义属性的读写接口: getter接口为读接口,在属性上报和平台主动查属性时被sdk调用 setter接口为写接口,在平台修改属性时被sdk调用,如果属性是只读的,则setter接口保留空实现。
定义服务的命令: 命令的入参和返回值类型固定不能修改。
上面完成了服务的定义 接下来创建设备,注册烟感服务,然后初始化设备:
启动服务属性自动周期上报
使用设备代码生成器
上面基于物模型编程中,要求服务的定义必须和产品模型保持一致,基于这一点,我们提供了代码生成器,能根据产品模型自动生成设备代码。代码生成器的源码在iot-device-code-generator目录,详情可见:代码自动生成说明。
3.14 泛协议开发
目前平台支持基于MQTT/HTTP/LwM2M等标准协议接入,为解决用户自定义协议设备快速接入IoT平台的诉求。华为云IoT提供泛协议适配机制,您可使用泛协议对接SDK,快速构建协议插件,进行设备或平台与IoT的双向数据通信。SDK介绍
基于SDK实现泛协议设备接入的业务流程:
监听平台下行数据的接口说明
相关类说明
使用 Bridge Demo
Brdige Demo提供了一个使用TCP设备接入网桥、于云平台进行交互的例子。下面将介绍Demo中各个部分的功能,帮您熟悉网桥开发要点。Demo项目结构图如下:
相关类如下:
1. 初始化网桥SDK
创建BridgeBootstrap对象实例,调用InitBridge方法,在该方法中会读取环境变量的配置信息,并同IoT平台建立网桥连接。
环境变量说明 | 环境变量名称 | 参数说明 | 样例 | | :—- | :—- | :—- | | NET_BRIDGE_ID | 网桥ID | bridge001 | | NET_NET_BRIDGE_SECRET | 网桥秘钥 | ******** | | NET_NET_BRIDGE_SERVER_IP | IoTDA平台地址 | *****.st1.iotda-device.cn-north-4.myhuaweicloud.com | | NET_NET_BRIDGE_SERVER_PORT | IoTDA平台泛协议接入端口号 | 8883 |
初始化成功后,需要设置平台下行数据的监听器,监听平台的下行数据。
代码样例:
2. 设备登录上线
设备登录上线的实现样例如下:
设备上线时,需要从原始设备消息中解析出鉴权信息(设备ID和秘钥),再调用SDK提供的login接口向平台发起登录请求,平台收到设备的login请求后,会对设备的鉴权信息进行认证,认证通过后会通过返回码告知网桥SDK设备的登录结果。您需要根据登录结果对设备进行记录会话信息、给设备返回响应等处理。
3. 设备数据上报
设备登录成功后,收到设备的上行数据时,可调用SDK的reportProperties将解码后的数据上报到IoT平台。
代码样例参考:
4. 平台指令下发
网桥在初始化时向SDK注册了BridgeCommandListener的监听。当有下行指令时,网桥SDK就会回调BridgeCommandListener的OnCommand方法。您可在OnCommand中对平台的下行指令进行处理。
代码样例参考:
5. 设备离线
网桥检查到设备到服务端的长连接断开时,需要调用SDK的logout接口通知平台设备离线。
代码样例参考:
测试验证
1. 获取网桥接入信息
代码调试时,需要获取对应的网桥接入信息,并配置到对应的环境变量中。网桥接入信息,环境变量配置参考:
2. 功能验证
均可参考https://support.huaweicloud.com/usermanual-iothub/iot_02_3.html 实现
启动TCP:打开开文件
iot-bridge-demo\src\main\java\com\huaweicloud\sdk\iot\device\demo\TcpDevice.java,将42行修改为:启动工程模拟设备同网桥建立TCP连接,并发送登录请求。
3.15 日志框架修改
从1.2.2版本开始,在iot-device-sdk-java默认使用SLF4J门面 + 动态绑定,当客户使用且无具体配置时,采用slf4j-simple的日志框架打印日志。 若是需要对日志框架进行修改,可以通过排除slf4j-simple,引入您需要的日志框架。排除slf4j-simple:
若要使用log4j日志框架,可在.pom文件中添加如下Mvn引用,并在resources文件夹中新增格式文件log4j2.xml。
若要使用logback日志框架,可在.pom文件中添加如下Mvn引用,并在resources文件夹中新增格式文件logback.xml。
4. 常见问题
建链返回:
2025-07-02 11:44:31 INFO MqttConnection:291 - connect failed, the reason is 错误的用户名或密码 (4)。排查方法:
查看deviceId是否错误:在控制台界面查看设备,在界面中复制
设备ID,即为SDK中deviceId的值。确认密码是否正确:在设备创建时用户填入的
密钥即为SDK中deviceSecret的值。若是忘记密码,可在设备详情页面重置密钥。5. License
SDK的开源License类型为 BSD 3-Clause License。详情参见LICENSE.txt
6. 如何贡献代码
1、创建github账号 2、fork huaweicloud-iot-device-sdk-java源代码 3、同步huaweicloud-iot-device-sdk-java主仓库代码到fork的仓库 4、在本地修改代码并push到fork的仓库 5、在fork的仓库提交pull request到主仓库