【搭建物联网后台】基于Workerman的物联网后端管理平台设计 您所在的位置:网站首页 workerman是什么协议 【搭建物联网后台】基于Workerman的物联网后端管理平台设计

【搭建物联网后台】基于Workerman的物联网后端管理平台设计

2023-08-11 18:36| 来源: 网络整理| 查看: 265

项目地址:https://github.com/Laity000/SmartBed-Workerman-AngularJS

在线演示(手机端登录虚拟设备admin1): 在这里插入图片描述

部分功能展示:

通过二维码绑定设备: 在这里插入图片描述

控制设备并实时反馈: 在这里插入图片描述

查询设备历史数据: 在这里插入图片描述

写在前面

最近开发了一款关于物联网项目的后端管理平台,可以实现对设备的管理,包括设备的连接、区分,状态反馈的推送、记录,对设备的控制等操作(这里的设备是护理床,主要可以实现对姿态的实时记录、控制)。以及,用户端可以实现多种终端多对一设备绑定,监控。

其管理平台的业务特征如下:

设备是基于TCP长连接,指令/反馈不定期实时推送,因此需要长连接双向通信。设备需要后端平台的管理支撑,如设备的区分,数据长久化保存,设备批量化管理设备需要一对多的绑定,实现多用户不同终端的实时监控用户端需要查询设备的实时状态(观察者权限)、授权控制设备(控制者权限)

这里把项目(后端,前端)中的一些设计思路和开发心得整理记录下来。如果你的业务中也需要设备管理模块的设计开发,或者正好需要上述特征,下面的介绍或许对你有所帮助。当然有错误之处,也请批评指正。

(~ ̄▽ ̄)~

后端的选择与设计

首先我们思考下物联网后端的设计难点。如何选择和设计物理网项目的后端框架呢?

——>难度1:选择

需要什么样的通信方式(协议),决定了使用什么样的服务器框架。

与传统的web服务器不同,我们这里的设备由于需要基于TCP的长连接、实时通信,在后端中我们需要实现socket通信。而用户端采用应用层的协议通信,便于终端的开发。为此,我们需要一款支持长连接的、多协议转化的服务器框架。

——>难度2:设计

其次,根据业务的特征:由于设备端的数据需要实时推送给绑定的用户,用户也需要给绑定的设备发送控制指令。

整个业务场景类似于IM聊天室的感觉,只不过这里的角色不是平等的,具体划分为设备端和用户端(给予不同用户权限)。我们的后端分别需要对设备管理和用户管理。

设备的管理主要包括:设备的登录识别,设备的控制,设备可以反馈什么状态、反馈到哪,设备状态的长久化记录,具体用户绑定后与设备的交互,等等用户端需要分为用户的管理和具体用户的操作:也就是不同的用户对设备有不同的操作权限(观察模式和控制模式)用户的管理:因为涉及不到设备模块,这个可以归纳到web开发中,web开发包括了整个app建设,包括需求、数据。具体用户的操作包括:用户对设备的绑定和解绑,用户对设备状态的查询(查询数据库、直接发送指令查询设备),与设备的交互,等等。 ——>整体框架

这里写图片描述

项目后台的架构图如上所示。采用模块化的方式,包括两个大的模块:

设备管理模块(后端:wm模块):这是我们本篇所讨论的用户管理模块(web模块):后续的开发,不影响wm模块的开发

web模块在wm模块(后端)的基础上,便于后续的扩展。(目前还没有设计web模块,用户不需要注册和登录,直接匿名登录的方式连接到wm模块后绑定设备。后面业务逻辑章节有具体说明。)

区别:Workerman是一个通用的socket服务器框架,支持长连接,支持各种协议如HTTP、WebSocket以及自定义协议。而Apache/nginx/php-fpm一般来说只用于开发HTTP协议的Web项目。

我们目前首要的任务是关注设备端的管理,设备与用户的通信交互。也就是物联网后端的选择和设计(设备管理,用户操作的业务)才是项目开发的重中之重。

