基于物联网技术设计的陈列馆监控系统【玩转华为云】
当前项目使用的相关软件工具、传感器源代码工程已经上传到网盘(实时更新项目内容):https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
1.1 项目开发背景
随着科技的迅速发展,物联网(IoT)技术在各个领域的应用日益广泛,尤其是在智慧场馆管理中表现出强大的潜力。陈列馆作为重要的文化遗产和文物展示空间,其环境的精细化管理至关重要。文物的保存对温度、湿度、光照等环境参数有着严格要求,同时也需要高度重视安全防范工作,防止火灾和盗窃等突发事件对文物造成损害。因此,设计一套基于物联网技术的智能监控系统,可以有效提升陈列馆的管理效率和文物保护水平。
传统的陈列馆监控方式通常依赖人工定时巡查和简单的环境监测设备,缺乏自动化与智能化手段。这种方式不仅效率低下,而且在紧急情况下响应能力有限。通过物联网技术与智能化手段的结合,可以实现对陈列馆内环境参数和安全状况的全面感知和实时管理,大幅提高运行效率和风险防范能力。
该项目构建一个功能全面、实时监控的陈列馆智能监控系统。通过引入高精度的温湿度传感器(SHT30)、光照强度检测模(BH1750)、烟雾和火焰传感器(MQ2和火焰传感器),实时采集馆内环境数据,并利用10寸LCD显示屏进行本地展示,同时通过WIFI模块(ESP8266)和MQTT协议将数据上传至华为云IoT平台,实现云端存储与分析。结合Qt开发的Windows可视化大屏,工作人员可以在办公室内直观查看环境参数、预警信息及陈列馆实时监控画面,进一步提升管理便捷性。
此外,系统还结合了视频监控功能,采用支持RTMP推流的独立摄像头,将实时视频画面通过NGINX服务器推流至华为云ECS服务器,并在可视化大屏上呈现。同时,通过深度学习算法对视频画面进行人体识别,实时统计陈列馆内人流量并生成每日统计数据,为场馆运营提供决策依据。
本系统的开发不仅满足了陈列馆日常环境监控与安全管理的需求,还通过引入先进的IoT技术和视频分析能力,为文物保护和场馆管理提供了一种高效、智能的解决方案,具有广泛的推广价值和应用前景。
大屏调试
下面是陈列馆
的内部实景一角。
1.2 设计实现的功能
(1)温湿度检测 使用SHT30传感器实时检测陈列馆内的环境温度和湿度,确保文物保存的适宜条件。
(2)光照强度检测 使用BH1750传感器实时检测光照强度,避免强光对文物造成损害。
(3)烟雾与火焰检测 通过MQ2传感器检测烟雾浓度和火焰传感器检测火光,及时发现火灾隐患。一旦检测到火情,系统将立即拉响警报并触发报警机制。
(4)本地数据显示 配备10寸LCD显示屏,实时展示采集的温湿度、光照强度等环境参数。显示屏安装在陈列馆大门口,方便工作人员查看。
(5)数据上传与云端存储 使用ESP8266模块,通过WIFI和MQTT协议,将采集到的环境数据上传至华为云IoT物联网平台进行存储和管理。
(6)可视化大屏显示 在办公室内的Windows电脑上,通过Qt开发的可视化大屏展示环境参数、实时监控画面及预警信息,方便工作人员远程管理。
(7)环境参数预警 当温湿度、光照强度超出预设阈值时,系统会在可视化大屏上发出警示,提醒工作人员及时采取措施。
(8)视频监控与实时推流 使用支持RTMP协议的独立摄像头,通过NGINX服务器推流,将实时监控画面上传至华为云ECS服务器。可视化大屏上可以实时查看视频监控画面,便于随时了解馆内情况。
(9)人流量监控与统计 基于深度学习算法进行人体识别,实时统计陈列馆内的人流量。在可视化大屏上显示当前人流量,并生成每日统计数据,为运营分析提供支持。
(10)火灾警报与应急响应 在检测到火灾时,系统会自动触发警报,同时上传报警信息到云端,提醒工作人员采取应急措施。
(11)稳定供电支持 系统通过220V市电供电,保证设备长期稳定运行,满足陈列馆全天候监控需求。
1.3 项目硬件模块组成
(1)主控芯片(STM32F103RCT6) 作为系统的核心控制单元,负责接收和处理各类传感器的数据,控制显示屏显示内容,管理与云端的通信等功能。
(2)温湿度传感器(SHT30) 用于实时检测陈列馆内的环境温度和湿度,数据将被传输到主控芯片进行处理和显示。
(3)光照强度传感器(BH1750) 用于测量陈列馆内的光照强度,确保馆内光照水平符合文物保护的需求。
(4)烟雾传感器(MQ2) 用于检测馆内是否有烟雾存在,及时发现火灾隐患,防止火灾的发生。
(5)火焰传感器 用于检测火焰的存在,一旦检测到火焰,立即触发报警系统进行应急处理。
(6)WIFI模块(ESP8266) 负责通过WIFI将传感器采集的数据上传至华为云IoT平台,支持与云端的通信和数据传输。
(7)显示屏(10寸LCD显示屏) 用于实时显示陈列馆内的环境参数,如温湿度、光照强度等,便于工作人员进行现场监控。
(8)220V市电供电模块 为整个系统提供稳定的电源支持,确保硬件设备持续运行。
(9)监控摄像头(支持RTMP协议) 用于实时采集陈列馆内的画面,并通过RTMP协议将视频推送至云端,支持视频监控和人流量统计功能。
(10)视频推流服务器(NGINX服务器) 用于接收来自监控摄像头的RTMP视频流,并将其转发至华为云ECS服务器,实现实时视频监控功能。
(11)环境参数报警模块 当检测到温湿度或光照强度超出预设阈值时,系统将通过警报装置(如蜂鸣器、LED指示灯等)向工作人员发出预警信号。
1.4 设计思路
本项目的设计思路是通过物联网技术将传感器数据采集、视频监控和云端管理相结合,构建一个智能化、自动化的陈列馆环境监控系统。其核心目标是实时监测环境参数、确保文物安全,并通过智能化管理提升陈列馆的运营效率。
系统通过多种传感器模块实现环境参数的实时监测。温湿度传感器(SHT30)和光照强度传感器(BH1750)负责监测陈列馆内部的温度、湿度和光照强度,确保环境条件适宜文物的保存。烟雾传感器(MQ2)和火焰传感器则负责检测馆内是否存在火灾隐患,一旦发生异常,系统会及时响应并触发报警机制,保障馆内的安全。
所有采集的数据通过主控芯片STM32F103RCT6进行处理,传感器的数据通过WIFI模块(ESP8266)被上传到华为云IoT平台,进行远程存储和管理。这一部分的设计思路是通过云端的集中式存储,方便数据的后期分析与统计,确保数据的可靠性和长期存储需求。
系统的本地显示部分通过10寸LCD屏幕实时展示馆内的环境数据,方便馆内工作人员直观查看当前的环境状况,并及时发现异常情况。可视化大屏通过Qt在Windows平台开发,能够显示包括环境参数、警报信息以及实时视频监控画面等内容。通过这种方式,工作人员不仅可以在现场通过LCD显示屏进行操作,还可以在远程的办公室内通过大屏监控整个馆内的运行状况。
在安全监控方面,设计了支持RTMP协议的监控摄像头,能够将实时视频流推送至NGINX服务器,再通过华为云ECS服务器进行存储和管理。通过RTMP推流技术,系统能够实时展示陈列馆内的监控画面,帮助工作人员随时了解馆内动态。此外,结合深度学习算法,系统可以对视频数据进行人体识别,统计馆内人流量,并将统计结果呈现在可视化大屏上。这一设计不仅能实现对文物的安全监控,还能帮助工作人员优化馆内的人员流动管理。
为了确保系统的稳定性,所有硬件模块如传感器、显示屏和监控设备都通过220V市电进行供电,同时考虑到电力供应的可靠性,电源管理模块采用了稳定的供电设计。设备运行时,主控芯片与传感器之间的通信通过稳定的接口和协议进行,保证了数据采集的准确性和实时性。
本项目的设计思路是通过物联网技术结合环境监测、视频监控、数据云存储和智能化管理,实现陈列馆环境的全方位监控与管理,提升文物保护效果和馆内运营效率,同时确保馆内的安全与紧急事件的快速响应。
1.5 系统功能总结
功能模块 | 功能描述 |
---|---|
温湿度检测 | 实时监测陈列馆内的环境温度和湿度,确保文物保存的适宜条件。 |
光照强度检测 | 实时检测陈列馆内的光照强度,防止强光对文物造成损害。 |
烟雾与火焰检测 | 通过烟雾传感器(MQ2)和火焰传感器检测火灾隐患,一旦发现异常即触发报警,保障文物与馆内安全。 |
本地数据显示 | 通过LCD显示屏实时显示温湿度、光照强度等环境参数,方便馆内工作人员查看当前环境状态。 |
数据上传与云端存储 | 使用WIFI模块(ESP8266)和MQTT协议,将环境数据上传至华为云IoT平台进行存储,便于数据管理与分析。 |
可视化大屏显示 | 在办公室内通过Qt开发的可视化大屏展示环境参数、实时监控画面及预警信息,帮助工作人员远程监控管理。 |
环境参数预警 | 设定阈值,当温湿度或光照强度超过/低于设定范围时,系统将在可视化大屏上进行警示,提醒工作人员采取措施。 |
视频监控与实时推流 | 使用支持RTMP协议的监控摄像头,通过NGINX服务器将视频流推送至云端,并在可视化大屏上实时显示监控画面。 |
人流量监控与统计 | 基于深度学习算法对视频进行人体识别,实时统计馆内人流量,并在可视化大屏上显示当前人流量和每日统计数据。 |
火灾警报与应急响应 | 监测到火灾时自动触发警报并向云端上传报警信息,提醒工作人员采取紧急措施,避免灾难发生。 |
稳定供电支持 | 系统通过220V市电供电,保证设备稳定运行,确保长时间的监控需求。 |
1.6 开发工具的选择
【1】设备端开发
STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。
开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。
【2】上位机开发
上位机的开发选择Qt框架,编程语言采用C++;Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt能轻松创建具有原生C++性能的连接设备、用户界面(UI)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。
1.8 模块的技术详情介绍
【1】ESP8266模块
ESP8266是一款低功耗、低成本的WiFi模块,广泛应用于物联网(IoT)项目中。它集成了WiFi无线通信功能,可以实现设备与互联网的无线连接,具有非常高的性价比。ESP8266模块的设计旨在简化无线网络的配置和连接过程,特别适合嵌入式系统和智能硬件应用。
ESP8266模块基于Tensilica Xtensa架构的32位微处理器,并集成了WiFi协议栈、网络功能以及各种控制和通信接口,能够支持WiFi标准的IEEE 802.11 b/g/n协议。它内置有处理器、存储器、WiFi射频模块以及网络协议栈,支持通过AT命令或通过编程来控制和操作。用户可以通过编程将其嵌入到各种应用中,作为通信桥梁在微控制器和互联网之间进行数据传输。
该模块通常包括多个版本,常见的有ESP-01、ESP-12E等,它们的差异主要体现在引脚数目、外部存储、天线设计等方面。ESP8266具有较强的处理能力,能够支持复杂的通信协议,并能够独立执行部分任务,无需外部微处理器的支持。它的主要功能是将嵌入式设备连接到WiFi网络,通过HTTP、MQTT、WebSocket等协议与云端进行数据交互和控制。
在实际应用中,ESP8266模块通过串口(UART)与其他硬件设备进行通信,且其支持AT命令集,通过这些命令可以配置WiFi参数、控制网络连接、发送和接收数据。对于开发者来说,它的开发环境支持Arduino IDE、NodeMCU、PlatformIO等,极大地简化了开发流程。使用这些开发环境,开发者可以通过编程实现更复杂的功能,如数据采集、远程控制、智能家居应用等。
ESP8266的低功耗特点使得它特别适合于物联网设备的应用。模块的工作电压范围为3.3V,虽然其本身的功耗较低,但在深度休眠模式下,功耗可以进一步降低到微安级别,从而延长电池寿命。这使得ESP8266在需要长期运行的无线传感器网络和便携式设备中具有广泛的应用。
在物联网应用中,ESP8266常常用于实现设备与互联网的互联互通,能够通过WiFi协议将数据上传到云平台,如华为云、AWS、ThingSpeak等,实现数据存储、远程监控、控制和分析。在智能家居、智能农业、环境监控等领域,ESP8266作为通信模块发挥着至关重要的作用。
ESP8266凭借其低成本、高集成度、强大的WiFi连接功能以及良好的开发支持,成为了物联网领域中最受欢迎的无线通信模块之一,尤其适用于需要无线连接的嵌入式设备和智能硬件项目。
【2】MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种轻量级、发布/订阅模式的消息传输协议,专为低带宽、不可靠网络环境设计。它最早由IBM提出,现已成为物联网(IoT)通信的重要协议之一。由于其高效、低功耗和实时性等特点,MQTT在智能家居、工业自动化、远程监控和车联网等领域得到了广泛应用。
MQTT的工作原理基于发布/订阅模型。这种模型有别于传统的客户端-服务器模型,通信方不需要直接建立连接。MQTT由三个核心组件构成:客户端、代理(Broker)和主题(Topic)。客户端可以作为消息的发布者或订阅者,消息通过代理进行路由。代理是一个中间服务端,用于接收和分发来自不同客户端的消息。发布者发送消息到一个特定的主题上,代理负责将这些消息分发给所有订阅了该主题的客户端。通过这种解耦的架构设计,客户端之间可以实现松耦合的通信,降低了复杂性和依赖性。
在MQTT协议中,消息被分为不同的主题(Topic),例如“home/sensor/temperature”可以用来代表温度传感器数据。客户端可以订阅这个主题,当发布者发送新的数据到该主题时,所有订阅该主题的客户端都会收到更新信息。这种灵活的主题结构和层次化的命名规则,使得MQTT在复杂场景下也能快速组织和管理消息流。
MQTT协议支持三种服务质量(QoS)等级,分别为“至多一次”(QoS 0)、“至少一次”(QoS 1)和“仅一次”(QoS 2)。QoS 0表示消息传输尽力而为,可能会丢失或重复;QoS 1确保消息至少送达一次,但可能会有重复;QoS 2则确保消息恰好传输一次,保证消息的严格可靠性。这种设计使MQTT能够适应不同的应用场景,用户可以根据应用需求选择合适的QoS级别。
为了保证通信的安全性,MQTT支持用户名和密码验证,代理可以对连接进行身份认证。此外,许多实现中还支持TLS/SSL加密通信,确保数据在传输过程中不会被窃取或篡改。用户也可以使用不同的认证方式来增强系统的安全性,适应物联网应用中对安全性的高需求。
MQTT非常注重轻量化和低功耗。它的报文头非常小,通信开销很低,这使其特别适合在资源受限的设备或不稳定的网络环境中使用。MQTT支持“保持连接”和“遗嘱消息”功能,客户端可以在连接断开时自动向代理发送遗嘱消息,通知其他客户端连接状态的变化。这种特性有助于提高网络的健壮性和系统的可用性。
MQTT的典型使用场景包括物联网设备数据采集、实时监控、消息推送和控制命令的发布。比如在智能家居中,传感器可以发布环境数据,如温湿度、烟雾浓度等,控制设备根据收到的消息作出响应,实现自动化操作。在工业场景中,MQTT可以帮助收集和管理大规模设备的运行状态,实现集中化和高效的设备监控。
MQTT协议凭借其低功耗、高效能、实时性强等优势,已成为物联网通信的主要协议之一。它的发布/订阅模式简化了设备之间的通信,使其特别适合多对多、低延迟、高可靠性的数据传输场景。MQTT易于使用、拓展性强,为开发者提供了灵活的解决方案来构建各种物联网应用。
二、搭建视频监控流媒体服务器
2.1 购买云服务器
如果之前没有使用过华为云的ECS服务器,可以先申请试用1个月,了解服务器的基本使用然后再购买,不得不说提供这个试用服务还是非常不错。
产品试用领取地址: https://activity.huaweicloud.com/free_test/index.html
每天9:30开抢,每天限量100份,这个页面不仅有云服务器可以领取试用,还有云数据库、沙盒等其他产品。
我这里领取了 2核4G S6云服务器
,这个服务器是配套华为自研25GE智能高速网卡,适用于网站和Web应用等中轻载企业应用。
选择配置的时候发现S6规格的已经没有了,来晚了。
S6规格没有了,就选择了S3,2核,4GB的配置结算。
页面向下翻,下面选择系统预装的系统,我这里选择ubuntu 20.04,安装NGINX,来搭建流媒体服务器。
页面继续下翻,设置云服务器名称,设置系统的root密码。
接着就可以继续去支付了。
购买后等待一段时间,系统资源就即可分配完成。
2.2 登录云服务器
云服务器的管理控制台从这里进入: https://www.huaweicloud.com/product/ecs.html
在官网主页,点击产品,找到计算选项,就可以看到弹性云服务器ECS,点击进去就可以看到管理控制台的选项。
在弹性云服务器
的选项页面可以看到刚才购买的云服务器,如果点击进去提示该区域没有可用的服务器,说明区域选择的不对,在下面截图红色框框的位置可以看到可用的区域切换按钮,切换之后就行了。
点击服务器右边的更多
,可以对服务器重装系统、切换操作系统、关机、开机、重启、重置密码等操作。
接下来先点击登录,了解一下登录的流程,看看系统进去的效果。
云服务器支持SSH协议远程登录,可以在浏览器上直接使用CloudShell方式或者VNC方式登录,如果本身你自己也是使用Linux系统,可以在Linux系统里通过ssh命令直接登录,如果是在windows下可以使用SecureCRT登录。
其他登录方式。
最方便的登录方式,直接在控制台使用VNC在浏览器里登录,点击立即登录
。
根据提示输入用户名,密码后,按下回车键即可登录。
用户名直接输入root
,密码就是刚才配置云服务器时,填入的root密码。
注意: Linux下输入密码默认都是隐藏的,也就是在键盘上输入密码界面上是不会有反应的,自己按照正确的密码输入即可。
用户名、密码输入正确后,登录成功。
可以点击全屏模式,更好的操作。
2.3 使用CloudShell登录云服务器
在页面上直接点击CloudShell登录
按钮。CloudShell方式比VNC方式方便、流畅多了,也支持命令的复制粘贴。
输入密码点击连接。
登录成功进入终端。
2.4 使用SecureCRT登录云服务器
上面演示了两种登录方式,都是直接在浏览器里登录,这种两种方式比较来看,VNC方式效率最低,CloudShell
相对来说要方便很多。一般我自己正常开发时,都是使用第三方工具来登录的,如果本身自己开发环境的电脑就是Linux,MAC等,可以直接使用ssh命令登录,这种方式操作流畅方便。如果在windows下,可以使用第三方软件登录。
我现在使用的系统是win10,在windows系统下有很多远程终端软件支持SSH登录到Linux云服务器,我当前采用的使用SecureCRT 6.5
来作为登录终端,登录云服务器。
注意: SecureCRT 6.5
登录高版本Linux系统会出现Key exchange failed
问题,导致登录失败,比如: 登录ubuntu 20.04 系统。 出现这种问题需要对系统ssh配置文件进行添加配置。
添加配置的流程:
命令行输入:
vim /etc/ssh/sshd_config
在文件最后添加:
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
保存退出。
重启ssh服务
service ssh restart
如果不想这么麻烦的去修改配置文件,那么最简单的办法就是: 切换操作系统,换一个低版本的,比如:ubuntu18.04 即可。
在云服务器的控制台,找到自己的服务器,然后选择切换操作系统。
根据界面上的引导流程,切换即可。更换新的系统需要1~4分钟时间,稍微等待一下即可。
如果要使用远程SSH协议方式登录云服务器,需要具备以下几个前提条件。
[1]弹性云服务器状态为“运行中”。
[2]弹性云服务器已经绑定弹性公网IP,绑定方式请参见绑定弹性公网IP。
[3]所在安全组入方向已开放22端口,配置方式请参见配置安全组规则。
[4]使用的登录工具(如PuTTY,SecureCRT`)与待登录的弹性云服务器之间网络连通。例如,默认的22端口没有被防火墙屏蔽。
但是这些配置不用担心,在购买服务器后,根据引导一套走完,上面的这些配置都已经默认配置好了,不用自己再去单独配置。
系统切换成功后,打开SecureCRT 6.5
软件,进行登录。SecureCRT 6.5
整体而言还是挺好用的。
如果自己没有`SecureCRT
,自己下载一个即可。当然,不一定非要使用SecureCRT
,其他还有很多SSH远程登录工具,喜欢哪个使用哪个。
下面介绍`SecureCRT
登录的流程。
选择新建会话。
选择SSH2协议。
主机名就填服务器的公网IP地址,端口号默认是22,用户名填root。
自己云服务器的公网IP地址,在控制台可以看到。
软件点击下一步之后,可以填充描述信息,备注这个链接是干什么的。
选择刚才新建的协议端口点击连接。
云服务器连接上之后,软件界面会弹出对话框填充用户名、密码。
登录成功的效果如下。
软件可以配置一些选项,让界面符合Linux终端配色,可以修改字体大小、字体编码等等。
配置后的效果。
2.5 安装NFS服务器
为了方便向服务器上拷贝文件,可以采用NFS服务器、或者FTP服务器 这些方式。 我本地有一台ubuntu 18.04 系统笔记本,我这里采用NFS方式拷贝文件上去。
(1)安装NFS服务器
root@ecs-348470:~# sudo apt-get install nfs-kernel-server
(2)创建一个work目录方便当做共享目录使用
root@ecs-348470:~# mkdir work
(3)编写NFS配置文件
NFS 服务的配置文件为/etc/exports,如果系统没有默认值,这个文件就不一定会存在,可以使用 vim 手动建立,然后在文件里面写入配置内容。
/home/work *(rw,no_root_squash,sync,no_subtree_check,insecure)
配置文件里参数的含义:
(4)NFS服务器相关指令
/etc/init.d/nfs-kernel-server start #启动 NFS 服务
ufw disable #关闭防火墙
/etc/init.d/nfs-kernel-server restart #重启NFS服务
exportfs -arv #共享路径生效
(5)本地客户机挂载服务器的目录
wbyq@wbyq:~$ sudo mount -t nfs -o nolock 122.112.212.171:/home/work /home/wbyq/mnt/
(6)设置华为云服务器的安全策略
需要把华为云服务器的端口号开放出来,不然其他客户端是无法访问服务器的。
我这里比较粗暴直接,直接将所有端口号,所有IP地址都开放出来了。
(7)本地客户机挂载服务器测试
挂载指令:
sudo mount -t nfs -o nolock 122.112.212.171:/home/work /home/wbyq/mnt/
2.6 安装NGINX(配置RTMP服务)
(1)下载编译时需要依赖的一些工具
root@ecs-348470:~# sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
(2)下载NGINX编译需要的软件包
root@ecs-348470:~# mkdir nginx
root@ecs-348470:~# cd nginx/
root@ecs-348470:~# wget http://nginx.org/download/nginx-1.10.3.tar.gz
root@ecs-348470:~# wget http://zlib.net/zlib-1.2.11.tar.gz
root@ecs-348470:~# wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz
root@ecs-348470:~# wget https://www.openssl.org/source/openssl-1.0.2k.tar.gz
root@ecs-348470:~# wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
(3)下载后的文件全部解压
root@ecs-348470:~# tar xvf openssl-1.0.2k.tar.gz
root@ecs-348470:~# tar xvf nginx-rtmp-module-master.tar.gz
root@ecs-348470:~# tar xvf nginx-1.8.1.tar.gz
root@ecs-348470:~# tar xvf pcre-8.40.tar.gz
root@ecs-348470:~# tar xvf zlib-1.2.11.tar.gz
(4)配置NGINX源码,生成Makefile文件
root@ecs-348470:~# cd nginx-1.8.1/
root@ecs-348470:~# ./configure --prefix=/usr/local/nginx --with-debug --with-pcre=../pcre-8.40 --with-zlib=../zlib-1.2.11 --with-openssl=../openssl-1.0.2k --add-module=../nginx-rtmp-module-master
执行完上一步之后,打开objs/Makefile文件,找到-Werror选项并删除。
(5)编译并安装NGINX
root@ecs-348470:~/nginx/nginx-1.8.1# make && make install
安装之后NGINX的配置文件存放路径:
/usr/local/nginx/nginx:主程序
(6)查看NGINX的版本号
root@ecs-348470:/usr/local/nginx/sbin# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.8.1
(5)在配置文件里加入RTMP服务器的配置
root@ecs-348470:~# vim /usr/local/nginx/conf/nginx.conf
打开文件后,在文件最后加入以下配置:
rtmp {
server {
listen 8888;
application live {
live on;
record all;
record_unique on;
record_path "./video"; #视频缓存的路径
record_suffix -%Y-%m-%d-%H_%M_%S.flv;
}
}
}
这样配置之后,服务器收到RTMP流会在NGINX的当前目录下,创建一个video目录用来缓存视频。
客户端向服务器推流之后,服务器就会缓存视频到设置的目录。
(5)检查配置文件是否正确
root@ecs-348470:/usr/local/nginx/sbin# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
(6)NGINX常用的3个命令
sudo service nginx start
sudo service nginx stop
sudo service nginx restart
(7)启动NGINX服务器
sudo service nginx start
2.7 摄像头推流音视频到服务器
为了模拟摄像头实时监控推流,我这使用QT+FFMPEG编写了一个小软件,在windows下运行,推流本地笔记本电脑的数据到服务器。软件运行之后,将本地音频、视频编码之后通过RTMP协议推流到NGINX服务器。
软件可以去网盘里下载:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
软件运行效果:
推流工具运行过程中效果。
2.8 编写本地RTMP流播放器
在上面通过推流客户端模拟摄像头,已经将本地的摄像头数据实时推流到服务器了,那么还差一个播放器,为了方便能够在任何有网的地方实时查看摄像头的音频和图像,还需要编写一个RTMP流媒体播放器。
我这里的播放器内核是采用libvlc开发的,使用QT作为GUI框架,开发了一个流媒体播放器,可以实时拉取服务器上的流数据,并且还支持回放。因为服务器上的NGINX配置了自动保存的参数,可以将推上去的流按时间段保存下来。
软件可以去网盘里下载:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
输入服务器地址之后就可以拉取流进行播放。
点击获取回放列表,可以查看服务器上保存的历史视频回放播放。
2.9 配置监控摄像头
第一次使用摄像头,先使用网线将摄像头连接到家里路由器上,然后登录摄像头管理页面配置摄像头。
在摄像头上面有一个码,扫描之后就能看到使用办法。里面有一个软件下载下来,可以搜索摄像头IP。
详细过程看这里:https://www.showdoc.com.cn/sqIPC/7929920934644196
设置摄像头动态获取IP(非常重要)
摄像头用户名是admin 密码是12345
登录成功。
设置参数:
设置摄像头连接的WIFI:
推流地址:rtmp://111.160.79.93/live/video158
设置WIFI联网之后,摄像头就会自动去连接指定的WIFI,完成推流。
三、部署华为云物联网平台
华为云官网: https://www.huaweicloud.com/
打开官网,搜索物联网,就能快速找到 设备接入IoTDA
。
3.1 物联网平台介绍
华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助我们快速构筑物联网解决方案。
使用物联网平台构建一个完整的物联网解决方案主要包括3部分:物联网平台、业务应用和设备。
物联网平台作为连接业务应用和设备的中间层,屏蔽了各种复杂的设备接口,实现设备的快速接入;同时提供强大的开放能力,支撑行业用户构建各种物联网解决方案。
设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台,并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台,平台也可以将控制命令下发给设备。
业务应用通过调用物联网平台提供的API,实现设备数据采集、命令下发、设备管理等业务场景。
3.2 开通物联网服务
地址: https://www.huaweicloud.com/product/iothub.html
开通免费单元。
点击立即创建
。
正在创建标准版实例,需要等待片刻。
创建完成之后,点击详情。 可以看到标准版实例的设备接入端口和地址。
下面框起来的就是端口号
和域名
点击实例名称,可以查看当前免费单元
的配置情况。
开通之后,点击接入信息
,也能查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。
总结:
端口号: MQTT (1883)| MQTTS (8883)
接入地址: dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com
根据域名地址得到IP地址信息:
打开Windows电脑的命令行控制台终端,使用ping
命令。ping
一下即可。
Microsoft Windows [版本 10.0.19045.5011]
(c) Microsoft Corporation。保留所有权利。
C:\Users\Lenovo>ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com
正在 Ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
117.78.5.125 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 37ms,最长 = 37ms,平均 = 37ms
C:\Users\Lenovo>
MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口合适
。
3.3 创建产品
(1)创建产品
(2)填写产品信息
根据自己产品名字填写,下面的设备类型选择自定义类型。
(3)产品创建成功
创建完成之后点击查看详情。
(4)添加自定义模型
产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。
模型简单来说: 就是存放设备上传到云平台的数据。
你可以根据自己的产品进行创建。
比如:
烟雾可以叫 MQ2
温度可以叫 Temperature
湿度可以叫 humidity
火焰可以叫 flame
其他的传感器自己用单词简写命名即可。 这就是你的单片机设备端上传到服务器的数据名字。
先点击自定义模型。
再创建一个服务ID。
接着点击新增属性。
3.4 添加设备
产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。
(1)注册设备
(2)根据自己的设备填写
(3)保存设备信息
创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。
(4)设备创建完成
(5)设备详情
3.5 MQTT协议主题订阅与发布
(1)MQTT协议介绍
当前的设备是采用MQTT协议与华为云平台进行通信。
MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端,已经形成了初步的生态系统。
MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;MQTT协议是工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;所以,只要具备TCP协议栈的网络设备都可以使用MQTT协议。 本次设备采用的ESP8266就具备TCP协议栈,能够建立TCP连接,所以,配合STM32代码里封装的MQTT协议,就可以与华为云平台完成通信。
华为云的MQTT协议接入帮助文档在这里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
业务流程:
(2)华为云平台MQTT协议使用限制
描述 | 限制 |
---|---|
支持的MQTT协议版本 | 3.1.1 |
与标准MQTT协议的区别 | 支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msg |
MQTTS支持的安全等级 | 采用TCP通道基础 + TLS协议(最高TLSv1.3版本) |
单帐号每秒最大MQTT连接请求数 | 无限制 |
单个设备每分钟支持的最大MQTT连接数 | 1 |
单个MQTT连接每秒的吞吐量,即带宽,包含直连设备和网关 | 3KB/s |
MQTT单个发布消息最大长度,超过此大小的发布请求将被直接拒绝 | 1MB |
MQTT连接心跳时间建议值 | 心跳时间限定为30至1200秒,推荐设置为120秒 |
产品是否支持自定义Topic | 支持 |
消息发布与订阅 | 设备只能对自己的Topic进行消息发布与订阅 |
每个订阅请求的最大订阅数 | 无限制 |
(3)主题订阅格式
帮助文档地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
对于设备而言,一般会订阅平台下发消息给设备 这个主题。
设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。
如果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。
以当前设备为例,最终订阅主题的格式如下:
$oc/devices/{device_id}/sys/messages/down
最终的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down
(4)主题发布格式
对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。
这个操作称为:属性上报。
帮助文档地址:https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html
根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结如下:
发布的主题格式:
$oc/devices/{device_id}/sys/properties/report
最终的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report
发布主题时,需要上传数据,这个数据格式是JSON格式。
上传的JSON数据格式如下:
{
"services": [
{
"service_id": <填服务ID>,
"properties": {
"<填属性名称1>": <填属性值>,
"<填属性名称2>": <填属性值>,
..........
}
}
]
}
根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。
根据这个格式,组合一次上传的属性数据:
{"services": [{"service_id": "stm32","properties":{"你的字段名字1":30,"你的字段名字2":10,"你的字段名字3":1,"你的字段名字4":0}}]}
3.6 MQTT三元组
MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像我们平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。
接下来介绍,华为云平台的MQTT三元组参数如何得到。
(1)MQTT服务器地址
要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。
帮助文档地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home
MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。
根据上面的域名和端口号,得到下面的IP地址和端口号信息: 如果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。 (IP地址就是域名解析得到的)
华为云的MQTT服务器地址:117.78.5.125
华为云的MQTT端口号:1883
如何得到IP地址?如何域名转IP? 打开Windows的命令行输入以下命令。
ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
(2)生成MQTT三元组
华为云提供了一个在线工具,用来生成MQTT鉴权三元组: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。
下面是打开的页面:
填入设备的信息: (上面两行就是设备创建完成之后保存得到的)
直接得到三元组信息。
得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。
ClientId 663cb18871d845632a0912e7_dev1_0_0_2024050911
Username 663cb18871d845632a0912e7_dev1
Password 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237
3.7 模拟设备登录测试
经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。
MQTT软件下载地址【免费】: https://download.csdn.net/download/xiaolong1126626497/89928772
(1)填入登录信息
打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。
(2)打开网页查看
完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。
点击详情页面,可以看到上传的数据:
到此,云平台的部署已经完成,设备已经可以正常上传数据了。
(3)MQTT登录测试参数总结
MQTT服务器: 117.78.5.125
MQTT端口号: 183
//物联网服务器的设备信息
#define MQTT_ClientID "663cb18871d845632a0912e7_dev1_0_0_2024050911"
#define MQTT_UserName "663cb18871d845632a0912e7_dev1"
#define MQTT_PassWord "71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237"
//订阅与发布的主题
#define SET_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down" //订阅
#define POST_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report" //发布
发布的数据:
{"services": [{"service_id": "stm32","properties":{"你的字段名字1":30,"你的字段名字2":10,"你的字段名字3":1,"你的字段名字4":0}}]}
3.8 创建IAM账户
创建一个IAM账户,因为接下来开发上位机,需要使用云平台的API接口,这些接口都需要token进行鉴权。简单来说,就是身份的认证。 调用接口获取Token时,就需要填写IAM账号信息。所以,接下来演示一下过程。
地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users
【1】获取项目凭证 点击左上角用户名,选择下拉菜单里的我的凭证
项目凭证:
28add376c01e4a61ac8b621c714bf459
【2】创建IAM用户
鼠标放在左上角头像上,在下拉菜单里选择统一身份认证
。
点击左上角创建用户
。
创建成功:
【3】创建完成
用户信息如下:
主用户名 l19504562721
IAM用户 ds_abc
密码 DS12345678
3.9 获取影子数据
帮助文档:https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html
设备影子介绍:
设备影子是一个用于存储和检索设备当前状态信息的JSON文档。
每个设备有且只有一个设备影子,由设备ID唯一标识
设备影子仅保存最近一次设备的上报数据和预期数据
无论该设备是否在线,都可以通过该影子获取和设置设备的属性
简单来说:设备影子就是保存,设备最新上传的一次数据。
我们设计的软件里,如果想要获取设备的最新状态信息,就采用设备影子接口。
如果对接口不熟悉,可以先进行在线调试:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow
在线调试接口,可以请求影子接口,了解请求,与返回的数据格式。
调试完成看右下角的响应体,就是返回的影子数据。
设备影子接口返回的数据如下:
{
"device_id": "663cb18871d845632a0912e7_dev1",
"shadow": [
{
"service_id": "stm32",
"desired": {
"properties": null,
"event_time": null
},
"reported": {
"properties": {
"DHT11_T": 18,
"DHT11_H": 90,
"BH1750": 38,
"MQ135": 70
},
"event_time": "20240509T113448Z"
},
"version": 3
}
]
}
调试成功之后,可以得到访问影子数据的真实链接,接下来的代码开发中,就采用Qt写代码访问此链接,获取影子数据,完成上位机开发。
链接如下:
https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow
3.10 访问接口的代码实现
(1)配置 Qt 项目
在 Qt 项目的 .pro
文件中,加入对 libcurl
的支持:
QT += core
CONFIG += console
CONFIG -= app_bundle
INCLUDEPATH += /usr/include/curl # 根据你的系统设置 libcurl 的路径
LIBS += -lcurl # 链接 libcurl 库
SOURCES += main.cpp
(2)代码实现
main.cpp
文件中实现代码如下:
#include <QCoreApplication>
#include <curl/curl.h>
#include <QDebug>
#include <QString>
#include <QByteArray>
// 回调函数,处理libcurl下载数据
size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t totalSize = size * nmemb;
QByteArray *response = static_cast<QByteArray *>(userp);
response->append(static_cast<char *>(contents), totalSize);
return totalSize;
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 初始化libcurl
CURL *curl;
CURLcode res;
QByteArray responseData; // 用于存储响应数据
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
// 设置访问URL
const QString url = "https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow";
// 设置HTTP请求头
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer <Your_Access_Token>"); // 这里需要替换为你的实际 token
curl_easy_setopt(curl, CURLOPT_URL, url.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
// 发起GET请求
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
qDebug() << "Curl request failed:" << curl_easy_strerror(res);
} else {
qDebug() << "Response data:" << responseData;
}
// 清理
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
}
curl_global_cleanup();
return a.exec();
}
3.11 数据解析代码
在 Qt 中使用 CJSON (一个用于解析 JSON 数据的轻量级 C 库) 来解析返回的 JSON 数据。
(1)配置 Qt 项目
在 Qt 项目的 .pro
文件中,确保包括了 CJSON 的头文件,并链接 CJSON 的源代码。
QT += core
CONFIG += console
CONFIG -= app_bundle
SOURCES += main.cpp \
cJSON.c # 将 cJSON.c 文件添加到你的项目中
INCLUDEPATH += path/to/cjson/ # 添加 CJSON 头文件的路径
LIBS += -lcurl # 链接 libcurl 库
(2)解析 JSON 数据的完整代码
在 main.cpp
中,以下代码展示了如何解析你提供的 JSON 数据。
#include <QCoreApplication>
#include <curl/curl.h>
#include <QDebug>
#include <QString>
#include <QByteArray>
#include "cJSON.h"
// 回调函数,处理libcurl下载数据
size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t totalSize = size * nmemb;
QByteArray *response = static_cast<QByteArray *>(userp);
response->append(static_cast<char *>(contents), totalSize);
return totalSize;
}
// 解析 JSON 数据
void parseJson(const QByteArray &data) {
// 将 QByteArray 转换为 char*
const char* jsonData = data.constData();
// 解析 JSON
cJSON *root = cJSON_Parse(jsonData);
if (root == NULL) {
qDebug() << "Error parsing JSON.";
return;
}
// 解析 "device_id"
cJSON *deviceId = cJSON_GetObjectItemCaseSensitive(root, "device_id");
if (cJSON_IsString(deviceId) && (deviceId->valuestring != NULL)) {
qDebug() << "Device ID:" << deviceId->valuestring;
}
// 解析 "shadow" 数组
cJSON *shadow = cJSON_GetObjectItemCaseSensitive(root, "shadow");
if (cJSON_IsArray(shadow)) {
cJSON *shadowItem = NULL;
cJSON_ArrayForEach(shadowItem, shadow) {
// 解析每个 shadow 项目
cJSON *serviceId = cJSON_GetObjectItemCaseSensitive(shadowItem, "service_id");
if (cJSON_IsString(serviceId) && (serviceId->valuestring != NULL)) {
qDebug() << "Service ID:" << serviceId->valuestring;
}
// 解析 "reported" 对象
cJSON *reported = cJSON_GetObjectItemCaseSensitive(shadowItem, "reported");
if (cJSON_IsObject(reported)) {
// 解析 "properties" 对象
cJSON *properties = cJSON_GetObjectItemCaseSensitive(reported, "properties");
if (cJSON_IsObject(properties)) {
cJSON *data1 = cJSON_GetObjectItemCaseSensitive(properties, "data1");
if (cJSON_IsNumber(data1)) {
qDebug() << "data1:" << data1->valueint;
}
cJSON *data2 = cJSON_GetObjectItemCaseSensitive(properties, "data2");
if (cJSON_IsNumber(data2)) {
qDebug() << "data2:" << data2->valueint;
}
cJSON *data3 = cJSON_GetObjectItemCaseSensitive(properties, "data3");
if (cJSON_IsNumber(data3)) {
qDebug() << "data3:" << data3->valueint;
}
cJSON *data4 = cJSON_GetObjectItemCaseSensitive(properties, "data4");
if (cJSON_IsNumber(data4)) {
qDebug() << "data4:" << data4->valueint;
}
}
// 解析 "event_time"
cJSON *eventTime = cJSON_GetObjectItemCaseSensitive(reported, "event_time");
if (cJSON_IsString(eventTime) && (eventTime->valuestring != NULL)) {
qDebug() << "Event Time:" << eventTime->valuestring;
}
}
// 解析 version
cJSON *version = cJSON_GetObjectItemCaseSensitive(shadowItem, "version");
if (cJSON_IsNumber(version)) {
qDebug() << "Version:" << version->valueint;
}
}
}
// 释放 JSON 对象
cJSON_Delete(root);
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 模拟获取到的 JSON 数据
QByteArray jsonData = R"(
{
"device_id": "663cb18871d845632a0912e7_dev1",
"shadow": [
{
"service_id": "stm32",
"desired": {
"properties": null,
"event_time": null
},
"reported": {
"properties": {
"data1": 18,
"data2": 90,
"data3": 38,
"data4": 70
},
"event_time": "20240509T113448Z"
},
"version": 3
}
]
})";
// 调用解析函数
parseJson(jsonData);
return a.exec();
}
四、STM32设备端代码设计
模块代码可以在网盘里下载:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
STM32(传感器读取、数据处理、WiFi通信等)代码已经设计完成,在main.c
中初始化硬件模块,处理环境数据,并通过WiFi上传到云端的框架代码。
#include "stm32f1xx_hal.h"
#include "sht30.h" // 温湿度传感器库
#include "bh1750.h" // 光照传感器库
#include "mq2.h" // 烟雾传感器库
#include "wifi_module.h" // WiFi模块库 (ESP8266)
#include "lcd_display.h" // LCD显示屏库
#include "mqtt_client.h" // MQTT客户端库
// 定义传感器和模块实例
SHT30_HandleTypeDef hSHT30; // 温湿度传感器
BH1750_HandleTypeDef hBH1750; // 光照传感器
MQ2_HandleTypeDef hMQ2; // 烟雾传感器
ESP8266_HandleTypeDef hWiFi; // WiFi模块
MQTT_Client_HandleTypeDef hMQTTClient; // MQTT客户端
// 环境参数
float temperature = 0.0;
float humidity = 0.0;
uint16_t light_intensity = 0;
uint16_t smoke_level = 0;
// 传感器阈值
#define TEMPERATURE_THRESHOLD_HIGH 30.0f
#define TEMPERATURE_THRESHOLD_LOW 18.0f
#define HUMIDITY_THRESHOLD_HIGH 70.0f
#define HUMIDITY_THRESHOLD_LOW 40.0f
#define LIGHT_INTENSITY_THRESHOLD 300
// 外设初始化函数
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_I2C1_Init(void);
static void MX_SPI1_Init(void);
static void MX_WIFI_Init(void);
static void MX_LCD_Init(void);
// 读取传感器数据
void Read_Sensors(void) {
// 获取温湿度数据
if (SHT30_Read(&hSHT30, &temperature, &humidity) != HAL_OK) {
// 处理错误
}
// 获取光照强度数据
if (BH1750_Read(&hBH1750, &light_intensity) != HAL_OK) {
// 处理错误
}
// 获取烟雾传感器数据
if (MQ2_Read(&hMQ2, &smoke_level) != HAL_OK) {
// 处理错误
}
}
// 处理环境数据并进行显示及上传
void Process_And_Display(void) {
// 显示当前环境参数到LCD
LCD_DisplayTemperature(temperature);
LCD_DisplayHumidity(humidity);
LCD_DisplayLightIntensity(light_intensity);
LCD_DisplaySmokeLevel(smoke_level);
// 上传数据到云端
char payload[256];
snprintf(payload, sizeof(payload), "{\"temperature\": %.2f, \"humidity\": %.2f, \"light\": %d, \"smoke\": %d}",
temperature, humidity, light_intensity, smoke_level);
if (MQTT_Publish(&hMQTTClient, "env_data/topic", payload) != HAL_OK) {
// 处理MQTT发布错误
}
// 环境预警
if (temperature > TEMPERATURE_THRESHOLD_HIGH || temperature < TEMPERATURE_THRESHOLD_LOW) {
MQTT_Publish(&hMQTTClient, "alert/topic", "Temperature out of range!");
}
if (humidity > HUMIDITY_THRESHOLD_HIGH || humidity < HUMIDITY_THRESHOLD_LOW) {
MQTT_Publish(&hMQTTClient, "alert/topic", "Humidity out of range!");
}
if (light_intensity > LIGHT_INTENSITY_THRESHOLD) {
MQTT_Publish(&hMQTTClient, "alert/topic", "Light intensity too high!");
}
}
// 主程序入口
int main(void) {
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化外设
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_I2C1_Init(); // 初始化I2C
MX_SPI1_Init(); // 初始化SPI
MX_WIFI_Init(); // 初始化WiFi模块
MX_LCD_Init(); // 初始化LCD显示屏
// 初始化MQTT客户端
MQTT_Init(&hMQTTClient);
// 连接WiFi
if (ESP8266_Connect(&hWiFi, "your_ssid", "your_password") != HAL_OK) {
// 处理WiFi连接失败
}
// 连接MQTT服务器
if (MQTT_Connect(&hMQTTClient, "mqtt_server_address", 1883, "username", "password") != HAL_OK) {
// 处理MQTT连接失败
}
// 主循环
while (1) {
// 定时读取传感器数据
Read_Sensors();
// 处理数据并显示/上传
Process_And_Display();
}
}
五、上位机开发
为了方便查看设备上传的数据,接下来利用Qt开发一款Android手机APP 和 Windows上位机。
使用华为云平台提供的API接口获取设备上传的数据,进行可视化显示,以及远程控制设备。
5.1 Qt开发环境安装
Qt的中文官网: https://www.qt.io/zh-cn/
QT5.12.6的下载地址:https://download.qt.io/archive/qt/5.12/5.12.6
打开下载链接后选择下面的版本进行下载:
如果下载不了,可以在网盘里找到安装包下载: https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
软件安装时断网安装,否则会提示输入账户。
安装的时候,第一个复选框里的编译器可以全选,直接点击下一步继续安装。
选择编译器: (一定要看清楚了)
前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。
【1】新建工程
【2】设置项目的名称。
【3】选择编译系统
【4】选择默认继承的类
【5】选择编译器
【6】点击完成
【7】工程创建完成
5.3 切换编译器
在左下角是可以切换编译器的。 可以选择用什么样的编译器编译程序。
目前新建工程的时候选择了2种编译器。 一种是mingw32
这个编译Windows下运行的程序。 一种是Android
编译器,可以生成Android
手机APP。
不过要注意:Android的编译器需要配置一些环境才可以正常使用,这个大家可以看下面的教程配置一下就行了。
Android环境搭建的博客链接: https://blog.csdn.net/xiaolong1126626497/article/details/117254453
windows的编译器就没有这么麻烦,安装好Qt就可以编译使用。
下面我这里就选择的 mingw32
这个编译器,编译Windows下运行的程序。
5.4 编译测试功能
创建完毕之后,编译测试一下功能是否OK。
点击左下角的绿色三角形按钮
。
正常运行就可以看到弹出一个白色的框框。这就表示工程环境没有问题了。 接下来就可以放心的设计界面了。
5.5 设计UI界面与工程配置
【1】打开UI文件
打开默认的界面如下:
【2】开始设计界面
根据自己需求设计界面。
5.5 编译Windows上位机
点击软件左下角的绿色三角形按钮进行编译运行。
5.6 配置Android环境
如果想编译Android手机APP,必须要先自己配置好自己的Android环境。(搭建环境的过程可以自行百度搜索学习)
然后才可以进行下面的步骤。
【1】选择Android编译器
选择编译器。
切换编译器。
【2】创建Android配置文件
创建完成。
【3】配置Android图标与名称
【3】编译Android上位机
Qt本身是跨平台的,直接选择Android的编译器,就可以将程序编译到Android平台。
然后点击构建。
成功之后,在目录下可以看到生成的apk
文件,也就是Android手机的安装包,电脑端使用QQ
发送给手机QQ,手机登录QQ接收,就能直接安装。
生成的apk
的目录在哪里呢? 编译完成之后,在控制台会输出APK文件的路径。
知道目录在哪里之后,在Windows的文件资源管理器里,找到路径,具体看下图,找到生成的apk文件。
-- File: D:/QtProject/build-265_AgritechIoTManager-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk
六、总结
综上所述,基于物联网技术设计的陈列馆监控系统在环境监测、安全防护和数据管理等方面提供了全面的解决方案。通过多种传感器模块实时采集温湿度、光照强度、烟雾和火焰数据,并结合视频监控与人流量统计,系统能够有效保障陈列馆内文物的安全和环境的稳定。同时,系统还通过WIFI模块与云端实现数据同步和远程监控,便于工作人员随时掌握馆内的实时情况,及时响应可能发生的异常事件。
该系统不仅具备高效的本地数据显示功能,还通过可视化大屏展现环境监测信息、预警提示和视频监控,进一步增强了馆内管理的智能化和便捷性。利用深度学习技术进行人流量监控,为管理人员提供了更精准的数据支持,有助于优化陈列馆的运营效率。
通过合理的硬件选型和智能化软件设计,本系统展示了物联网技术在文化遗产保护领域的巨大潜力。未来,随着技术的不断发展,系统的功能和应用场景也有望得到进一步扩展和优化,为更多公共设施和文化场馆的智能化管理提供借鉴和支持。
- 点赞
- 收藏
- 关注作者
评论(0)