云智能家居。 第2部分:云服务

图片

我将继续介绍有关云智能家居的三篇文章系列。

上一篇文章中 ,考虑了用于感知智能家居的设备,以及用于将感官数据转换为执行设备的控制命令的算法。 智能家居的主要组件是控制器,该控制器在大多数情况下会根据设置阶段确定的逻辑自主工作。 各种设备(IP摄像机,传感器,执行器)连接到控制器,控制器将从这些设备接收的数据发送到云。

现在让我们谈谈用于存储和处理来自传感器和摄像机的信息的云服务的体系结构。

云服务的好处


智能家居云服务提供了一种简单,灵活和廉价的方式来存储和访问从智能家居设备接收的数据。 云服务的用户无需担心其数据的安全性。 多处理器媒体服务器的功能(配备带有多个10到12 TB驱动器的RAID阵列的磁盘篮)远远超出了智能家居控制器中SD或闪存卡的容量。 另外,存储卡的重写周期数量有限并且经常失败,因此不可靠。 云中数据存储的深度由用户的资费决定,可以在其个人帐户中轻松配置。

此外,当智能家居设备通过NAT协议从外部网络隐藏时,无需访问用户路由器上的“端口转发”即可访问数据。 在可通过移动设备访问的个人帐户中,您可以轻松配置智能家居的配置和逻辑。

不仅方便将数据存储在云中,还可以对其进行处理,从而为用户提供不同时间段的统计信息。 下面我们将考虑一个基于多传感器测量值计算每周平均室温的示例。

云服务架构


在上一篇文章中,我们讨论了安装在用户端并使用几种协议与云服务进行交互的智能家居控制器:

  • MQTT用于在控制器和业务逻辑服务器之间交换JSON消息;
  • HTTP,用于从媒体服务器集群的负载均衡器中获取负载最小的媒体服务器的IP地址;
  • RTMP将H.264 + AAC流传输到媒体服务器。

现在,我们将考虑智能家居的云服务-它的主要组成部分,以及与智能家居控制器的交互方式。


(单击图片以更高的分辨率打开)

业务逻辑服务器是云服务中整个信息交换方案中的关键元素。 它的主要目的是通过RESTful API接口管理各种服务器子系统。 它基于用户模型实现了云服务的逻辑:根据所选资费,用户与智能家居控制器之间的交互等,记录视频存档和传感器测量值。

在客户端上安装的智能家居控制器和业务逻辑服务器之间交换JSON消息时,需要MQTT代理 。 客户订阅代理中充当消息通道的主题。 作为MQTT代理,使用Eclipse Mosquitto

媒体服务器集群是一种分布式系统,用于存储,处理,搜索和播放多云智能家居IP摄像机的视频信息。 一个特殊的负载均衡器收集有关集群中每个服务器当前性能的信息,计算负载最小的负载,并将其IP地址报告给智能家居控制器,该控制器将视频从摄像机传输到该控制器。

需要一个云数据库来存储云服务的用户模型,其设备的配置和当前状态以及有关视频存档条目的元信息。 作为云数据库的实现,使用了MySQL DBMS。

Touch Database是非关系型NoSQL数据库。 它按时间顺序存储智能家居传感器的事件和测量值。 为处理此类数据而优化的InfluxDB DBMS的使用可显着提高云服务的性能。

客户端应用程序的后端是服务器应用程序,其主要功能是以方便的格式提供从云和触摸数据库接收的数据,以供客户端应用程序随后在用户设备上显示。 后端还以JSON格式为智能家居控制器生成控制命令。 后端基于Laravel PHP框架。 在下一篇文章中,有关与云智能家居进行交互的客户端应用程序将对此进行更详细的讨论。

推送通知提供程序将有关智能家居事件的消息传递到用户的移动设备,以便他可以快速介入情况(例如,当出现漏水或冒烟时,请致电相应的响应服务)。 选择OneSignal服务作为Push-notifications的提供者,该服务具有便捷的RESTful API接口和识别移动设备的功能,这对于正确地操作用户个人帐户中的通知是必需的。