我们后端选择的是workman框架。前面开题提到的管理平台的业务特征,其实,80%都是建立在其中的GatewayWorker框架之上的(文中用gw框架代替)。

为什么选择workerman?

初期调研的时候开始寻找是一些物联网的公有云平台,但是发现大多都是面向企业的(收费滴~~ ⊙︿⊙),不能个性化定制。对于个人开发者来说主要是不开源的,没有学习的机会。

后来了解到了Workerman(传送门),一款纯PHP开发的开源高性能的PHP socket 服务器框架。

其中二次开发的GatewayWorker(传送门)进程模型具有高并发,长连接,支持单播、多播(一对多模式)、广播方式推送消息,支持多协议等特征。

gw框架是为聊天室设计的IM服务端,并且开发文档丰富,上手起来也很快(为了学习后来自己也基于此DIY了一个聊天室DEMO:基于JavaFX的聊天室ChatRoom)

具体的workerman介绍就不在这班门弄斧了,官方的介绍和文档在上面传送门中。总之,GatewayWorker的业务逻辑也适合物联网项目,比如上面提到的GatewayWorker特征都可以用到项目的业务中。

通信协议的思考

工欲善其事,必先利其器。在介绍如何设计后端之前,先传授下协议大法。

通信协议可以简单解释为双方“说话”的规则,需要考虑的问题:数据的形式,怎么发送数据,数据怎么被对方理解,等等。

——>为什么需要通信协议?

由于TCP是基于流的,客户端发送的请求数据是像水流一样流入到服务端,服务端探测到有数据到来后应该检查数据是否是完整的,因为可能只是一个请求的部分数据到达服务端,甚至可能是多个请求连在一起到达服务端。如何判断请求是否全部到达或者从多个连在一起的请求中分离请求,就需要规定一套通讯协议。——workerman

简单来说,我们这里说的协议可以归纳为网络中应用层的协议,是在TCP基础上,为解决网络中数据包粘包问题。当然协议的作用这只是其中一点。我们主要关心的key:

区分指令/反馈的标识指令/反馈格式定义

一般通信协议都有现成的技术,根据不同的场景有不同的应用,比如我们熟悉的:

http(网站)websocket(长连接)mqtt(物联网)

当然有时候需要自定义协议,比如用于单片机不需要这么复杂的:

workerman中自定义的text协议我们项目中设备与服务器通信的数据包协议

但是本质上还是在TCP基础上简单实现的。

——> 总结: WebSocket vs HTTP : 主要考虑用户可以通过多种终端(网页,移动,pc)通信,http和websocket基本上都可以做到由于指令(发送)和反馈(接收)是实时,有状态的,双向通信但是http是c/s模式,无状态、无连接;而websocket支持长连接websocket 胜! 我们项目中用户与服务器的通信使用websocket通信的(gw框架中已支持)设备端使用自定义的数据包协议,协议简单支持单片机解析,需要自己编写(如何在gw框架中编写自定义协议,请查看官方手册,项目源码中也有例子)由于用户端和设备端拥有各自的协议,会增加后端开发的难度,因为需要分别对应解析(框架中设置两个端口分别接收用户端和设备端数据) 数据的格式在业务逻辑中需要转化,比如用户端的指令需要转发成数据包的形式发送给设备。

——>下面具体介绍用户端和设备端两种数据的消息类型。

后端设计之消息类型 设备端与服务器的消息类型用户端与服务器的消息类型

如果说通信协议是各种终端与服务器沟通的桥梁,那么消息类型就是其中行驶的各类车辆。不同的汽车代表不同的数据,不管是终端还是服务器都需要提前知道其含义(这里就是设计封装/解析消息的业务逻辑)。

只有将数据(指令/反馈)封装成消息类型,数据才有了灵魂。我们需要考虑的key:

第一点:如何封装成消息?第二点:有哪些消息(指令和反馈)? ——>第一点:

首先一条消息要根据需要分为几个字段,比如:①既然要区分消息类型,就要有类型字段,②消息的来源,③有些消息还要携带内容。

其实,封装消息就是相当于关联数组的形式。然后将数组转换成字符串(用户端)或字节流(设备端)发送。

