Modbus之自动化阈值控制:温湿度超标自动通风、自动浇水业务逻辑

0 阅读7分钟

17-自动化阈值控制:温湿度超标自动通风、自动浇水业务逻辑

各位看官,前几篇我们把传感器数据从 485 总线一路搬到了云端时序数据库,属于"只读不写"的活儿。可智慧农业的核心诉求从来不是"看得见",而是"管得住"——大夏天的棚里 38℃,你光在手机上看个数字,菜就熟过头了。今天这篇,就来把自动化控制这块硬骨头啃下来。

一、需求拆解:控制到底要解决什么问题

先说三个最典型的场景:

  • 温度过高自动通风:大棚中午暴晒,温度传感器上报 38℃,阈值设定 35℃,系统自动开启卷膜电机/风机,降温后自动关闭。
  • 土壤湿度低自动浇水:土壤湿度低于 25% 时自动打开电磁阀滴灌,湿度回到 45% 后停水。
  • 光照不足自动补光:阴雨天光照强度低于 8000Lux,自动开启补光灯,持续 2 小时。

你看,这些需求长得很像:传感器数值 + 阈值比较 + 触发执行器。这就是"阈值规则"的本质。它不需要复杂的机器学习,一套规则引擎就能吃得下。但别小看它,落地时全是细节:什么时候触发、动作执行多久、触发了要不要防抖、人手干预了规则还该不该管。

二、阈值规则引擎:两张表打天下

规则引擎的设计核心,是把"条件"和"动作"解耦,做成可配置的规则表。数据库里就两张表:

规则表 rule
├── id
├── name          规则名称,如"高温通风"
├── sensor_point  条件传感器点位,如 temp_1
├── operator      比较符,如 gt / lt / gte / lte
├── threshold     阈值,如 35.0
├── time_start    生效时间窗开始,如 08:00
├── time_end      生效时间窗结束,如 18:00
├── enabled       是否启用
└── action_id     关联动作

动作表 action
├── id
├── device_point  执行器点位,如 fan_1(风机继电器)
├── action_value  动作值,如 1(开)或 0(关)
├── duration_sec  执行时长,如 300 秒
└── cooldown_sec  冷却时间,如 600 秒

两张表一拼,规则就活了:"当 temp_1 > 35.0(且当前时间在 08:00-18:00 内),则 fan_1 置 1,持续 300 秒"。生效时间窗这个字段别忽略,夜里你开着卷膜电机,凌晨的露水能把作物全冻死,这是踩坑踩出来的。

三、条件模型与动作模型:把业务翻译成结构

新手最容易犯的错,是把判断逻辑写死在代码里——加一条规则就改一次代码、发一次版。正确姿势是把"业务知识"抽成数据,程序只做通用执行。

规则条件模型(Condition)设计成这样:

字段含义示例
pointCode传感器点位编码soil_humidity_1
compare比较符> < >= <=
threshold阈值25.0
timeWindowStart/End生效时间窗08:00 ~ 20:00
windowType窗口类型:每天/仅白天/关闭DAILY

动作模型(Action)设计成这样:

字段含义示例
pointCode执行器点位编码valve_1
actionValue动作值,继电器通断1 / 0
durationSec执行时长,超时自动复位600
cooldownSec冷却时间,防抖用1200

这里有个关键点:动作值要写入 Modbus 线圈还是寄存器? 卷膜电机这种开关型设备走 FC05 写单线圈;变频器调风速这种模拟量设备走 FC06 写单寄存器。点位模型里要带 functionCode 字段,动作执行时才知道调哪种报文。

四、规则引擎实现:定时扫描 + 触发执行

引擎跑起来就是一个定时任务,默认 30 秒扫一轮,流程如下:

  1. 取数据:从内存缓存(边缘网关实时上报的数据)读传感器最新值。
  2. 过条件:逐条规则比较,加上生效时间窗校验。不满足直接跳过。
  3. 查状态机:每条规则有个"上次触发时间",在冷却期内不重复触发——防止温度在阈值附近抖动,风机开一下停一下。
  4. 下动作:通过 Modbus TCP 写执行器,同时记录一条执行日志(触发规则、动作值、时间)。
  5. 超时复位:动作执行满 durationSec 后,自动把执行器恢复到默认值(比如关风机)。