业务逻辑服务器


如前所述,业务逻辑服务器是云智能家居的关键组件。 基于用户模型 (系统用户的信息描述,包括系统,个人,财务和逻辑功能),他管理云中的各种服务,这些服务具有不同的实现和功能,并通过RESTful API接口相互通信。



服务器内部的业务逻辑模块负责以下操作:

  1. 在触摸数据库中管理智能家居IP摄像机的传感器测量值和运动检测器事件的存储;
  2. 管理由智能家居控制器广播的IP摄像机的媒体流在媒体服务器档案中的记录(恒定/通过运动检测器);
  3. 从客户端应用程序到智能家居控制器的命令翻译;
  4. 广播智能家居控制器的配置(连接的设备,用户定义的生产逻辑规则);
  5. 将有关智能家居控制器和已连接设备的状态的推送通知发送到客户端应用程序。

业务逻辑服务器的一个功能是与运行在Internet上多个服务器上的远程应用程序进行进程间通信。 大多数时候,业务逻辑服务器应用程序在I / O锁上处于空闲状态,因此它是基于多线程体系结构设计的,并且由一组有限的子任务组成。

为了确保最高效率,业务逻辑服务器的内部实现应该是最简单的( KISS原则 )。 由于用户模型是完全确定性的,并且不包含功能之间的变化关系,因此不需要灵活的推理机制(如在智能家居控制器中,用户逻辑由用户配置)。 因此,可以通过具有条件转换的常规算法框图来描述服务器内部业务逻辑模块的操作。


(单击图片以更高的分辨率打开)

启动后,业务逻辑服务器立即进入等待状态,使用MQTT协议(来自智能家居控制器)和HTTP(来自客户端应用程序的后端)来等待消息。 如果消息通过HTTP到达,则意味着用户与客户端应用程序进行交互并将命令发送到智能家居控制器或更新其配置。 为了使来自客户端的消息落入智能家居控制器中,该消息由业务逻辑服务器传输到该控制器所订阅的MQTT代理的相应主题( SendGatewayMessage任务 )。

在初始化阶段,智能家居控制器会等待用户将其注册到他们的个人帐户中。 因此,将执行子任务CheckGatewayExistance ,以检查MySQL云数据库中的相应状态。 要在您的个人帐户中注册,控制器会将其完整配置发送到业务逻辑服务器,然后将其后端广播到客户端应用程序( SendBackend任务 ),客户端应用程序将在云和触摸数据库中创建和更新配置记录。

当智能家居控制器成功注册到用户的个人帐户中后,业务逻辑服务器将根据以下业务逻辑算法将用户模型从云数据库加载到其RAM中,并开始处理来自IP摄像机和Z-Wave传感器的消息。

来自Z-Wave传感器的JSON消息,带有信息字段:

{ "vendor": "*****", "version": "3.0.0", "timestampMs": "1571754749561", "clientType": "gateway", "deviceId": "c8e8de37-d301-45f4-ba01-************", "deviceType": "sensor", "protocol": "zwave", "messageType": "sensorData", "homeId": "0xefa0cfa7", "nodeId": "19", "sensorType": "SENSOR MULTILEVEL", "label": "Temperature", "sensorData": "26.1", "units": "C", "gatewayId": "6774f85a-0a5b-4059-9b68-************" } 

当来自Z-Wave传感器的消息通过MQTT协议到达时,将执行以下子任务:

  • StoreSensorDataMySQL更新(UPDATE)MySQL云数据库中的现有记录,其中存储了有关传感器的当前状态和测量值的信息。 对于为用户显示智能家居当前状态的客户端应用程序而言,这是必需的。
  • StoreSensorDataInfluxDB将新记录添加(INSERT)到InfluxDB触摸数据库,该数据库存储来自传感器的测量历史记录。 该信息用于计算不同时间段(例如,每天,每月或每年的能耗)的统计数据,并以图形和表格的形式显示在客户端应用程序中;
  • SendPushNotification会生成JSON消息,其中包含时间戳,传感器名称,事件的文本描述,与他一起输入其个人帐户的用户的智能手机的标识符,OneSignal提供程序系统中应用程序的内部标识符。 此外,此消息通过RESTful API https://onesignal.com/api/v1/notifications发送到推送通知提供者,该消息将其传递到用户的智能手机。