项目中的用法:

用户端采用Json的格式封装消息,是比较流行的方法,各种终端都有相应的开源API,用起来方便设备端由于解析的难度,采用常见的简单数据包格式,变长的数据包具体有两种(其中关键的就是如何判断数据包的起始和结束):包头+包类型+包长度+内容+校验(项目中使用的)包头+包类型+内容+校验+包尾 ——>第二点:

有哪些消息类型就是业务逻辑的事情。

再介绍之前首先明确三种***消息的流向***(结合下章的分析效果更佳):

设备——服务器——>用户:反馈(如设备状态信息)用户——服务器——>设备:指令,包括:查询指令:通用的权限(如姿态查询)控制指令:有权限 (如控制姿态)服务器设备/用户:服务器反馈(如设备的心跳检测,用户/设备的登录和反馈)

消息类型具体参见(结合下章的分析效果更佳):

设备端的消息类型:设备数据包格式(这里)用户端的消息类型:用户端与服务器具体的消息类型(这里) 后端设计之业务逻辑的设计

建议在思考自己的业务逻辑之前,首先整体阅读下GatewayWorker文档(传送门)! 建议在思考自己的业务逻辑之前,首先整体阅读下GatewayWorker文档(传送门)! 建议在思考自己的业务逻辑之前,首先整体阅读下GatewayWorker文档(传送门)!

好了,现在万事具备,只欠东风。接下来我们可以大干一场,开发出属于自己的需求。当然啦,不同的需求需要不同的业务逻辑。

这里提炼下我们项目中用到的一些业务逻辑和心得体会,避免走弯路,也许对你会有所启发。

——>0、概况

首先,我们的后端特征如下所示:

使用Workerman中GatewayWorker框架(类似IM场景)长连接、有状态、双向通信,实现指令和反馈的不定期实时推送双协议:TCP+自定义数据包格式(设备端),WebSocket+Json格式(用户端)发布订阅模式,实现设备一对多用户。也可以实现点对点应答模式业务逻辑清晰:设备登录,用户绑定,实时反馈(观察者权限),授权控制(控制者权限)设备状态实时记录到MySQL数据库中,支持按日期查询

简单的流程图如下所示:

用户主机 服务器主机 设备主机 连接请求,携带PID(设备标识符) 记录PID ,检查唯一性 允许连接 发送设备状态信息 解析状态记 录到数据库 用户在某刻 时间段后登录 登录,携带UID(用户标识符) 记录个人信息 登录成功 发送待连接设备的PID,绑定设备 如果该设备在线 绑定成功 查询设备状态 发送数据库记录的设备当前状态 发送指令 动作完成,记录状态 用户主机 服务器主机 设备主机 用户、设备连接建立的过程 ——>1、设备的识别和用户绑定设备

首要解决的问题便是设备连接服务器后的识别、管理,然后用户绑定对应的设备进行交互。

项目中用到的识别号及作用:

id:gw框架中提供的连接识别号(20个字节,全局唯一),不管是设备还是用户连接到gw框架后都有一个id号,用于gw框架中业务逻辑的开发。pid:设备的识别号(自定义的,6个字节),用于后端区分设备,管理设备,用户通过pid可以绑定到设备,建立通信。uid:用户的识别号(目前没有定义),目前用户端直连到gw获取id,后期增加用户管理(web模块),实现用户uid的注册、登录、授权控制。

具体的逻辑如下:

①设备连接到服务器后首先需要发送自己的pid,保存在session中②服务器还需要进行pid有效性检查、重名检查等③用户绑定设备时需要检查设备是否在线④用户绑定成功时将设备pid保存在gw框架的uid中,使用Gateway::bindUid(gw框架uid与用户uid不同,原理请查看官方手册)⑤每次服务器向设备发送消息时也需要检查设备是否在线⑥多个用户和绑定的设备可以发送指令和反馈(具体如何实现交互的,结合下文3.一对多模式介绍)⑦用户下线后会自动解绑,或手动解绑Gateway::unbindUid ——>2、观察者、控制者用户权限

