设备连接物联网平台后,数据直接上报至物联网平台。平台上的数据可以通过AMQP通道流转至您的服务器。这一步中,我们将配置AMQP服务端订阅功能。您的服务器可以通过接入AMQP客户端,接收设备数据。
配置AMQP服务端订阅
- 登录物联网平台控制台。
- 在实例概览页,找到对应的企业版实例,单击实例进入实例详情页。
- 在左侧导航栏,选择规则引擎 > 服务端订阅。
- 在服务端订阅页,单击创建订阅。
- 在创建订阅对话框中,完成配置,单击确认。
参数 说明 产品 选择冷链运输追踪器。 订阅类型 选择为AMQP。 消费组 单击选择目标消费组对话框右下角的创建消费组,新建消费组(例如:冷链运输追踪器上报数据)。消费组相关说明,请参见管理消费组。 推送消息类型 服务端要订阅的消息类型。目前,服务端可订阅的设备消息类型包括: - 设备上报消息:产品下所有设备Topic列表中,操作权限为发布的Topic中的消息。
设备上报消息,包括设备上报的自定义数据和物模型数据(属性上报、事件上报、属性设置响应和服务调用响应)。推送到服务端的物模型数据是经物联网平台系统处理过后的数据,数据格式请参见数据格式。
例如,一个产品有3个Topic类,分别是:/${YourProductKey}/${YourDeviceName}/user/get
,具有订阅权限。/${YourProductKey}/${YourDeviceName}/user/update
,具有发布权限。/${YourProductKey}/${YourDeviceName}/thing/event/property/post
,具有发布权限。
那么,服务端订阅会推送具有发布权限的Topic类中的消息,即
/${YourProductKey}/${YourDeviceName}/user/update
和/${YourProductKey}/${YourDeviceName}/thing/event/property/post
中的消息。 - 设备状态变化通知:该产品下的设备上下线状态变化时通知的消息。
- 网关子设备发现上报:网关将发现的子设备信息上报给物联网平台。需要网关上的应用程序支持。网关产品特有消息类型。
- 设备拓扑关系变更:子设备和网关之间的拓扑关系建立和解除消息。网关产品特有消息类型。
- 设备生命周期变更:设备创建、删除、禁用、启用等消息。
- 物模型历史数据上报:设备上报的属性和事件历史数据。
- OTA升级状态通知:验证升级包和批量升级时,设备升级成功或失败的事件通知。
- 设备标签变更:设备上报的标签变更消息。
- OTA模块版本号上报:设备上报的OTA模块版本号变更消息。
- OTA升级批次状态通知:设备OTA升级批次状态变化通知。
- 设备上报消息:产品下所有设备Topic列表中,操作权限为发布的Topic中的消息。
Java SDK接入示例
- 打开IntelliJ IDEA,创建一个Maven工程。例如Amqp。
- 在工程中的pom.xml文件中,添加Maven依赖,然后单击Load Maven Changes图标,完成依赖包下载。
<!-- amqp 1.0 qpid client --> <dependency> <groupId>org.apache.qpid</groupId> <artifactId>qpid-jms-client</artifactId> <version>0.47.0</version> </dependency> <!-- util for base64--> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency>
- 在路径Amqp\src\main\java下,创建Java类(例如AmqpJavaClientDemo),将AmqpJavaClientDemo.java文件内容替换为以下代码。
以下代码示例中涉及的参数说明,请参见AMQP客户端接入说明。
import java.net.URI; import java.util.Hashtable; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Session; import javax.naming.Context; import javax.naming.InitialContext; import org.apache.commons.codec.binary.Base64; import org.apache.qpid.jms.JmsConnection; import org.apache.qpid.jms.JmsConnectionListener; import org.apache.qpid.jms.message.JmsInboundMessageDispatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AmqpJavaClientDemo { private final static Logger logger = LoggerFactory.getLogger(AmqpJavaClientDemo.class); //业务处理异步线程池,线程池参数可以根据您的业务特点调整,或者您也可以用其他异步方式处理接收到的消息。 private final static ExecutorService executorService = new ThreadPoolExecutor( Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50000)); public static void main(String[] args) throws Exception { //参数说明,请参见AMQP客户端接入说明文档。 String accessKey = "${YourAccessKey}"; String accessSecret = "${YourAccessSecret}"; String consumerGroupId = "${YourConsumerGroupId}"; //iotInstanceId:企业版实例请填写实例ID,公共实例请填空字符串""。 String iotInstanceId = "${YourIotInstanceId}"; long timeStamp = System.currentTimeMillis(); //签名方法:支持hmacmd5、hmacsha1和hmacsha256。 String signMethod = "hmacsha1"; //控制台服务端订阅中消费组状态页客户端ID一栏将显示clientId参数。 //建议使用机器UUID、MAC地址、IP等唯一标识等作为clientId。便于您区分识别不同的客户端。 String clientId = "${YourClientId}"; //userName组装方法,请参见AMQP客户端接入说明文档。 String userName = clientId + "|authMode=aksign" + ",signMethod=" + signMethod + ",timestamp=" + timeStamp + ",authId=" + accessKey + ",iotInstanceId=" + iotInstanceId + ",consumerGroupId=" + consumerGroupId + "|"; //计算签名,password组装方法,请参见AMQP客户端接入说明文档。 String signContent = "authId=" + accessKey + "×tamp=" + timeStamp; String password = doSign(signContent,accessSecret, signMethod); //接入域名,请参见AMQP客户端接入说明文档。 String connectionUrl = "failover:(amqps://${YourHost}:5671?amqp.idleTimeout=80000)" + "?failover.reconnectDelay=30"; Hashtable<String, String> hashtable = new Hashtable<>(); hashtable.put("connectionfactory.SBCF",connectionUrl); hashtable.put("queue.QUEUE", "default"); hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory"); Context context = new InitialContext(hashtable); ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF"); Destination queue = (Destination)context.lookup("QUEUE"); // 创建连接。 Connection connection = cf.createConnection(userName, password); ((JmsConnection) connection).addConnectionListener(myJmsConnectionListener); // 创建会话。 // Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()。 // Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)。 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); connection.start(); // 创建Receiver连接。 MessageConsumer consumer = session.createConsumer(queue); consumer.setMessageListener(messageListener); } private static MessageListener messageListener = new MessageListener() { @Override public void onMessage(Message message) { try { //1.收到消息之后一定要ACK。 // 推荐做法:创建Session选择Session.AUTO_ACKNOWLEDGE,这里会自动ACK。 // 其他做法:创建Session选择Session.CLIENT_ACKNOWLEDGE,这里一定要调message.acknowledge()来ACK。 // message.acknowledge(); //2.建议异步处理收到的消息,确保onMessage函数里没有耗时逻辑。 // 如果业务处理耗时过程过长阻塞住线程,可能会影响SDK收到消息后的正常回调。 executorService.submit(() -> processMessage(message)); } catch (Exception e) { logger.error("submit task occurs exception ", e); } } }; /** * 在这里处理您收到消息后的具体业务逻辑。 */ private static void processMessage(Message message) { try { byte[] body = message.getBody(byte[].class); String content = new String(body); String topic = message.getStringProperty("topic"); String messageId = message.getStringProperty("messageId"); String tag = message.getStringProperty("tag"); logger.info("receive message" + ",\n topic = " + topic + ",\n messageId = " + messageId + ",\n tag = " + tag + ",\n content = " + content) +"\n"); System.out.println(); //如果创建Session选择的是Session.CLIENT_ACKNOWLEDGE,这里需要手动ACK。 message.acknowledge(); //如果要对收到的消息做耗时的处理,请异步处理,确保这里不要有耗时逻辑。 } catch (Exception e) { logger.error("processMessage occurs error ", e); } } private static JmsConnectionListener myJmsConnectionListener = new JmsConnectionListener() { /** * 连接成功建立。 */ @Override public void onConnectionEstablished(URI remoteURI) { logger.info("onConnectionEstablished, remoteUri:{}", remoteURI); } /** * 尝试过最大重试次数之后,最终连接失败。 */ @Override public void onConnectionFailure(Throwable error) { logger.error("onConnectionFailure, {}", error.getMessage()); } /** * 连接中断。 */ @Override public void onConnectionInterrupted(URI remoteURI) { logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI); } /** * 连接中断后又自动重连上。 */ @Override public void onConnectionRestored(URI remoteURI) { logger.info("onConnectionRestored, remoteUri:{}", remoteURI); } @Override public void onInboundMessage(JmsInboundMessageDispatch envelope) {} @Override public void onSessionClosed(Session session, Throwable cause) {} @Override public void onConsumerClosed(MessageConsumer consumer, Throwable cause) {} @Override public void onProducerClosed(MessageProducer producer, Throwable cause) {} }; /** * 计算签名,password组装方法,请参见AMQP客户端接入说明文档。 */ private static String doSign(String toSignString, String secret, String signMethod) throws Exception { SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod); Mac mac = Mac.getInstance(signMethod); mac.init(signingKey); byte[] rawHmac = mac.doFinal(toSignString.getBytes()); return Base64.encodeBase64String(rawHmac); } }
- 运行AmqpJavaClientDemo.java文件,执行结果如下图。
- 代码运行成功后,您可以在服务端订阅中,查看消费组状态的基本信息。
具体操作,请参见管理消费组。
查看日志
所有配置完成后,登录物联网平台控制台,在企业实例下的监控运维 > 日志服务中,从产品列表选择冷链运输追踪器,可在云端运行日志页签下,查看完整的日志信息。

序号 | 描述 |
---|---|
① | 设备上报数据到阿里云。 |
② | 数据转发到AMQP服务端订阅消费组。 |
③ | 上报到平台上的数据通过AMQP通道流转至您的服务器。 |
在文档使用中是否遇到以下问题
更多建议
匿名提交