来自IP摄像机的带有信息字段的JSON消息示例:

 { "vendor": "*****", "version": "3.0.0", "timestampMs": "1571753150317", "clientType": "gateway", "deviceId": "1616453d-30cd-44b7-9bf0-************", "deviceType": "camera", "protocol": "onvif", "messageType": "deviceState", "deviceState": "streamingOn", "mediaserverIp": "***.***.***.***", "applicationName": "rtp-live-iot", "gatewayId": "6774f85a-0a5b-4059-9b68-************" } 

当使用MQTT协议从IP摄像机收到消息时,业务逻辑服务器将从messageType字段中提取其类型。 根据此字段的值,执行以下操作:

  • “ MessageType”:“ deviceState” -该消息包含有关IP摄像机状态更改的信息。 执行子任务UpdateCameraState ,更新云数据库中的信息。 如果deviceState字段为streamingOnstreamingOff (IP摄像机将数据流发送/停止到媒体服务器), 则将执行RecordMediaStream子任务,该任务会生成一个启用/禁用档案记录模式的命令,并考虑到用户模型将其发送给媒体服务器;
  • “ MessageType”:“ sensorData” -有关IP摄像机上运动检测器操作的信息。 如果在用户模型中将存档记录模式设置为“通过运动检测器”,那么将执行RecordMediaStream子任务。 接下来,执行子任务StoreSensorDataInfluxDB (将检测器的历史记录保存在触摸数据库中)和SendPushNotification (通过提供者发送推送通知);
  • “ MessageType”:“预览” -消息包含来自IP摄像机的缩略图帧,该帧定期发送到云中。 子任务StorePreview将其保存在云数据库中。 然后,当显示摄像机列表时,它将在客户端应用程序中使用;
  • “ MessageType”:“命令” -当用户通过Web界面更改其设置时,智能家居控制器发送的命令。 执行子任务RecordMediaStream ,这取决于用户模型,打开/关闭媒体服务器上的记录模式。


(单击图片以更高的分辨率打开)

作为业务逻辑模块工作的结果,形成了一个任务队列 -彼此独立执行的一系列最小代码段。 任务队列被传输到线程池 ,该线程池在中央处理器的空闲内核之间分配任务。 在执行过程中发生I / O锁定时,线程暂停并进入空闲状态并释放中央处理器的内核,这使线程池可以立即从队列中启动下一个任务。 在释放I / O锁的那一刻,被阻塞的线程将其状态更改为工作状态,并在中央处理器的核心之一释放后立即继续执行。

因此,通过将业务逻辑任务分解为同时执行的许多单独的子任务,可以提高业务逻辑服务器的性能。 系统扩展是通过增加中央处理器的内核数量和系统中业务逻辑服务器的数量来实现的。

业务逻辑服务器应用程序是用C ++开发的,并作为Linux Debian Sarge操作系统的系统服务运行。 对于其他性能监视,使用监视资源监视系统,该监视资源监视系统会在性能出现问题时重新启动服务。

当前,云服务运行在Yandex.Cloud虚拟机上运行的一台业务逻辑服务器。 虚拟机参数-4个vCPU内核,保证的份额为20%,2 GB RAM,100 GB HDD。 根据计算,此性能足以处理来自〜1000个智能家居控制器的消息,每个控制器带有3个IP摄像机和5个Z-Wave传感器(计算将在系统运行期间得到澄清)。

媒体服务器


媒体服务器是专用服务器,在该服务器上安装了专用软件,用于:

  • 使用专用网络协议从编码器设备接收视频和音频数据流;
  • 在其文件系统中以归档文件的形式存储数据;
  • 以标准流格式广播存档文件中的信息,以便在客户端设备上播放。

