物联网架构成长之路(61)-物联网第三方应用命令下发方案

0.前言

  

  上一篇博客讲的这个图,说到,设备主动上报数据到应用服务器端,只说到基于MQ来实现,只讲到安装篇,至于代码篇,等后面实际用到再继续深入了解。本篇博客主要讲,客户端(手机或者PC端)命令下发到设备,然后设备应答,返回结果到客户端。常用于扫码支付类应用。这该是如何设计呢?以前有说到,把手机或者PC客户端当作一个设备,同样接入MQTT Broker,这样,设备和客户端,同时订阅和发布相同Topic,就可以两者之间进行通信。这种方式实现比较简单。效率高。适用范围比较单一。一般也就用于自家设备与自家手机应用客户端。适合公司做自己项目的公司。因为这种方式,平台端还需要管理终端用户,这对于互联网公司来说,一般是不太乐意接受的。

  下面讲到的这种异步调用与同步调用,比较适合一些硬件厂商,或者一些想做大平台的公司。就是提供API给第三方客户接入。完全分离设备端厂商与应用端厂商,两者只需要按照流程接入即可,不用管Topic的事情。这样做的好处是,可以做成一个类似小米一样的生态系统。定好协议,左边是给设备厂商接入,右边是给第三方公司,特别是互联网公司接入。平台只做好设备认证和客户应用接入。客户的终端客户我们平台端就不需要管了。专心做好平台,做好生态即可。

  应用场景:

  假如我是一个卖设备模块的公司,假如这个模块就一个开关功能。现在定义好模块的通信协议。开放给硬件产品公司模块,就一个功能,开跟关。至于硬件产品公司,把开关应用到消防安防的开关,还是闸门、门禁的开关,还是智能插座的开关等等开关类应用。然后这批模块,按照不同的产品公司,在物联网平台创建好模型,创建好产品。完成设备接入。

  下一步,就是开放API给第三方软件公司。软件公司,只需要与平台对接,通过产品key,设备sn,命令参数,就可以下发命令到设备。第三方软件公司,开发自己的APP应用。接收命令后通过RPC调用物联网平台,平台下发命令,设备应答,平台返回命令下发结果。完成整个调用。(以上应用场景,均可用于共享仪器,扫码支付等场景)

 

1. 异步调用

  

2. 同步调用

  

  注:本时序图,最后为什么会有轮询呢?因为在一个同步调用过程中,会设置超时,如果超时时间内,设备还无法回复。那么就返回超时并返回请求的Msgid给应用服务器。应用服务根据MsgID再去定时轮询。(也有可能是硬件故障无法回复)。

  当然上面的应用服务器与客户端之间,除了Http请求外,可以采用其他的请求方式。

 

3. 同步调用参考代码

  同步调用,是基于Java Servlet 3.x 提供的DeferredResult实现的。

  MessageQueueDeferredService.java

 1 package com.wunaozai.demo.deferred;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 import org.springframework.stereotype.Service;
 7 import org.springframework.web.context.request.async.DeferredResult;
 8 
 9 @Service
10 public class MessageQueueDeferredService {
11 
12     /**
13      * 内存级别消息队列
14      */
15     private final Map<String, DeferredResult<String>> results =
16             new HashMap<String, DeferredResult<String>>();
17     
18     /**
19      * 设置应答
20      * @param key
21      * @param value
22      * @return
23      */
24     public boolean setResponse(String key, String value) {
25         if(results.containsKey(key)) {
26             DeferredResult<String> res = results.get(key);
27             res.setResult(value);
28             results.remove(key);
29             return true;
30         }
31         //可能超时或者不存在对应key
32         return false;
33     }
34     /**
35      * 设置请求
36      * @param key
37      * @param result
38      * @return
39      */
40     public DeferredResult<String> setRequest(String key) {
41         DeferredResult<String> result = new DeferredResult<String>(5000L, "not response");
42         results.put(key, result);
43         result.onTimeout(new Runnable() {
44             @Override
45             public void run() {
46                 results.remove(key, result);
47             }
48         });
49         result.onCompletion(new Runnable() {
50             @Override
51             public void run() {
52                 results.remove(key, result);
53             }
54         });
55         return result;
56     }
57 
58 }

  DeferredResultController.java

 1 package com.wunaozai.demo.deferred;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.web.bind.annotation.GetMapping;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.RestController;
 7 import org.springframework.web.context.request.async.DeferredResult;
 8 
 9 @RestController
10 @RequestMapping(value="/deferredresult/")
11 public class DeferredResultController {
12 
13     @Autowired
14     private MessageQueueDeferredService messagequeuedeferredService;
15     
16     @GetMapping(value="/request")
17     public DeferredResult<String> setRequest(String msgid){
18         DeferredResult<String> result = messagequeuedeferredService.setRequest(msgid);
19         return result;
20     }
21     @GetMapping(value="/response")
22     public boolean setResponse(String msgid, String value) {
23         boolean flag = messagequeuedeferredService.setResponse(msgid, value);
24         return flag;
25     }
26 
27 }

  运行结果

  

  前三次请求,由于没有调用response方法,所以等到5秒超时。并返回not response。等第四次,在5秒内访问 http://127.0.0.1:8080/deferredresult/reponse?msgid=001&value=test ,然后就在 http://127.0.0.1:8080/deferredresult/request?msgid=003 页面看到返回结果test了。

 

参考资料:

  https://www.cnblogs.com/coderxiaohei/p/14061468.html

 

本文地址:https://www.cnblogs.com/wunaozai/p/14078660.html
本系列目录: https://www.cnblogs.com/wunaozai/p/8067577.html
个人主页:https://www.wunaozai.com/

posted @ 2020-12-03 11:48  无脑仔的小明  阅读(1019)  评论(0编辑  收藏  举报