结合上文的三种消息流向,我们设计了两种用户权限:

观察者权限:设备的反馈信息发送给用户,和一些查询设备指令控制者权限:用户控制设备,这里指的是一些受限的控制指令(比如操作设备),并不是所有的指令(比如直接查询设备)

**一个合法的用户可以有观察者权限,但是不一定会有控制者权限。**控制者权限需要授权后获得。

可以在后期的开发中(web开发)加入用户角色的管理,目前用户是直接匿名连接gw框架的。至于控制者权限,需要输入对应设备的密码,服务器才接受该用户对设备的控制。

具体反馈和指令的消息流向是怎么传输的,还需要结合下文的一对多模式来分析。

——>3、设备一对多用户模式

如果设备和用户只需一对一的绑定,那么开发起来很简单,可以直接在数据库或session中建立用户和设备的映射关系,来实现指令和反馈的传输。

但是,我们项目考虑用户可以实现多种终端监控,那么多个用户都可以直接绑定到同一个设备上,那么用户与设备之间是如何交互的呢?比如,设备发送反馈需要考虑是发送给所有绑定用户,还是发送给一个用户。用户如何通过pid找到绑定的设备id。

下面具体分析之:

用户——服务器——>设备:由于用户只能将指令发送给绑定的设备,设备的pid保存在用户gw框架的uid中,通过其找到用户的id //检查用户是否绑定了PID $boundPID = Gateway::getUidByClientId($user_id); //设备集session $bed_sessions = Gateway::getAllClientSessions(); //检查设备是否在线 foreach ($bed_sessions as $temp_client_id => $temp_sessions) { if(!empty($temp_sessions['PID']) && $temp_sessions['PID'] == $boundPID) { return $temp_client_id; } } 设备——服务器——>所有用户:设备更新后的数据直接推送给所以绑定的用户,发布订阅模式,使用Gateway::sendToUid

什么是发布订阅模式:观察者模式和“发布-订阅”模式有区别吗?

具体实现原理详见gw手册中的介绍:这里

设备——服务器——>单个用户:点对点应答模式(这里具体分析下)

应答模式:用户发送一个合法指令给设备,设备解析后必须应答该指令发送反馈给原用户。(不合法的指令服务器会直接拒绝不转给设备,但也会给原用户发送相应的服务器反馈)

由于用户对设备来说是无状态的,设备就不知道发来的消息是哪个用户,无法直接点对点回复。那么怎么实现?

首先前提是我们的设备在收到指令后才发送反馈消息,是典型的点对点中的应答模式。

一种方式是:发送给设备的消息字段中包括用户的uid或id,设备发送反馈消息携带该uid或id,服务器就知道了该发给哪个用户。