具有Java语言开发的附加模块的Wowza流引擎4.7.2被用作云智能家居系统中的媒体服务器,用于将流数据记录到文件档案中并用于云数据库。


(单击图片以更高的分辨率打开)

来自智能家居控制器的RTMP格式的媒体流进入媒体服务器,并与抖动缓冲区中的时间戳对齐。 这是补偿通过Internet传输数据流时网络数据包延迟的影响所必需的。

为了将视频流作为MP4文件记录到媒体服务器文件系统,业务逻辑服务器通过RESTful HTTP API将以下命令发送到媒体服务器:

 http://<mediaserverIp>:<port>/v2/servers/_defaultServer_/vhosts/_defaultVHost_/applications/rtp-live-iot/instances/_definst_/streamrecorders/1616453d-30cd-44b7-9bf0-************ { "instanceName": "_definst_", "fileVersionDelegateName": "CustomFileVersionDelegate", "serverName": "", "recorderName": "1616453d-30cd-44b7-9bf0-************", "segmentSchedule": "", "outputPath": "", "currentFile": "", "applicationName": "rtp-live-iot", "fileTemplate": "", "segmentationType": "SegmentByDuration", "fileFormat": "MP4", "recorderState": "", "option": "", "currentSize": "0", "segmentSize": "0", "segmentDuration": "1800000", "backBufferTime": "0", "currentDuration": "0", "startOnKeyFrame": "true", "recordData": "false", "moveFirstVideoFrameToZero": "true", "defaultRecorder": "false", "splitOnTcDiscontinuity": "false" } 

recorderName字段中, 指示视频流的名称(智能家居控制器上的IP摄像机标识符),在fileVersionDelegateName字段中指示用于确定文件夹路径和文件名的继承类的名称。 以下清单显示了Java类代码:

 import java.io.File; import java.util.Calendar; import java.util.TimeZone; import com.wowza.wms.livestreamrecord.manager.IStreamRecorder; import com.wowza.wms.livestreamrecord.manager.IStreamRecorderFileVersionDelegate; import com.wowza.wms.logging.WMSLoggerFactory; public class CustomFileVersionDelegate implements IStreamRecorderFileVersionDelegate { @Override public String getFilename(IStreamRecorder recorder) { String sDisk = GetDisk(); if(sDisk == null) { WMSLoggerFactory.getLogger(null).error("CustomFileVersionDelegate::getFilename(): No drive chosen"); return null; } String sStreamName = recorder.getStreamName(); int nCameraId = Integer.parseUnsignedInt(ServiceQueries.GetCameraId(sStreamName)); TimeZone tz = TimeZone.getTimeZone("Europe/Moscow"); Calendar now = Calendar.getInstance(tz); String sDirPath = ServerParams.m_sServerContentPath + "/" + sDisk + "/" + Integer.toString(nCameraId / 200) + "/" + sStreamName + "/" + String.format("%1$tY/%1$tm/%1$td", now); String sFullFilePath = sDirPath + "/" + sStreamName + "_" + String.format("%1$tH_%1$tM_%1$tS", now) + ".mp4"; File dirs = new File(sDirPath); dirs.setExecutable(true); dirs.setWritable(true); dirs.mkdirs(); WMSLoggerFactory.getLogger(null).info( "CustomFileVersionDelegate::getFilename(): Filename created: " + sFullFilePath); return sFullFilePath; } } 

CustomFileVersionDelegate类中, IStreamRecorderFileVersionDelegate基类的虚拟getFilename函数已重载 ,在将流写入文件之前,媒体服务器会对其进行调用。 该函数在磁盘上使用路径sDirPath创建一个文件夹,并将完整路径返回到sFullFilePath文件。

由于媒体数据量非常大,因此文件系统包含多个作为子目录安装的大容量(8-12 TB)物理磁盘。 记录期间,具有最大可用空间的光盘被选为目标磁盘。 为了在访问文件时实现文件系统的最佳运行,目标文件夹的路径如下所示:

 /content/<diskId>/<cameraIdDivideBy200>/<streamUuid>/<year>/<month>/<day>/ 

