zoukankan      html  css  js  c++  java
  • 物联网架构成长之路(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/

  • 相关阅读:
    JavaScript event对象
    JavaScript Date对象
    JavasSript函数
    break语句补充:判断当前系统时间与2021年元旦相聚的天数
    JavaScript控制流程
    初识JavaSript-JavaScript主要特点,运用在HTML中的三种用法,基本语法
    一个简单的Java程序
    什么是Java语言规范、API、JDK和IDE
    Vue渐变淡入淡出的轮播图
    js获取窗口滚动条高度、窗口可视范围高度、文档实际内容高度、滚动条离浏览器底部的高度
  • 原文地址:https://www.cnblogs.com/wunaozai/p/14078660.html
Copyright © 2011-2022 走看看