简介:面向智慧农业场景的“智慧化养猪”App是一套基于Java的Android工程源码,适合移动开发初学者、农业信息化从业者、物联网开发者和高校学生参考,可用于毕业设计或课程实战。资源共179个文件,压缩包整体约20.14MB,目录结构完整:38个java文件承载登录、监测、设备控制等核心业务逻辑;59个xml文件负责界面布局与资源配置;34个png及jpg/webp等构成应用界面素材;25个so文件提供底层能力支持;另有gradle构建脚本、jar依赖包和日志记录,便于从工程创建到打包上线全流程研读。已有316人学习浏览,可作为智慧养殖App从零搭建的入门模板。通过研究源码可掌握Android基础组件、数据交互、SDK集成与常见调试排错方法,结合BaiduLBS定位库可深入理解第三方服务接入;配合完整UI素材与项目配置,读者能较快复现并扩展为可运行的智慧养殖演示系统。
1. 智慧化养猪 App:给传统猪场装上一套数字化神经
一个存栏五千头的育肥场,以前靠饲养员逐栏巡检、纸质记录采食和精神状态,数据在纸面上睡觉。我接过的某养殖集团模拟项目X,要求做一套智慧化养猪 App,让场长在手机上实时查看各栋舍的温度、湿度、氨气浓度和猪只异常预警,用 Java 把终端、服务端和数据链路整个跑通。这套方案解决的核心问题不是「给猪拍照」,而是让养殖管理的决策从「凭经验」变成「凭数据」:母猪发情漏配、育肥猪呼吸道疾病爆发、环控设备失灵引发的热应激,都能在造成损失前形成预警。
本文写给两类人:一类是准备用 Java 技术栈做农业物联网应用的开发者,想知道完整的架构和数据流怎么搭;另一类是养殖企业的信息化负责人,需要判断这套 App 的投入节奏和落地路径。我会把前后端分离的架构、关键数据表设计、设备接入协议、预警推送机制全部拆开讲,包括几个容易让项目翻车的坑:Modbus 协议字节序、4G 物联网卡在猪场的信号死角、以及 Android 端在弱网环境下的数据补传策略。这套方案不是实验室产物,而是能在猪场那种灰尘大、温差大、电压不稳的环境里跑稳的生产工具。
2. 为什么是 Java:从猪场环境反推出来的技术选型
2.1 物联网终端侧的硬约束:稳定性比性能更重要
猪场的硬件环境比写字楼恶劣得多:配电箱电压波动常见、粉尘附着在控制柜、夏季高温高湿。我在确定技术栈时先看终端——舍内环境采集器用的大多是 Modbus RTU 协议的传感器(温湿度、氨气、二氧化碳),控制风机和湿帘的也是 Modbus 继电器模块。这些设备对协议栈的要求是稳定、可靠、可重试,Java 的 Netty 框架处理长连接和粘包拆包非常成熟,生态里还有 modbus4j 这类现成库。相比 Python 的 asyncio 方案,Java 在 JVM 的稳定内存模型下跑 7x24 小时的长连接服务,内存泄漏概率更低。
服务端选型上,我采用了 Spring Boot 搭单体应用起步,等接入的设备超过五百台再拆微服务。原因是猪场项目不像互联网高并发场景,单场两三百台采集器、每台 5 秒上报一条数据,每秒吞吐不到 100 条消息,单体应用绰绰有余。团队里如果都是 Java 背景,维护成本也比引入 Go 或 Node.js 低。选型不是追新,是从现场运维的角度考虑:出了问题谁能最快定位、部署脚本谁都能跑。
2.2 App 端与后端的数据链路:三种通道各司其职
智慧化养猪 App 的通信不能只靠一条链路,我把它拆成了三条:
- MQTT 通道:用于实时告警和设备状态推送。终端采集器通过 4G 网关上报数据到 EMQX(开源版即可),Java 后端订阅 MQTT 主题,把解析后的数据写入数据库。App 端同样订阅 MQTT,收到告警实时弹出通知。
- HTTP 接口:用于查询类操作,比如场长查看历史曲线、猪只档案、报表导出。这部分走 Spring Boot 的 RESTful API,采用 HTTPS 加密,用 JWT 做鉴权。
- Socket(TCP 长连接):用于给终端设备下发控制指令,比如远程开关风机、调节水帘。因为控制指令需要确认设备是否执行,TCP 长连接比 MQTT QoS 更可控。
三条链路共用一个后端核心服务,设备接入层做了统一抽象。我在网关设备上选的是支持 MQTT 协议的 4G DTU,它能自动把 Modbus RTU 转成 MQTT 消息,这样 Java 端就不需要直接处理串口通信,省掉一层复杂度。
2.3 数据库选型:时序数据与业务数据分开存储
猪场的环境数据是典型的时序数据:每台采集器每 5 秒报一条,一天就是 17280 条,一个千头猪场一天产生几十万条记录。如果全塞进 MySQL,三个月后查询历史曲线会明显变慢,索引膨胀得厉害。我采用双库方案:
- MySQL:存猪只档案、免疫记录、饲料消耗、人员操作日志等业务数据。这类数据量小、关系复杂,适合关系型数据库管理事务。
- TDengine(或 InfluxDB):存环境采集数据、设备运行状态等时序数据,按时间戳聚合查询,保留原始数据只存最近 30 天,超过的部分降采样成 1 分钟一条的聚合数据长期保存。这样历史曲线查询秒级返回,存储压力也可控。
数据库拆分后,报表统计的 SQL 跨库查询是个问题。我在 Java 服务层做了一层聚合:先查 TDengine 拿时序统计结果,再查 MySQL 拿业务数据,Java 内存里做关联组装。因为数据量不大,这种服务层聚合的方式比引入数据仓库简单得多。
3. 核心功能模块拆解:从猪只档案到智能预警
3.1 数据建模:三个关键表的设计与字段释义
智慧化养猪的业务核心是「猪只生命周期管理」。我设计了三个核心表,下面是 MySQL 的建表 SQL:
-- 猪只档案表 CREATE TABLE pig_profile ( id BIGINT AUTO_INCREMENT PRIMARY KEY, ear_tag VARCHAR(32) NOT NULL COMMENT '耳标编号,唯一标识', barn_id BIGINT NOT NULL COMMENT '栋舍ID', pen_id BIGINT NOT NULL COMMENT '栏位ID', breed_type VARCHAR(16) COMMENT '品种:杜洛克/长白/大白', birth_date DATE COMMENT '出生日期', status TINYINT DEFAULT 0 COMMENT '0-在栏 1-转群 2-出栏 3-死亡', weight_kg DECIMAL(6,2) COMMENT '当前体重(kg)', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_barn (barn_id), INDEX idx_status (status) ) ENGINE=InnoDB COMMENT='猪只档案表'; -- 环境采集数据表(TDengine 中创建) CREATE TABLE environment_data ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, device_id VARCHAR(32) NOT NULL, barn_id BIGINT NOT NULL, temperature DOUBLE COMMENT '舍内温度(℃)', humidity DOUBLE COMMENT '相对湿度(%)', ammonia DOUBLE COMMENT '氨气浓度(ppm)', co2 DOUBLE COMMENT '二氧化碳浓度(ppm)' ) TAGS (device_id, barn_id);环境数据建到 TDengine 的超级表里,以 device_id 和 barn_id 作为标签,查询时可以按标签快速过滤。字段设计上,温度和湿度是环控的核心指标——育肥猪的适宜温度在 18~22℃,湿度 60%~75%,氨气浓度长期超过 25ppm 会诱发呼吸道疾病。这些阈值不写死在数据库,而是配在预警规则表里,可以根据季节和猪只日龄动态调整。
3.2 设备接入与数据解析:Modbus 协议的处理细节
采集器上报的数据不是干净的 JSON,而是 Modbus RTU 的寄存器数值。以温湿度传感器为例,读取到的原始数据是两个 16 位寄存器值,需要按照协议文档换算成实际温度。我在 Java 端封装了一个解析服务,代码如下:
/** * Modbus RTU 温湿度数据解析 * @param registerData 传感器返回的寄存器字节数组 * @param dataType 1-温度 2-湿度 */ public double parseModbusData(byte[] registerData, int dataType) { // Modbus RTU 大端模式:高字节在前 int rawValue = ((registerData[0] & 0xFF) << 8) | (registerData[1] & 0xFF); // 温度传感器:原始值除以10得到实际温度,支持负数 if (dataType == 1) { // 处理负数,Modbus 用补码表示负数 if (rawValue > 0x8000) { rawValue = rawValue - 0x10000; } return rawValue / 10.0; } // 湿度传感器:部分设备直接返回百分比,部分需要除以10 return rawValue / 10.0; }真正让新人踩坑的是字节序问题。不同厂家传感器的 Modbus 寄存器有的大端、有的小端,有的浮点数用两个寄存器按 IEEE 754 存储。我在接入某品牌氨气传感器时就遇到了字节序反了导致浓度显示成天文数字的情况。解决办法是:对接入的每一款设备,先用手持 Modbus 调试工具读原始值,确认字节序和数据精度,然后在设备配置表里加上 byteOrder 和 precision 两个字段,解析服务根据设备型号动态读取配置。
3.3 预警引擎:规则可配置,推送要分级
预警是智慧化养猪 App 最有价值的功能。不能在环境数据超标时无脑告警,否则饲养员一天收几百条推送,很快就把通知关掉。我把预警规则设计成三级:
- 一级预警(黄色):温度超过设定阈值 2℃,或者氨气超过 20ppm,App 推送提醒。
- 二级预警(橙色):温度超过阈值 5℃,持续 10 分钟以上,或湿度超过 80%,推送 + 短信通知场长。
- 三级预警(红色):设备离线超过 15 分钟,或温度超过阈值 8℃,推送 + 短信 + 电话语音通知,立即触发应急预案。
预警规则表记录了规则的条件表达式,用 Java 的 Aviator 表达式引擎做规则评估,支持场长在界面上自行调整阈值。推送通道上,因为 Android App 常驻后台可能被系统杀掉,我除了用极光推送之外,还保留了一个 WebSocket 通道做前台消息实时到达,后台被杀之后依赖厂商推送通道拉起。
4. App 端到 Java 后端:接口设计与联调血泪经验
4.1 数据上报接口:批量上报与合并去重
App 端有移动巡检功能,饲养员携带手机在猪舍内扫描耳标、录入猪只异常情况。巡检数据需要支持离线保存、联网上报。后端接口设计成批量提交模式,一次最多传 50 条巡检记录:
@PostMapping("/api/pig/inspection/batch") public ApiResponse<Integer> batchInspection(@RequestBody @Validated List<InspectionDTO> list) { // 参数校验:单次请求数量限制 if (list.size() > 50) { return ApiResponse.error(400, "单次批量提交不能超过50条"); } // 幂等性检查:用客户端生成的batchId做去重 // 防止弱网环境下App重试提交同一批数据导致重复 String batchId = list.get(0).getBatchId(); if (redisTemplate.hasKey("inspection:" + batchId)) { return ApiResponse.success(0); // 已处理过,直接返回成功 } // 批量插入 int insertCount = inspectionService.batchInsert(list); // 记录batchId到Redis,有效期24小时 redisTemplate.opsForValue().set("inspection:" + batchId, "1", 24, TimeUnit.HOURS); return ApiResponse.success(insertCount); }这个接口的核心是幂等性处理。我踩过的坑是:App 端在猪舍里信号差,打了 30 分钟提交按钮没反应,饲养员反复点,后台收到好几遍相同的巡检数据,猪只档案里的异常次数翻了三倍。加了这个 batchId 去重逻辑之后,数据才真正可靠。
4.2 实时数据推送:WebSocket + 心跳保活机制
App 首页要展示猪舍的实时环境数据,不能一直轮询 HTTP 接口,否则流量和耗电都扛不住。我采用 WebSocket 建立长连接,服务端每 5 秒推送一次最新环境数据。但手机熄屏后 WebSocket 会被系统断开,恢复前台时要检测连接状态并自动重连:
// uni-app 或 Android WebView 前端代码中心跳重连逻辑 function initWebSocket() { const wsUrl = "wss://api.pigfarm.com/ws/realTime?token=" + getToken(); ws = new WebSocket(wsUrl); // 心跳包:每30秒发一次ping,服务端回pong heartbeatTimer = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: "ping", ts: Date.now() })); } }, 30000); // 监听断开事件:指数退避重连 ws.onclose = () => { clearInterval(heartbeatTimer); // 首次重连延迟2秒,之后翻倍,最大60秒 let retryDelay = retryCount < 5 ? Math.pow(2, retryCount) * 2000 : 60000; setTimeout(initWebSocket, retryDelay); retryCount++; }; }4.3 文件上传:耳标照片与健康检查图片的压缩方案
饲养员巡检时给异常猪只拍照,一张照片原图可能有 3-5MB,猪场网络环境又不稳定,直接传原图容易超时。我做了两层处理:App 端先用 canvas 压缩到最大 800px 宽、质量 0.7 的 JPEG;后端接收后校验文件类型和体积,统一存储到对象存储服务(内网自建 MinIO),然后返回 URL。图片压缩后的平均大小在 100KB 左右,弱网环境下上传成功率从 60% 提升到了 98%。
5. 部署与运维:让系统在猪场环境稳定跑起来
5.1 服务器规划:单机部署与双机热备
一个存栏万头的猪场,我推荐用两台物理服务器做双机热备而非上云。原因现实:猪场通常在偏远地区,公网带宽不稳定,数据要留在本地。配置上,一台主力服务器(16核 32GB 内存,2TB SSD)跑 Java 后端 + MySQL + EMQX 消息服务;另一台备用服务器(配置相同)跑 TDengine 和文件存储,同时做主服务器的冷备。每天凌晨 2 点做增量备份,每周日做全量备份。这个配置的吞吐量支撑两个万头猪场完全足够,成本控制在几万元内,比云服务器年费省下不少。
5.2 数据备份策略:秒级数据不能丢
环境数据是连续采集的,如果服务器宕机一小时,这期间的数据就断了,猪场环境变化曲线会出现缺口。我在 4G DTU 上启用了本地缓存功能——设备自带存储,网络断开时数据缓存到本地,网络恢复后自动补传。Java 后端的数据写入采用批量入库,每 10 秒攒一批写入 TDengine,减少 I/O 压力。备份上,TDengine 支持按时间段导出数据文件,我写了个定时任务每天把前一天的数据打包传到备用服务器,保留 90 天。
5.3 设备离线告警:不能全指望 App 推送
设备离线是物联网项目最常见的故障,但排查链路长。我在后台管理页面专门做了一个「设备在线状态矩阵」:横轴是时间,纵轴是设备列表,离线时段用红块标出,一眼就能看出哪个时段、哪栋舍的设备集体掉线。常见原因排序:4G 信号盲区(猪舍的钢筋混凝土对信号衰减很强)、SIM 卡欠费、DTU 电源被误关。我在每栋猪舍安排了一台信号增强器,把 4G 天线引到窗外,彻底解决了信号问题。
6. 智慧化养猪 App 落地避坑:五条真实场景排查记录
6.1 数据延迟:TDengine 查询突然变慢
现象:系统上线一个月后,App 的历史曲线页打开要等 8 秒以上。
原因:TDengine 的保留策略没配好,原始数据无限增长,查询扫描的数据块太多。我们当时的保留策略只设了「数据永不删除」,结果一个月就有近 2 亿条记录。
解决:重建数据库并设置合理的保留策略——原始数据保留 30 天,超过 30 天的数据降采样为分钟级聚合数据,保留 2 年。查询速度恢复到 500ms 以内。
6.2 Modbus 数据错乱:同一个传感器返回不同温度
现象:某传感器上午显示正常,下午突然跳到 -40℃。
原因:Modbus 串行链路有两个设备地址冲突,主站轮询时读到了错误设备的寄存器。现场排查发现是新增的一台采集器默认地址是 1,和原有的 1 号设备冲突了。
解决:所有设备接入前必须检查地址分配表,用 Modbus 调试工具逐台设备读取地址并重新分配,确保全局唯一。
6.3 告警风暴:氨气传感器半小时推了 200 条告警
现象:某天上午,App 的告警推送几乎每隔 10 秒响一次,场长直接把通知权限关了。
原因:那一栋舍的风机故障停机,氨气浓度快速上升,我们的预警规则是「浓度超过 30ppm 即告警」,每次上报都触发。
解决:在预警规则里加了「持续时间」条件——告警触发后,如果 5 分钟内没有恢复,才进行下一次推送;同一条告警 30 分钟内最多重复推送 3 次。告警风暴立刻消除。
6.4 APP 无法登录:JWT 过期时间设置不合理
现象:饲养员早上登录 App,中午再看就掉线,需要重新输密码。
原因:我把 JWT 的有效期设成了 4 小时,但饲养员一个班次是 8 小时,中间必然掉线。而且没有做刷新令牌机制。
解决:改成双令牌方案——Access Token 有效期 8 小时,Refresh Token 有效期 7 天。App 自动用 Refresh Token 去换取新的 Access Token,用户感知不到掉线。
6.5 控制指令失效:远程开风机没反应
现象:场长在办公室远程打开 3 号风机,App 显示「已发送」,但风机没转。
原因:控制指令走 MQTT 主题,设备端订阅了,但指令的 topic 和设备实际监听的 topic 不一致。排查发现是配置文件中多了一个前缀/prod/。
解决:统一了 topic 命名规范,并且加了「指令回执」逻辑——设备执行成功后上报一条确认消息,后端 10 秒没收到回执就标记为失败并重试。
7. 进阶玩法:把 AI 视觉引入猪只健康监测
App 做完了环境监测和档案管理,更进一步的价值是猪只健康状态的自动识别。我用 Java 调用了开源的图像识别模型(TensorFlow Serving),对舍内摄像头抓拍的猪只图片做行为分析:猪只的咳嗽声(通过拾音器采集音频特征)、站立/卧倒姿态异常、腹部呼吸频率加快,都是呼吸道疾病的早期信号。这是非常前沿的尝试,但要注意两点:一是猪舍的摄像头安装位置要能覆盖整个栏位,光照差时效果打折;二是模型训练需要积累大量标注数据,起步阶段可以先只检测「猪只长时间卧倒不起」这种强特征。我把这部分设计成独立的微服务,通过 HTTP 与主应用通信,不影响核心业务稳定性。实际跑下来,对呼吸道疾病预警的准确率大约在 70% 左右,还不能做到完全替代人工巡检,但已经能显著降低漏检率。后续可以持续用新数据做增量训练,同时结合环境数据(氨气、温差)做交叉验证,让误报率进一步下降。这套方案给养殖场带来的收益是可量化的:早发现一头病猪,省下的治疗费和避免的死亡率,足以覆盖整套系统的建设成本。做个不恰当的类比,智慧化养猪 App 就像给猪场装了一套健康的神经系统,环境是皮肤感受器,预警是疼痛信号,而 Java 后端就是那个不眠不休的脑干。希望帮到你。
本文还有配套的精品资源,点击获取