其中diskId是磁盘(装入的文件夹)的标识符,
cameraIdDivideBy200-摄像机标识符除以200的整数的结果,
streamUuid-媒体流标识符,
年,月,日 -分别为年,月和日。

这避免了在一个文件夹中使用大量子文件夹,因此,随着多云智能家居中IP摄像机数量的增加,整个文件系统的性能将急剧下降。

有关媒体服务器IP地址,带有媒体数据的文件的路径,写入文件的开始和结束时间的信息存储在云数据库中,然后由客户端应用程序用来显示可在其上选择和播放视频的存档时间轴。

为了获取视频流,客户端应用程序的前端访问媒体服务器,并通过HTTP协议发送以下命令。 对于“实时”视频流:

 https://<mediaserverIp>:<port>/rtp-live-iot/<streamUuid>/playlist.m3u8 

对于存档的视频流:

 https://<mediaserverIp>:<port>/vod/_definst_/mp4:<diskId>/<cameraIdDivideBy200>/<streamUuid>/<year>/<month>/<day>/<fileName>/playlist.m3u8?wowzaplaystart=<offsetMs>&wowzaplayduration=<durationMs> 

其中, fileName是磁盘上存档文件的名称,
offsetMs-相对于文件开头的播放偏移量(以毫秒为单位),
durationMs-播放的持续时间(以毫秒为单位)。

媒体服务器以HLS格式发送流,该流使您可以在所有现代浏览器以及具有iOS和Android操作系统的移动设备上显示H.264 + AAC视频。 HLS打包器以单独的块的形式对流进行编码,并通过HTTP发送它,以响应来自移动应用程序的请求。

为了优化存储成本和访问存档文件,在Supermicro CSE-825TQ硬件平台,主板X8DT6、2xCPU Intel Xeon E5645 2.4 GHz,32 GB RAM,44 TB HDD Adaptec AAC-RAID上开发了云智能家庭媒体服务器。 媒体服务器作为专用服务器安装在宿主站点上,并以保证的400 Mbps宽度连接到Internet通道。 一台媒体服务器的性能足以以H.264编解码器,720p帧分辨率和1 Mbps比特率处理来自约400个IP摄像机的媒体流。



因此,为了能够处理来自1000个IP摄像机的流,必须安装3个媒体服务器并在它们之间平均分配负载。 为此,使用了一个负载平衡器,该负载平衡器作为单独的Dynamic Load Balancing AddOn插件连接到Wowza Streaming Engine媒体服务器。 实际上,这与负载均衡器(或源服务器 )有所区别,负载均衡器(或源服务器 )定期从最终媒体服务器(或边缘服务器 )接收性能指标,并根据此信息查找群集中负载最少的服务器。

智能家居控制器通过HTTP访问平衡器,并作为响应接收该服务器的IP地址,控制器通过RTMP将来自IP摄像机的媒体流传输到该IP地址。 性能指标包括与媒体流的源和使用者的已建立连接数以及服务器上Internet通道的当前带宽。 在平衡器的设置中,还可以考虑边缘服务器的地理空间位置来指定边缘服务器的选择,这使您可以在不同城市和国家/地区托管服务器,以创建用于分发CDN内容的分布式网络。

触摸数据库


如上一篇文章中前面提到的,智能家居控制器使用MQTT协议以JSON格式将Z-Wave传感器的读数以及IP摄像机的当前状态和事件发送到云。 业务逻辑服务器对这些消息进行解码并运行StoreSensorDataInfluxDB子任务,该子任务通过HTTP将数据传输到触摸数据库。


(单击图片以更高的分辨率打开)

智能家居的云数据库是基于InfluxDB 1.7.x开发的, InfluxDB 1.7.x是一个用于处理时间序列的开源数据库管理系统,在物联网的许多项目中都使用它来存储来自传感器和分析的数据。 触摸数据库的查询以类似于传统SQL的InfluxQL语言生成。