SpringBoot 里核心就三个类:RuleEntity(规则)、ActionEntity(动作)、RuleEngineService(引擎调度)。我直接贴核心执行逻辑:

@Service
public class RuleEngineService {

    @Autowired
    private PointDataCache pointCache;   // 最近一次点位数据缓存
    @Autowired
    private ModbusMasterService modbus;  // Modbus 写操作封装
    @Autowired
    private RuleRepository ruleRepo;

    private final Map<Long, Long> lastTriggerMap = new ConcurrentHashMap<>();

    @Scheduled(fixedDelay = 30000)  // 每 30 秒扫描一次
    public void scan() {
        for (RuleEntity rule : ruleRepo.findByEnabled(true)) {
            // 1. 生效时间窗校验
            if (!inTimeWindow(rule)) continue;
            // 2. 冷却期校验
            long now = System.currentTimeMillis();
            Long last = lastTriggerMap.get(rule.getId());
            if (last != null && now - last < rule.getAction().getCooldownSec() * 1000L) continue;

            // 3. 比较阈值
            Double cur = pointCache.getLatest(rule.getSensorPoint());
            if (cur == null) continue;
            if (!compare(cur, rule.getOperator(), rule.getThreshold())) continue;

            // 4. 触发动作:写执行器
            doAction(rule.getAction());
            lastTriggerMap.put(rule.getId(), now);
            ruleLogRepo.save(buildLog(rule, cur));
        }
    }

    private void doAction(ActionEntity action) {
        // functionCode=5 写线圈 / 6 写寄存器,发 Modbus 报文
        modbus.writePoint(action.getPointCode(), action.getActionValue());
        // 5. 注册超时复位任务
        scheduleReset(action, action.getDurationSec());
    }
}

注意 scheduleReset:用 ScheduledExecutorService 延迟执行,到点把执行器写回默认值。千万别省这步,否则风机开了忘了关,棚里一夜变冰窖。

五、自动浇水完整业务流程拆解

把上面拼起来,走一遍"自动浇水"全流程,你就彻底懂了:

  1. 数据层:土壤湿度探头(485 总线)→ 边缘网关采集,土壤湿度 24.8%。
  2. 缓存层:网关解析报文,湿度值写入本地缓存,同时 MQTT 上报云端。
  3. 规则层:云端规则引擎扫描,命中规则"soil_humidity_1 <= 25.0",生效时间窗通过,冷却期已过。
  4. 动作层:引擎调用 Modbus TCP 写 valve_1 线圈为 1,电磁阀打开,滴灌开始。
  5. 闭环:湿度回升到 32%(阈值带 25/45 之间),此时不满足"<=25"这条条件,但注意——我们还有一条规则"soil_humidity_1 >= 45.0 → valve_1 写 0",等湿度够高才停水。
  6. 超时兜底:哪怕规则没触发,valve 打开满 30 分钟,超时复位任务强制关阀,防止管道被淹。

这里体现了一个进阶技巧:双阈值防抖。开阀阈值 25%、关阀阈值 45%,中间 25~45% 是"死区",系统不做任何操作。否则单阈值 30%,湿度在 29.9%~30.1% 抖动,阀门每分钟开合一次,电磁阀寿命撑不过一个月。

六、安全保护:农业现场不能"全自动"蛮干

自动化的反面是"失控"。三把保护锁必须上齐:

  1. 双阈值 + 死区:见上文,避免频繁启停,保护执行器和作物。
  2. 手动优先:云端下发"手动控制"指令后,规则引擎对该点位自动挂起(manualOverride 标志),执行器只听手动的。手动解除后才能恢复自动化。你总不能大棚里有人作业时,系统突然把卷膜机降下来。
  3. 执行次数限制 + 异常回滚:单条规则 1 小时内触发上限(比如 5 次),达到上限告警并禁用规则。Modbus 写失败重试 3 次仍失败,走告警通道通知管理员,绝不静默失败。

七、小结

阈值自动化控制,业务上就一句话:传感器值过条件,执行器动一动。但工程上它把数据采集、点位模型、Modbus 写报文、定时任务、状态机、安全兜底全串了起来。读懂这篇,你就从"只会读 Modbus"升级到了"能闭环控制设备",这在智慧农业项目里是质的飞跃。下一篇咱们聊聊多品牌 Modbus 设备怎么统一接入——那才是项目真正头疼的开始。