使用 IoT 中心发送云到设备的消息 (Java)
Azure IoT 中心是一项完全托管的服务,有助于在数百万台设备和单个解决方案后端之间实现安全可靠的双向通信。
本文介绍如何:
通过 IoT 中心,将云到设备的消息从解决方案后端发送到单个设备
在设备上接收云到设备的消息
从解决方案后端,请求送达确认,确认收到从 IoT 中心发送到设备的消息(反馈)
注意
本文所述的功能只能用于 IoT 中心的标准层。 有关 IoT 中心基本层和标准/免费层的详细信息,请参阅选择适合你的解决方案的 IoT 中心层。
在本文结束时,会运行两个 Java 控制台应用:
SimulatedDevice:从设备将遥测数据发送到 IoT 中心中创建的应用的修改版本,它连接到 IoT 中心并接收云到设备的消息。
SendCloudToDevice:它通过 IoT 中心将云到设备消息发送到设备应用,然后接收其送达确认。
若要详细了解云到设备的消息,请参阅从 IoT 中心发送云到设备的消息。
先决条件
将遥测数据从设备发送到 IoT 中心快速入门或使用 IoT 中心配置消息路由一文的完整工作版本。 这篇云到设备文章以快速入门为基本。
Java SE 开发工具包 8。 请确保在“长期支持”下选择“Java 8”以获取 JDK 8 的下载。
确保已在防火墙中打开端口 8883。 本文中的设备示例使用 MQTT 协议,该协议通过端口 8883 进行通信。 在某些公司和教育网络环境中,此端口可能被阻止。 有关解决此问题的更多信息和方法,请参阅连接到 IoT 中心(MQTT)。
在模拟设备应用上接收消息
在本部分,修改设备应用,使其从 IoT 中心接收云到设备消息。
使用文本编辑器打开 simulated-device\src\main\java\com\mycompany\app\App.java 文件。
在 App 类中添加以下 MessageCallback 类作为嵌套类。 设备从 IoT 中心接收消息时,将调用 execute 方法。 在本示例中,设备始终通知 IoT 中心它已完成消息:
private static class AppMessageCallback implements MessageCallback { public IotHubMessageResult execute(Message msg, Object context) { System.out.println("Received message from hub: " + new String(msg.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET)); return IotHubMessageResult.COMPLETE; } }
修改 main 方法,以创建 AppMessageCallback 实例,并在打开客户端之前调用 setMessageCallback 方法,如下所示:
client = new DeviceClient(connString, protocol); MessageCallback callback = new AppMessageCallback(); client.setMessageCallback(callback, null); client.open();
若要使用 Maven 生成 simulated-device 应用,请在 simulated-device 文件夹中的命令提示符下执行以下命令:
mvn clean package -DskipTests
AppMessageCallback
类中的 execute
方法会返回 IotHubMessageResult.COMPLETE
。 这会通知 IoT 中心,指出已成功处理消息,可以安全地从设备队列中删除该消息了。 无论使用何种协议,设备都会在处理成功完成后返回此值。
使用 AMQP 和 HTTPS,但不使用 MQTT,该设备还可以:
- 放弃消息,使 IoT 中心将消息保留在设备队列中供将来使用。
- 拒绝消息,这会永久地从设备队列中删除该消息。
如果发生阻止设备完成、放弃或拒绝消息的情况,IoT 中心会在固定的超时期限过后再次对消息排队以进行传递。 因此,设备应用中的消息处理逻辑必须是幂等的,这样,多次接收相同的消息才会生成相同的结果。
若要获取有关云到设备消息生命周期以及 IoT 中心如何处理云到设备消息的详细信息,请参阅从 IoT 中心发送云到设备的消息。
注意
如果使用 HTTPS(而不使用 MQTT 或 AMQP)作为传输,则 DeviceClient 实例不会频繁检查 IoT 中心发来的消息(频率最低为每 25 分钟一次)。 有关 MQTT、AMQP 和 HTTPS 支持之间的差异的详细信息,请参阅云到设备通信指南和选择通信协议。
获取 IoT 中心连接字符串
本文中,你将创建一个后端服务,用于通过 IoT 中心发送云到设备消息。 若要发送云到设备消息,服务需要服务连接权限。 默认情况下,每个 IoT 中心都使用名为“服务”的共享访问策略创建,该策略会授予此权限。
若要获取 service策略的 IoT 中心连接字符串,请执行以下步骤:
在 Azure 门户中,选择“资源组”。 选择中心所在的资源组,然后从资源列表中选择中心。
在 IoT 中心的左侧窗格上,选择“共享访问策略”。
在策略列表中,选择“service”策略。
复制“主连接字符串”并保存该值。
有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限。
发送云到设备的消息
在本部分中,会创建 Java 控制台应用,用于向模拟设备应用发送“云到设备”消息。 需要设备的设备 ID 和 IoT 中心连接字符串。
在命令提示符处使用以下命令,创建名为 send-c2d-messages 的 Maven 项目。 请注意,此命令是一条很长的命令:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=send-c2d-messages -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
在命令提示符下,导航到新的 send-c2d-messages 文件夹。
使用文本编辑器,打开 send-c2d-messages 文件夹中的 pom.xml 文件,并在 dependencies 节点中添加以下依赖项。 这样即可使用应用程序中的 iothub-java-service-client 包来与 IoT 中心服务通信:
<dependency> <groupId>com.microsoft.azure.sdk.iot</groupId> <artifactId>iot-service-client</artifactId> <version>1.7.23</version> </dependency>
注意
可以使用 Maven 搜索检查是否有最新版本的 iot-service-client。
保存并关闭 pom.xml 文件。
使用文本编辑器打开 send-c2d-messages\src\main\java\com\mycompany\app\App.java 文件。
在该文件中添加以下 import 语句:
import com.microsoft.azure.sdk.iot.service.*; import java.io.IOException; import java.net.URISyntaxException;
将以下类级变量添加到 App 类,并将 {yourhubconnectionstring} 和 {yourdeviceid} 替换为前面记下的值 :
private static final String connectionString = "{yourhubconnectionstring}"; private static final String deviceId = "{yourdeviceid}"; private static final IotHubServiceClientProtocol protocol = IotHubServiceClientProtocol.AMQPS;
将 main方法替换为以下代码。 此代码用于连接到 IoT 中心,将消息发送到设备,然后等待设备已接收并处理消息的通知:
public static void main(String[] args) throws IOException, URISyntaxException, Exception { ServiceClient serviceClient = ServiceClient.createFromConnectionString( connectionString, protocol); if (serviceClient != null) { serviceClient.open(); FeedbackReceiver feedbackReceiver = serviceClient .getFeedbackReceiver(); if (feedbackReceiver != null) feedbackReceiver.open(); Message messageToSend = new Message("Cloud to device message."); messageToSend.setDeliveryAcknowledgement(DeliveryAcknowledgement.Full); serviceClient.send(deviceId, messageToSend); System.out.println("Message sent to device"); FeedbackBatch feedbackBatch = feedbackReceiver.receive(10000); if (feedbackBatch != null) { System.out.println("Message feedback received, feedback time: " + feedbackBatch.getEnqueuedTimeUtc().toString()); } if (feedbackReceiver != null) feedbackReceiver.close(); serviceClient.close(); } }
注意
为简单起见,本文不实现重试策略。 在生产代码中,应该按暂时性故障处理一文中所述实施重试策略(例如指数退避)。
若要使用 Maven 生成 simulated-device 应用,请在 simulated-device 文件夹中的命令提示符下执行以下命令:
mvn clean package -DskipTests
运行应用程序
现在,已准备就绪,可以运行应用程序了。
在 simulated-device 文件夹的命令提示符处,运行以下命令以发送遥测数据至 IoT 中心并侦听中心发出的云到设备消息:
mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
在 send-c2d-messages 文件夹的命令提示符处,运行以下命令以发送云到设备的消息并等待反馈确认:
mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
后续步骤
本文已介绍了如何发送和接收云到设备消息。
若要详细了解云到设备的消息,请参阅从 IoT 中心发送云到设备的消息。
若要详细了解 IoT 中心消息格式,请参阅创建和读取 IoT 中心消息。