客户有一堆小设备,需要通过小程序来控制它们,主要是设备门的开关、电源开关、状态查询、压力控制等。下面主要纪录下设计思路。源码地址:https://gitee.com/bxjg1987/abp

最初的设计是这样的

核心流程有3个,分别用绿、蓝、黑这3种颜色来标识。

流程1:小程序端发送指令控制设备(开关、舱压调整等)

以开关电源控制为例

  1. 小程序向wei服务端发起请求,说我想关闭设备id为1的那个设备
  2. wei服务端准备一条消息(说我要关闭id为1的那个设备),发送给RabbitMQ消息队列
  3. RabbitMQ消息队列将消息推送给硬件服务器
  4. 硬件服务器解析消息,根据设备id和按协议约定准备byte[]指令下发给具体设备
  5. 设备回复消息给硬件服务器
  6. 硬件服务器组织一条回复消息(所id为1的设备已经关闭成功)发送给RabbitMQ消息队列
  7. 消息队列将回复消息推送给web服务端
  8. web服务端通过abp提供的通知功能(默认基于a's'p.net core signalr)通知小程序端,

此时小程序端开源认为操作成功,但是不是太准确,另一种办法是小程序再查一次设备状态确认下。所以上面的步骤5可以向设备触发一个请求,让设备立即上报一次数据。默认情况下设备是轮询的比如30秒上报一次数据。

流程2:设备轮询30秒上报一次数据

  1. 设备上报状态数据
  2. 硬件服务器将设备状态数据存储到数据库
  3. 硬件服务器向RabbitMQ消息队列发送一条消息,说设备id为x的设备上报了状态数据
  4. RabbitMQ消息队列将消息推送给web服务端
  5. web服务端通过abp提供的通知机制通知小程序端

步骤3没必要直接将状态数据推送给消息队列,因为此消息的接收方未必关系具体的数据,目前设计只是说有设备状态上报了,这个消息通知到接收方,由接收方决定是否主动来查设备状态

流程3:小程序主动查询设备状态

这个就比较简单了

  1. 小程序端向web服务端发起查询请求
  2. web服务器直接从数据库查询设备状态返回就可以了

有点问题,这样查询不是设备的当前状态,我们可以再定义接口直接去查一次当前设备的状态,但是这样编码比较大,也不利于我们复用现有流程。最简单的办法是定义一个接口,向设备发送一条指令说请你立即上报一次数据,小程序原有的查询设备状态查到就是最新的了。

设备服务端SuperSocket

开源地址:https://github.com/kerryjiang/SuperSocket,这是个设计得比较好的,基于.net core的socket的通信框架。官方有文档学起来比较简单。

它负责与设备通信,可以单独部署在一台服务器上。

基于Abp的Web服务端

这就不多说了,因为它已经为我们提供了很好的web服务端基础设施,免得从头做起。此服务端也可以单独部署一台服务器

消息队列RabbitMQ

其它mq没用过,就用它咯。它主要是解耦设备服务端和web服务端的,主要是它可以主动推送消息给接收方,也可以考虑使用redis的推送来实现。消息队列也可以单独部署一台服务器

简化后的设计

如果设备比较少,请求量不大可以用下面这种简化的设计

既然是简化,流程就不说了。主要是省略了消息队列,并且省略了指令回复的处理,而是使用轮询的方式,比如每过10秒查一次当前设备状态,控制设备时,只是下发指令,而不等结果,因为我们的轮询会查到下一次的设备状态。

这里有些注意:

  • 设备上报状态存入数据库时可以使用一个全局的数据库连接
  • web服务器向设备服务器发送指令时也可以考虑使用全局的tcp连接
  • web服务器向设备服务器发送指令时可以使用supersocket提供的客户端库

结束

简化后的方案最low,但是也最容易实现,目前源码中就是采用的这种方式。前一种方式稍微好点,3台服务器可以分开部署,如果并发再大点可以考虑下分布式了,再不行就放弃这个上思路,直接上个阿里云IOT啥的。

随机推荐

  1. AutoMapper(七)

    返回总目录 Null值替换 如果源类型的成员链上的属性值为Null,Null值替换允许提供一个可替换的值.下面有两个类Person和PersonInfo类,都有一个属性Title(头衔),从Perso ...

  2. SuiteScript > Script Queue Monitor (Beta)

    Share Note: Installing and Accessing the Script Queue Monitor Script Queue Monitor (Beta) is availab ...

  3. JQuery EasyUI validatebox(验证框)

    JQuery EasyUI validatebox(验证框) http://www.easyui.info/archives/602.html

  4. JavaScript学习之—prototype

    一.利用prototype扩展String方法,去除字符前后空格: String.prototype.trim = function String$trim() { if (arguments.len ...

  5. SQL Server ansi_null_default | ansi_null_dflt_on

    先说一下这两个变量是一个意思,只是它们的作用范围不同 alter database dbTest set ansi_null_default on;  -- 这个的作用域是整个SQL Server   ...

  6. 基于visual Studio2013解决C语言竞赛题之1086任务分配

        题目 解决代码及点评 /************************************************************************/ /* ...

  7. Redis简介 Linux安装Redis Redis使用

    其他一些操作(包括 APPEND.GETRANGE.MSET 和 STRLENGTH 也可用于字符串.请参见http://doc.redisfans.com/string/index.html ) 使 ...

  8. Kubernetes之Deployment控制器

    Deployment 简介 deployment 是用来管理无状态应用的,面向的集群的管理,而不是面向的是一个不可变的个体,举例:有一群鸭子,要吃掉一个,只需要再放一个新的鸭仔就好了,不会影响什么,而 ...

  9. os.remove异常处理

    这种情况,正反斜杠都没问题.(windows环境下) 这种情况会出现下列异常 对于目录的形式,把反斜杠改成正斜杠就好了

  10. MongoDB 查询 $关键词 方法目录

    MongoDB $关键字 关系比较符号 $lt $lte $gt $gte $ne MongoDB 查询$关键字 $in $or $all MongoDB limit 选取 skip跳过 sort排序 ...