简介:本资源是一套面向Java开发者与农业信息化从业者的智慧农业物联网平台设计源码,聚焦农业生产环境的智能感知与可视化管理,解决传统农业中气象监测、水肥调控、土壤墒情评估及远程视频巡检等核心痛点。压缩包共21个文件,含12个Java核心业务类(覆盖设备接入、数据解析、告警逻辑与Web接口)、3个Markdown文档(含项目说明、部署指南与功能概览)、2个.gitignore配置文件,以及pom.xml、mvnw.cmd、application.properties等关键构建与配置文件,整体仅99KB,轻量易读。已有494人学习下载,适合具备Java Web基础的开发者快速理解物联网平台分层架构与农业场景落地逻辑。读者可直接基于该源码学习多源异构设备(气象站、水肥机、土壤传感器、IPC)的数据接入规范、Spring Boot微服务模块划分方式,以及前后端交互与状态可视化的设计思路,为二次开发或课程实践提供完整技术锚点。 做智慧农业物联网平台这两年,最大的感受不是“把设备连上网”这件事本身有多难,而是把农业现场一堆非标设备、各家各户封闭的传感器协议、时好时坏的田间网络,整合成一套稳定可靠、还能被不会写代码的人日常使用的系统,才是真正的硬骨头。
今天拿出来细聊的这套基于Java的智慧农业物联网平台,核心围绕气象站、水肥一体机、墒情监控、视频监控四个场景来搭。整套源码以Spring Boot为主框架,设备接入层用Netty做TCP/UDP长连接服务,消息通信走MQTT,业务数据落MySQL,时序类监测数据单独做分区表处理,前端配套Web管理后台和可视化大屏。它解决的典型问题很明确:基地里分散的传感器和设备,怎么统一采集、统一控制、统一展示,出了异常怎么第一时间告警,而不是每天靠管理员去田里转一圈看设备正不正常。
这篇文章主要面向正在做农业物联网项目、或者准备从零搭一套设备接入平台的朋友。不管你是刚接触物联网的Java开发,还是已经在田间地头调试过几轮设备的实施人员,希望这套源码里沉淀下来的设计思路和踩坑记录,能帮你少走一段弯路。我会从整体设计、四个核心功能模块、关键源码实现、现场部署问题排查这四个维度逐个展开。
1. 平台整体设计与技术选型思路
1.1 农业物联网项目的特殊性决定了架构走向
农业物联网和工厂里的工业物联网有很多相似之处,但又有几个非常突出的差异,这些差异直接决定了架构设计的方向。
第一,设备种类多、协议杂、标准化程度低。一个基地可能同时有气象站、土壤墒情传感器、水肥机、水泵、摄像头、卷帘机,这些设备来自不同厂商,有的走Modbus RTU,有的走私有TCP协议,有的只提供485串口,有的干脆是4G DTU透传。如果每个设备都单独写一套接口,项目很快会失控,所以必须抽象出一套通用的设备接入框架,把协议解析和业务逻辑解耦。
第二,网络环境差、不稳定。农业园区远离城市核心机房,通常靠光纤到园区、4G/5G路由器或者太阳能供电的网关来联网。设备频繁断线、IP地址变化、数据上报延迟是家常便饭,所以平台必须设计断线重连、指令重发确认、数据缓存补传机制。
第三,数据量不大但需要持续记录。单台传感器一般5秒到5分钟上报一次,量级和互联网高并发没法比,但积累一两年之后,十几台设备、几十个测点的数据总量也是千万级起步。时序数据要单独考虑存储策略,不能一股脑全塞进一张大表。
第四,操作者是农民或基地管理员,不是专业运维。平台要足够简单,告警要足够直观,设备状态要一眼看得懂。很多农业项目最后死在设备出了小故障没人会处理,而不是死在功能不齐全。
1.2 为什么选Java技术栈,而不是Python或者Node.js
我在项目早期也纠结过要不要直接用Python写协议解析脚本,毕竟像Modbus这种串口协议用Python的pymodbus库写起来非常快。但后来评估下来,还是选了Java作为主语言,原因很实在。
Spring Boot生态成熟,做后台管理系统、权限体系、定时任务、接口文档这些常规功能,效率非常高。农业物联网平台不只是设备接入,还要有用户体系、农场管理、设备管理、告警配置、报表统计,这些业务功能用Java做比用Python做更顺手,尤其是后期要招人维护的时候,Java开发者的资源明显更多。
设备接入层用Netty,这是Java生态里做长连接服务非常成熟的高性能网络框架。农业设备大量使用TCP透传方式上云,设备主动建立连接之后长时间保持,数据不定时上报,Netty对连接管理和粘包拆包的处理能力很强,Netty还天然支持断线重连、心跳检测,这些正是设备接入层最需要的。
MQTT通信选型上,我用的是EMQX Broker,Java客户端用Eclipse Paho。设备端通过MQTT上报数据、接收控制指令,服务端也通过MQTT做内部模块间通信。其实如果只是几十台设备,用Netty直接处理也完全够,但引入MQTT之后,将来接第三方设备、做消息留存、对接其他数据系统会省事很多。
1.3 系统整体架构与数据流向
这套平台的逻辑架构可以分为五层:
设备感知层:气象站、墒情传感器、水肥一体机、摄像头、DTU网关等。
接入通信层:Netty TCP服务负责处理设备主动上报的透传数据,EMQX负责MQTT消息流转,GB28181/RTSP负责视频流接入。
协议解析层:把设备原始报文解析成统一的数据模型,包括校验位校验、字节序转换、数据清洗和格式标准化。
业务处理层:包括设备管理、告警引擎、灌溉策略、视频服务、权限管理、报表统计等核心业务逻辑。
应用展示层:Web管理后台、可视化大屏、移动端H5,为管理人员提供监控、操作和数据查看入口。
数据流向图上来看,传感器数据从设备侧发出之后,经过网关或者DTU进入平台接入层,Netty或者EMQX收到原始报文后交给协议解析模块,解析得到一个统一的结构化数据对象,同时写入原始报文日志和解析后的实时数据表。实时数据经过规则引擎判断是否触发告警条件,如果触发就生成告警记录并发送通知。前端界面从接口层读取数据做可视化展示,大屏通过WebSocket接收实时推送。
这套架构的好处是每一层职责单一,设备接入层不关心业务逻辑,业务层也不关心设备具体协议。后续接入新的传感器型号,只需要新增一个协议解析器,不需要改其他模块。
2. 四大核心功能模块的拆解与实现
2.1 气象站接入:Modbus协议解析与数据清洗
农业气象站通常集成了空气温度、空气湿度、大气压力、风速、风向、雨量这几个传感器,有些还会加光照强度和紫外线强度。大多数中小型气象站采用RS485总线输出Modbus RTU协议,或者通过DTU将485信号转成TCP上云。
Modbus RTU报文结构比较简单:设备地址、功能码、寄存器起始地址、寄存器数量、CRC16校验。以读取气象站数据为例,主站发送的请求帧大致是:
01 03 00 00 00 06 C5 C8这是向地址为01的设备,发送功能码03(读取保持寄存器),从寄存器地址0x0000开始连续读6个寄存器。返回的帧大约是:
01 03 0C 02 5B 00 D9 01 80 00 2A 00 00 01 2C ...其中0x0C表示后面数据长度是12个字节,对应6个寄存器。每个寄存器占用两个字节,需要根据传感器厂商的数据手册换算成实际物理量。常见的换算方式是乘以一个系数,比如空气温度寄存器值是0x025B,十进制是603,如果温度分辨率为0.1,则实际温度是60.3摄氏度。但显然正常环境不可能有60度,这就说明数据异常,可能是读取错误、传感器故障或者线路干扰。
在Java端解析这类报文时,我习惯用一个专门的协议解析器,整体做法就是:先做CRC校验,确认报文完整;再检查报文长度与寄存器数量是否匹配;然后逐个寄存器解析,套用厂商给的换算公式;最后经过数据清洗模块,把超出物理范围的值、跳变过于剧烈的值、长时间不变化的值都处理掉。
关于CRC16校验,Modbus RTU使用的是CRC16-IBM/MODBUS算法,多项式是0xA001。Java代码实现并不复杂,我贴一个实际项目中用到的工具方法:
public static int crc16Modbus(byte[] data) { int crc = 0xFFFF; for (byte b : data) { crc ^= (b & 0xFF); for (int i = 0; i < 8; i++) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; }实际收到的报文末尾两个字节是CRC低位和高位,校验时把整帧去掉CRC前后的数据计算一遍,和报文里的CRC值比对,一致才认为报文有效。
气象站数据清洗我建议至少做三道检查:一是物理范围检查,比如空气温度超过-40到80摄氏度、湿度超过0到100%就直接标记为异常;二是变化率检查,比如两分钟之内温度突变超过10度,基本可以判定是传感器跳变;三是连续异常检查,如果同一个测点连续5次上报都是异常值,应该触发设备异常告警而不是简单丢弃。农业环境数据不像工业现场那样剧烈变化,正常情况下都是平滑缓变的。
2.2 水肥一体机:从传感器采集到设备反控
水肥一体机是智慧农业里面技术含量相对较高的设备,因为它涉及实时传感器检测和闭环控制。设备本身一般包括EC传感器(检测肥液电导率)、pH传感器(检测酸碱度)、流量计、若干个电磁阀、水泵、注肥泵和混液罐。
平台和水肥机的交互有两种典型方式。第一种是设备本地自主运行,平台只负责采集运行数据和远程启停;第二种是平台直接下发控制指令,通过Modbus寄存器或者继电器干接点控制水泵和阀门。实际项目里,因为园区管理员往往希望在办公室就能调整灌溉计划,我倾向于保留本地自动运行能力,同时支持平台远程切换模式和下发策略。
水肥一体机的Modbus控制协议比气象站稍微复杂一些,因为需要读的寄存器多,还要写寄存器。比如读取EC值、pH值、液位、各阀门开关状态可能需要读十几组寄存器,而下发指令时需要用功能码06写单个寄存器或者功能码10写多个寄存器。
平台下发控制指令的流程需要特别注意安全设计。我在做远程反控的时候,要求服务端必须记录每次控制指令的请求人、请求时间、内容、执行结果,同时设备端返回执行结果后平台才能标记指令完成。控制指令执行失败时要有告警,并且支持超时自动复位,防止出现阀门一直开着没关的情况。
这里贴一段简化后的控制指令下发代码,实际项目中还会加上权限校验和操作日志:
public void sendControlCommand(String deviceId, ControlCommand cmd) { DeviceSession session = deviceSessionManager.getSession(deviceId); if (session == null) { throw new BizException("设备不在线,无法下发控制指令"); } // 组装Modbus写寄存器报文:设备地址+功能码10+起始地址+寄存器数量+字节数+数据+CRC byte[] request = buildModbusWriteCommand(deviceId, cmd.getRegisterAddr(), cmd.getRegisterValue()); session.sendRequest(request, response -> { // 设备返回成功后,更新设备状态并记录操作日志 updateDeviceStatus(deviceId, cmd); saveControlLog(deviceId, cmd, "SUCCESS"); }, 5000, new RetryStrategy(3, 1000)); }“半路接手项目的人要特别注意:水肥机的控制逻辑一定要有手动、自动、远程三种模式,而且远程模式必须在设备端允许时才生效,否则一个误操作就可能导致田间植株大面积受损。
2.3 墒情监控:多层土壤数据与阈值告警
土壤墒情监控是比较容易理解的功能,就是把土壤水分、土壤温度传感器埋到地里,定时采集数据,让管理员通过平台就能知道当前土壤是否缺水、是否需要灌溉。和气象站相比,墒情数据更稳定,短时间内的变化很缓慢,所以采集频率通常不用太高,10分钟到30分钟一次就够了。
农业上有个基本概念叫田间持水量,不同类型土壤的适宜含水量范围差异很大。砂土、壤土、黏土对水分的保持能力不一样,所以墒情告警不能搞一刀切。比如砂土含水量35%可能就已经很湿润了,但在黏土里35%只能算中等偏干。做告警配置的时候,最好是能按地块、按传感器分别设置上下限。
墒情传感器还经常涉及多层监测。比如果树基地会在10厘米、30厘米、60厘米三个深度分别埋设传感器,用来判断不同根系深度的水分状况。平台在展示时要能区分不同层的数据,最好画出纵向剖面图。告警策略也要结合层次来定,表层土壤干旱可能只是蒸发快,深层土壤干旱才说明真的缺水。
墒情数据的阈值告警引擎可以考虑独立出来,做成可配置的规则。一个传感器可以配置多个告警规则,规则条件包括大于上限、小于下限、持续时长、连续次数。我在项目里使用了一个简单的规则表,核心字段是:
rule_id, sensor_id, rule_type, condition_value, duration_minutes, alarm_level, is_enabled判断逻辑是:只有当某个传感器的测量值持续超过阈值达到指定时长,比如持续15分钟超过上限,才触发告警。短期抖动不告警,避免频繁打扰。这种做法在实际项目中非常有用,尤其是碰到传感器偶发跳变的时候,能明显减少无效告警的数量。
2.4 视频监控:RTSP拉流、转码与Web播放
视频监控在农业物联网平台里的角色更像是一双“远程的眼睛”。管理员需要随时查看田间设备的实际状态、灌溉过程是否正常、是否有人员进入高风险区域。但农业基地的摄像头部署场景和城市安防差别很大,很多地方没有有线网络,只能靠4G/5G信号传输,因此视频方案需要特别考虑带宽和延迟。
目前海康、大华等主流摄像头一般都支持RTSP协议,可以直接通过如下地址访问视频流:
rtsp://username:password@ip:554/Streaming/Channels/101浏览器不能直接播放RTSP,所以常见做法是用流媒体服务拉取RTSP流转成HLS或者HTTP-FLV,再交给前端播放器播放。我在项目里用FFmpeg做转码,NodeMediaServer或者SRS做流媒体服务,前端用hls.js播放。
FFmpeg转码命令基本是这样:
ffmpeg -rtsp_transport tcp -i "rtsp://user:pass@192.168.1.64:554/Streaming/Channels/101" -c:v copy -c:a aac -f flv rtmp://127.0.0.1:1935/live/cam001注意拉流的时候建议指定-rtsp_transport tcp,因为UDP模式下跨网络拉流很容易丢包花屏。如果摄像头现场上行带宽有限,可以把输出分辨率降低、码率压低,比如转成720P甚至540P,帧率降到15帧,否则一个摄像头就占掉好几Mbps带宽,多个摄像头同时查看时网络根本扛不住。
视频功能还有一个容易被忽视的点是录像回放。农业项目里,管理员经常要在发生异常后回看几天前的监控画面。这需要流媒体服务或者NVR支持录像存储,并对外提供回放地址。如果平台只做直播不做录像,后续会被反复要求加这个功能,建议前期就预留好存储空间和回放接口。
3. 关键源码实现细节与库表设计
3.1 设备接入服务:Netty通道管理与粘包拆分
设备接入服务是整个平台最核心的部分。设备上电后会主动连接到平台的TCP端口,建立长连接,之后数据上报都是通过这个连接完成的。我使用Netty搭建这一层,重量轻、性能高,而且天然支持长连接管理。
Netty服务端的Pipeline配置很关键,顺序大致是:ChannelInboundHandler用于处理TCP连接建立和断开事件,FrameDecoder用于按协议拆包,DeviceMessageHandler用于把解析后的报文交给业务层。
农业设备很多使用自定义二进制协议,报文一般会以帧头开头、以帧尾结束,也有可能是在报文头里直接标明长度。分包粘包需要根据实际情况选择解码器,最常见的是用DelimiterBasedFrameDecoder按帧头帧尾拆分,或者用LengthFieldBasedFrameDecoder按长度字段拆包。
我遇到过一种设备,每帧数据以0xAA55开头,以0x0D0A结尾,中间包含数据长度字段。处理这种格式用LengthFieldBasedFrameDecoder就非常合适:
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 4, 2, -6, 0));这段代码的含义是最大帧长1024字节,长度字段从第4个字节开始,占用2个字节,长度字段前有4个字节的帧头,所以需要把长度字段的值减去6才是真实数据长度。参数看起来有点绕,第一次用的时候建议先在本地造几组报文测一遍,确认拆包正确性。
设备连接到服务端之后,需要登记设备ID和Channel的对应关系。当平台要向设备下发指令时,通过这个对应关系找到可用的Channel,再把报文发出去。
public class DeviceSession { private String deviceId; private Channel channel; private InetSocketAddress remoteAddress; private Instant connectedAt; private volatile Instant lastActiveTime; }Channel关闭时要清理对应的Session映射,否则再次下发指令时会拿到一个已经失效的Channel,抛异常还找不到原因。另外,服务端要周期性检查Session是否空闲,如果设备长时间没有上报数据,可以主动断开连接,等设备下次上线重新接入。
3.2 数据模型设计:设备、传感器、时序数据与告警
设备接入进来之后,数据如何存储是平台能否长期稳定运行的关键。农业物联网的数据模型相对固定,不需要太复杂的分布式架构,但表结构一定要设计得清楚。
设备信息表负责存储每台设备的静态信息:
device_id 设备唯一ID device_name 设备名称 device_type 设备类型(气象站/水肥机/墒情/摄像头) farm_id 所属基地 area_id 所属区域 model 设备型号 manufacturer 厂商 status 设备状态(online/offline/maintenance) last_online_time 最后在线时间传感器测点表负责存储每个设备下的所有传感器测点:
sensor_id 测点唯一ID device_id 所属设备 sensor_type 测点类型(air_temp/air_hum/wind_speed/soil_moisture...) sensor_name 测点名称 unit 单位 min_value 物理下限 max_value 物理上限 factor 换算系数 offset 换算偏移量 report_interval 上报周期 alarm_low 告警下限 alarm_high 告警上限时序监测数据表是最消耗存储空间的表。我采用按天分区的方案,一天一个分区,数据超过三个月之后自动删除历史分区。分区表的好处是删除数据时直接DROP分区,不需要逐条DELETE,对数据库性能影响极小。核心字段如下:
id 自增ID device_id 设备ID sensor_id 测点ID device_time 设备上报时间 value 原始值 status 数据质量标记(0正常 1异常 2修正) raw_data 原始报文视频设备的通道信息单独建表,记录摄像头名称、RTSP地址、播放地址、状态、许可证是否到期等信息。
告警记录表专门存历史告警,方便后续查询和分析:
alarm_id 告警ID device_id 设备ID sensor_id 测点ID alarm_type 告警类型(越限/离线/设备异常) alarm_level 告警等级(一般/重要/严重) message 告警内容 trigger_value 触发值 status 告警状态(未处理/已确认/已恢复) created_at 触发时间 handled_at 处理时间3.3 告警引擎与通知机制
告警引擎是平台体现“智慧”的核心模块之一。单纯把传感器数据展示在网页上没有太大价值,真正有价值的是当土壤墒情低于阈值时自动提醒管理员该浇水了,当设备离线超过设定时间时通知维护人员去现场检查,当水肥机EC值异常时及时停止灌溉。
我在项目中实现了一个轻量级告警引擎,核心思路是“数据进入实时流之后,交给规则引擎判断是否满足触发条件”。规则引擎不需要做成像Drools那样重,简单的配置表驱动即可。
具体流程是:实时数据解析完成并落库后,异步发送到告警判断队列;告警判断模块根据传感器ID查询该测点绑定的所有启用规则;逐条执行规则判断,满足触发条件后检查是否处于“告警冷却期”;如果不在冷却期,则生成告警记录并发送通知。通知方式可以配置成站内消息、短信、微信模板消息等。
告警触发后还要考虑恢复通知。比如墒情值低于下限触发缺水告警,之后管理员手动开启了灌溉,数据恢复后,系统应该自动关闭这条告警并给管理员发送“已恢复”通知。恢复通知可以减少管理员的确认压力,不然每天打开系统看到的都是旧告警,久而久之就麻木了。
这里有一个重要的细节:告警判断不要直接在Netty的工作线程里做,否则数据上报高峰期可能阻塞网络线程。我把告警判断放到独立的线程池或者消息队列中处理,Netty线程只负责报文解析和数据入库,保证整体吞吐量。
3.4 前后端接口与WebSocket实时推送
平台的管理后台采用前后端分离架构,后端提供RESTful API,前端使用Vue + Element Plus开发。业务接口包括用户认证、基础信息的增删改查、告警列表、视频播放地址获取、数据报表导出等。这部分的开发和普通Java Web项目差异不大,重点在于几个和物联网强相关的接口设计。
设备状态和传感器实时数据需要展示在页面上,如果用轮询方式每5秒请求一次,数据延迟还算可以接受,但并发页面多了服务器压力比较大。我的做法是:页面初次加载时走REST接口获取当前实时值,之后通过WebSocket订阅实时数据推送。服务端每隔几秒把最新的传感器数据推送到前端,页面不需要频繁发请求。
WebSocket推送还有一个应用场景是控制指令回执。管理员在页面上点击“开启灌溉”按钮,接口返回“指令已下发”,当设备端实际执行成功并回传状态后,平台通过WebSocket把“执行成功”推送到页面,管理员可以实时看到设备状态变化。这种即时反馈对用户信任感的建立非常重要。
权限设计方面,农业项目通常有多级账户,比如平台管理员、基地负责人、技术员、普通观察员。不同角色的权限不一样,技术员可以下发控制指令,普通观察员只能查看数据。这套权限体系用Spring Security加自定义数据权限过滤来实现,实际操作时按照设备所属农场做隔离,避免一个基地的管理员看到另一个基地的数据。
4. 现场部署与问题排查实录
4.1 传感器数据异常波动的排查思路
传感器数据跳变是最容易遇到的问题,几乎每个项目都会碰上。有一回我在测气象站数据,发现空气温度从28度突然跳到45度,过几分钟又恢复正常。一开始以为是传感器质量问题,后来发现是DTU转发报文时偶尔会触发重复帧拼接的问题,导致解析出来的数据错位。
排查这类问题,我的经验是先把原始报文日志打开。平台在收到每一条设备上报数据时都会把原始十六进制报文存一份到日志表,排查时直接对照原始报文,看解析结果和报文是否一致。如果报文本身是对的但解析结果不对,那就是解析逻辑有问题;如果报文本来就是乱序或重复的,那就是网络传输或DTU缓存的问题。
如果是偶尔出现一次异常值,可以在清洗逻辑里加毛刺过滤。做法很简单:把当前值与上一个正常值比较,如果变化幅度超过设置的阈值,则标记为可疑数据,不参与告警判断,但保留在数据表中供人工查看。如果连续多个点都异常,再判定为传感器硬件问题并触发告警。
田间环境对传感器的影响也很大。例如土壤传感器埋在土里,如果设备灌水后水分渗入传感器接口,会导致测量值产生漂移。同事实测过,防水接头没拧紧的情况下,两天后传感器数据整体漂移了5%。这种问题只能靠现场整改和定期维护来规避,平台侧能做的就是发现长时间稳定偏移时给出提示。
4.2 设备频繁离线重连的处理
农业设备频繁掉线非常磨人,原因是多方面的:4G信号差、网关供电不稳定、太阳能电瓶电压波动、DTU配置不当、服务端心跳参数设置不合理。
我最常见到的原因是服务端的心跳超时时间设置得太短。有些网络环境下,TCP连接由于NAT超时会被中间设备静默断开,但服务端和客户端都感知不到,直到下一次心跳或者发送数据时才暴露。解决办法是平台侧的读空闲时间设置得比设备心跳周期长一些,比如设备每30秒发一次心跳,服务端可以设置60秒读空闲,两者之间的间隙要足够大,但不能大到设备都断线了服务端还认为在线。
Netty的IdleStateHandler可以实现空闲检测:
pipeline.addLast("idleHandler", new IdleStateHandler(90, 30, 0));这里第一个参数是读空闲90秒,第二个参数是写空闲30秒。设备端每30秒发心跳,服务端90秒没收到任何数据就判定连接死掉,主动回收Session。
设备端也要配合做断线重连和缓存补传。最理想的情况是设备本地存储最近一段时间的数据,网络恢复后自动补传。如果设备没有本地缓存能力,平台可以在设备上线时主动向设备端发起历史数据查询指令,把离线期间的数据补回来。农业墒情这类数据即使缺几个小时也不影响整体判断,但气象站的风速雨量数据缺了就补不回来,必须靠设备本地缓存。
4.3 视频流并发压力大与播放卡顿
视频监控接入后最常见的坑是并发查看时机器带宽跑满。一个4MP摄像头的RTSP主码流大约是4到8Mbps,如果同时有10个人查看,直接拉主码流就需要40到80Mbps,普通办公室网络和服务器带宽根本扛不住。
解决办法是流媒体服务做分层转码和流的重用。同一个摄像头的RTSP流只从摄像头拉取一次,转成多档输出码率,不同用户根据网络情况选择清晰度。前端展示列表页使用子码流,点开大图才切换主码流,这样大部分场景下并发压力都能明显降下来。
如果你的摄像头群规模比较大,建议不要逐台拉RTSP,而是使用GB28181协议接入,让摄像头主动注册到流媒体服务器。GB28181是国标协议,支持设备管理、实时预览、录像回放、云台控制,不用暴露摄像头IP和端口,安全性和扩展性都比RTSP直连好很多。用Java生态做GB28181接入有现成开源项目可以借鉴,但纯Java实现SIP信令处理还是有点复杂,前期评估时要把这个工作量算进去。
如果前端播放用的是HLS,断点切片带来的延迟一般在3到5秒,对于监控场景可以接受。如果客户反馈延迟大,可以考虑改用HTTP-FLV或者WebRTC方案,延迟可以压到1秒以内,但实现成本也相应增加。
4.4 数据库容量膨胀与时序数据清理
平台运行几个月之后,时序数据表会越来越大。我以一个20台设备、平均每台8个传感器的项目为例来算笔账:每10分钟上报一次数据,一台设备一天就是8×24×6等于1152条记录,20台设备一天约2.3万条,一个月约69万条,一年超过800万条。如果采集频率提高到1分钟一次,这个数据量还会翻10倍。
这么大表如果不处理,查询接口会越来越慢,数据库备份恢复的时间也越来越长。我采用的做法是MySQL按周分区加索引优化,加上定期清理三个月之前的明细数据,只保留统计聚合值作为长期历史数据。
聚合值是个很实用的方案。比如一分钟的原始明细数据保留90天,但每天的分钟均值、小时均值、日均值、极值可以永久保存。绝大多数业务场景只需要看趋势和日均值,只有故障分析时才需要调用原始明细。这样既控制存储成本,又能满足长期数据追溯的需求。
如果项目预算允许,可以直接上TDengine或者InfluxDB这类时序数据库,对时序数据的写入和查询做了大量优化,数据压缩率也更好。MySQL方案本身没有问题,只是数据量过了千万级之后,维护成本会逐渐上升。
4.5 现场实施中的几个建议
最后聊几个现场实施时容易忽略的点,每条都是真实踩过的坑。
供电和防雷是第一优先级。农业基地的机柜和立杆基本都处在空旷的田间,雷雨季节雷击风险非常高。气象站、摄像头、传感器都建议加浪涌保护器,信号线全部走屏蔽线并做好接地。我就见过一个基地的摄像头因为立杆接地不合格,一个雷下来烧掉了三个网络口和一台交换机。
太阳能供电方案要留出足够余量。如果网关和路由器的总平均功耗是10W,在连续阴雨天的场景下,至少需要能支撑5到7天的电池容量。同时要关注电瓶低压保护值,不要让电池过度放电,否则电池寿命会大幅缩短,冬天的时候问题更明显。
平台部署后要给基地管理员做培训,重点不是教他怎么操作系统,而是教他遇到设备离线、数据不更新、画面连不上这些问题时,应该怎么初步排查。很多农业项目7×24小时都有设备在跑,但现场并没有专业IT人员,能不能快速定位问题直接决定了系统的实际可用性。
我个人在实际操作中的一个体会是:不要迷信“先进技术”,农业项目最看重的是稳定和简单。设备接入框架、告警逻辑、视频服务这些前期设计得越清晰,现场调试时麻烦就越少;界面做得再炫酷,也不如一条明确告诉管理员“东区三号墒情传感器低电量”的告警消息来得实用。
本文还有配套的精品资源,点击获取