另一种方式:我们的设备本质上是资源互斥。在同一时刻只能接收唯一用户的指令,当工作完后再发送相应的反馈。那么可以:①在发送指令时,给设备进程设置sessionGateway::setSession(array('work01_userid'=>xxx)对应用户的id,②工作完成后释放设备进程中该sessionGateway::updateSession,③当有其他用户想要操作设备时,首先检查设备进程中该操作的session释放被释放,没有释放则直接反馈正在工作的服务器反馈。

如果你的需求不是互斥的应答模式,选择第一种。我们这用第二种。

上面用户与设备的交互都经过服务器,服务器接收到消息解析后决定怎么处理,发送给哪个、全部用户或哪个设备。但是,如果服务器处理发来的消息不需要转发,而是直接反馈给原设备或原用户(服务器反馈)呢:使用Gateway::sendToCurrentClient

服务器——>设备:设备数据包格式(这里)服务器——>用户:用户端与服务器具体的消息类型(这里) ——>4、心跳检测

心跳检测在设备与服务器交互中也是不可忽略的一部分。由于设备自定义协议部分没有完善的断开连接检测机制,设备掉电的等情况下,服务器端无法短时间内知道设备的连接情况(长时间后可以通过TCP层知道连接断开)。为此,需要心跳检测的设置。

gw框架中有心跳检测的详细介绍和几种用法:这里

我们项目中是通过设备定时向服务器发送ping数据包,如果超过一定时间没有发送,则认为设备断开。(主要考虑到设备同时接受和发送数据存在丢失的情况,设置优先级)

——>5、日志

当后端以守护进程的方式运行时,需要将后端的运行日志输出到文件中保留。

这里采用monolog日志类库(这里)。

按日期生成日志文件。(日志位置:Applications\SmartBed\log)

——>好了,我们的业务逻辑就分析到这里了~~

前端设计

我们前端的特征:

使用AngularJs+jQuery WEUI搭建移动版单页面应用程序UI与业务的分离,使用angular-websocket接发消息,实现UI的异步刷新实现断开重连功能(手机在锁屏后会断开ws连接)实现扫描二维码绑定设备功能(设置绑定功能的路由url) ——>0、前端的选择

简单介绍下前端的选择和设计。由于我们的后端已经预留好了用户端的应用层协议(WebSocket)和消息类型(Json的形式),可以支持多种终端的开发:web端,手机端,PC端。

从技术的角度来说以上都可以实现,开发中主要关注几点:

①数据的解析和发送②UI界面的设计③数据与UI的交互

从用户的角度来说,网页版的轻应用(web app)无疑是首选,也是当前物联网前端开发的趋势。

只要是支持浏览器的各种终端上都可以运行。开发方便,有各种现成的前端框架和UI前端业务放在服务器中,更新维护方便

为此,我们web app的搭建选择AngularJS(web后台)和 jQuery WEUI(web前端)。

——>1、为什么选择AngularJS?

首先,需要了解下什么是单页面应用。

单页应用程序 (SPA) 是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。 浏览器一开始会加载必需的HTML、CSS和JavaScript,所有的操作都在这张页面上完成,都由JavaScript来控制

通俗一点说就是指只有一个主页面的应用,浏览器一开始就必须加载所有的html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。

我们项目中,处理websocket的业务逻辑(连接ws,接收/发送数据)都放在js中,在加载首页面时就建立起ws连接。但是,如果使用传统的多页面,每次跳转页面都行需要重新加载js,也就需要重新建立ws连接。

这就是项目中使用单页面应用的原因。其中,AngularJS就是一款优秀的前端JS框架, 使得开发现代的单一页面应用程序变得更加容易。由于自己在前端也是小白一枚,就不做过多介绍了。

主要说下我们项目中选择angularJS的优势在于:

单页面:保证ws的一次连接不断开MVC模式:UI与数据分离,UI可以异步处理数据的更新依赖注入:业务逻辑的处理部分注入到factory服务中,实现松耦合路由机制:实现多视图的单页Web,同样可以通过不同的 URL 访问不同的内容

其中,最主要的关注就是业务逻辑的处理部分:

websocket数据的处理(ws连接、数据接收/发送)?UI如何做到数据的异步刷新?

在项目中我们用到了angular-websocket的开源库,结合项目中的业务逻辑,写了一篇详细的用法介绍和心得体会:angular-websocket学习笔记(这里)

——>2、jQuery WEUI

Query WeUI 是专为微信公众账号开发而设计的一个简洁而强大的UI库,包含全部WeUI官方的CSS组件,并且额外提供了大量的拓展组件,丰富的组件库可以极大减少前端开发时间。

基本上需要的UI界面和动画插件都有,并且开发起来也易上手。传送门:jQuery WeUI

总结

护理床的项目算是自己的第一次,o( ̄︶ ̄)o。

花了不少的时间,一边学习一边上手开发。从开始的安卓开发:手机局域网内的连接监控(这里),到后端设备管理平台的搭建。 收获:虽然只算的上是一个学习研究的项目,离最终的目标还差的远,其中很多功能也不够完善和稳定。但这期间从后端到前端也学到了很多技术,知道项目开发的一些基本知识,锻炼了撸代码的能力。

不足之处:第一,因为都是自己一个人在折腾,视野和技术的选择会不够好。第二,目前只是做到拿来即用,技术栈的研究不够深入。后面多看看源码和技术细节,知其然知其所以然。

仅此附上项目开发的心路历程。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有