云智能家居中的数据存储时间由根据用户模型选择的资费确定。 由于视频数据和传感器数据量的巨大差异,它们的存储时间将有所不同。 视频存档的大小以天为单位(以不同的比率分别为7、14、30天),传感器的存档大小以年为单位(分别为3、5、7年)进行度量。 因此,对于每个智能家居控制器,在将其注册到用户的个人帐户后,都会在touch数据库中创建两个具有不同保留策略的单独数据库:

 CREATE DATABASE "gateway_6774f85a_0a5b_4059_9b68_************_cameras" WITH DURATION 720h SHARD DURATION 1h; CREATE DATABASE "gateway_6774f85a_0a5b_4059_9b68_************_sensors" WITH DURATION 61320h SHARD DURATION 24h; 

客户端应用程序的后端负责在touch数据库内部创建,编辑和删除数据库。 例如,如果云智能家居用户更改费率,则后端将发送以下命令来更改存储策略:

 ALTER RETENTION POLICY "autogen" ON "gateway_6774f85a_0a5b_4059_9b68_************_cameras" DURATION 168h SHARD DURATION 1h; 

从用户的个人帐户中删除智能家居控制器时,后端将删除相应的数据库:

 DROP DATABASE "gateway_6774f85a_0a5b_4059_9b68_************_cameras"; DROP DATABASE "gateway_6774f85a_0a5b_4059_9b68_************_sensors"; 

收到来自智能家居控制器的信息消息后,业务逻辑服务器执行将数据插入触摸数据库的请求:

 INSERT device_20873eb0_dd5e_4213_a175_************,class=METER,label=Energy,units=kWh value_float=0.05 1572194550125; 

带有来自一个智能家居控制器的Z-Wave传感器数据的表格示例:



云屋最有用的功能之一是根据接收到的数据计算统计信息。 用户需要知道房间的平均温度或他每月花费多少电量。

InfluxQL语言允许您使用分析功能执行查询。 例如,要计算一周的平均温度,您需要运行以下查询:

 SELECT MEAN("value_float") FROM device_63c660da_f0e8_4eca_8d5f_************ WHERE label = 'Temperature' AND time >= '2019-10-21T00:00:00.000Z' AND time <= '2019-10-27T23:59:59.999Z' GROUP BY time(1d) fill(null); 

该查询的结果显示在表中:



在完全专门针对客户端应用程序的下一篇文章中,我们将详细考虑各种参数的统计信息的计算以及基于该参数的表和图形的构造。

在云智能家居系统中,InfluxDB DBMS部署在Yandex.Cloud虚拟机上,该虚拟机具有以下参数:4个vCPU内核,保证份额为20%,2 GB RAM,100 GB HDD。 根据此配置的计算,足以存储3,000个IP摄像机和5,000个Z-Wave传感器的传感器数据长达7年。

结论


本文研究了用于智能家居的云服务的体系结构,业务逻辑服务器的算法,用于记录,存储和回放来自IP摄像机的媒体流的媒体服务器的体系结构,以及用于存储和分析来自智能家居传感器的数据的触摸数据库的体系结构。 云服务系统可在专用服务器和虚拟服务器上运行,以提高位于不同托管站点上的稳定性。 该系统目前正在试用中。

存储在云中的数据越旧,用户访问它的频率就越低。 在下一版本的云服务中,建议使用通过InfluxDB连续查询来稀疏(或过采样)数据的机制,以便通过聚合功能减少存储的数据量,从而增加触摸数据库的容量。



同样,在下一版本的云服务中,将根据本文讨论的媒体服务器集群的原理来实现业务逻辑服务器集群。 该图显示了这种群集的体系结构,其中几个边缘服务器(每个边缘服务器具有单独的MQTT代理和业务逻辑服务器软件)将性能指标发送到原始服务器,该原始服务器计算负载最小的服务器的IP地址。 这将允许您更大程度地扩展系统并克服现有的1000个智能家居限制。

Source: https://habr.com/ru/post/zh-CN474700/


All Articles