智能家居控制器 #

一、项目概述 #

1.1 项目目标 #

构建一个基于树莓派的智能家居控制器,实现以下功能:

text
┌─────────────────────────────────────────────────────────┐
│                  智能家居控制器架构                       │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌─────────────────────────────────────────────────┐   │
│  │                 云平台 / 手机APP                  │   │
│  └────────────────────────┬────────────────────────┘   │
│                           │ MQTT                        │
│  ┌────────────────────────┴────────────────────────┐   │
│  │              智能家居控制器 (树莓派)              │   │
│  │  ┌─────────┬─────────┬─────────┬─────────┐       │   │
│  │  │ 温湿度  │ 光照    │ 人体感应 │ 烟雾    │       │   │
│  │  │ 传感器  │ 传感器  │ 传感器  │ 传感器  │       │   │
│  │  └────┬────┴────┬────┴────┬────┴────┬────┘       │   │
│  │       │         │         │         │            │   │
│  │  ┌────┴────┬────┴────┬────┴────┬────┴────┐       │   │
│  │  │ 灯光    │ 空调    │ 窗帘    │ 门锁    │       │   │
│  │  │ 控制    │ 控制    │ 控制    │ 控制    │       │   │
│  │  └─────────┴─────────┴─────────┴─────────┘       │   │
│  └─────────────────────────────────────────────────┘   │
│                                                         │
└─────────────────────────────────────────────────────────┘

1.2 功能模块 #

模块 功能
环境监测 温湿度、光照、空气质量监测
安防监控 人体感应、烟雾报警、门窗状态
设备控制 灯光、空调、窗帘、门锁控制
场景联动 自动化场景规则执行
远程通信 MQTT云平台连接

二、硬件准备 #

2.1 硬件清单 #

设备 数量 用途
Raspberry Pi 4B 1 主控制器
DHT22温湿度传感器 1 环境监测
BH1750光照传感器 1 光照监测
HC-SR501人体感应 2 安防监控
MQ-2烟雾传感器 1 烟雾检测
4路继电器模块 1 设备控制
舵机SG90 2 窗帘/门锁

2.2 接线图 #

text
Raspberry Pi 4B
┌─────────────────────────────────────────┐
│ GPIO17 ── DHT22 数据线                  │
│ GPIO18 ── BH1750 SDA (I2C)              │
│ GPIO19 ── BH1750 SCL (I2C)              │
│ GPIO22 ── HC-SR501 #1 输出              │
│ GPIO23 ── HC-SR501 #2 输出              │
│ GPIO24 ── MQ-2 数字输出                 │
│ GPIO25 ── 继电器 IN1 (灯光)             │
│ GPIO5  ── 继电器 IN2 (空调)             │
│ GPIO6  ── 继电器 IN3 (风扇)             │
│ GPIO12 ── 继电器 IN4 (插座)             │
│ GPIO13 ── 舵机 #1 PWM (窗帘)            │
│ GPIO16 ── 舵机 #2 PWM (门锁)            │
└─────────────────────────────────────────┘

三、软件架构 #

3.1 项目结构 #

text
smart-home/
├── src/main/java/com/example/smarthome/
│   ├── Main.java
│   ├── config/
│   │   └── AppConfig.java
│   ├── sensor/
│   │   ├── Sensor.java
│   │   ├── TemperatureSensor.java
│   │   ├── LightSensor.java
│   │   └── MotionSensor.java
│   ├── actuator/
│   │   ├── Actuator.java
│   │   ├── Relay.java
│   │   └── Servo.java
│   ├── controller/
│   │   ├── HomeController.java
│   │   └── SceneController.java
│   ├── network/
│   │   ├── MQTTClient.java
│   │   └── HttpServer.java
│   └── automation/
│       ├── Rule.java
│       └── RuleEngine.java
├── src/main/resources/
│   └── config.properties
└── pom.xml

3.2 核心代码 #

主程序入口

java
package com.example.smarthome;

import com.example.smarthome.config.AppConfig;
import com.example.smarthome.controller.HomeController;
import com.example.smarthome.network.MQTTClient;
import com.pi4j.Pi4J;

public class Main {

    public static void main(String[] args) {
        System.out.println("智能家居控制器启动...");
        
        var pi4j = Pi4J.newAutoContext();
        AppConfig config = AppConfig.load();
        
        HomeController controller = new HomeController(pi4j, config);
        
        MQTTClient mqtt = new MQTTClient(config.getMqttBroker(), "smart-home");
        mqtt.connect();
        
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("正在关闭...");
            controller.shutdown();
            mqtt.disconnect();
            pi4j.shutdown();
        }));
        
        controller.start();
    }
}

传感器管理

java
package com.example.smarthome.sensor;

import java.util.Map;
import java.util.concurrent.*;

public class SensorManager {

    private final Map<String, Sensor> sensors = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler = 
        Executors.newScheduledThreadPool(2);
    
    public void register(String id, Sensor sensor) {
        sensors.put(id, sensor);
    }
    
    public void startPolling(int intervalMs) {
        scheduler.scheduleAtFixedRate(() -> {
            for (Map.Entry<String, Sensor> entry : sensors.entrySet()) {
                try {
                    double value = entry.getValue().read();
                    System.out.printf("[%s] %s: %.2f%n", 
                        System.currentTimeMillis(), 
                        entry.getKey(), value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 0, intervalMs, TimeUnit.MILLISECONDS);
    }
    
    public double getValue(String sensorId) {
        Sensor sensor = sensors.get(sensorId);
        return sensor != null ? sensor.getLastValue() : 0;
    }
    
    public Map<String, Double> getAllValues() {
        Map<String, Double> values = new ConcurrentHashMap<>();
        sensors.forEach((id, sensor) -> values.put(id, sensor.getLastValue()));
        return values;
    }
    
    public void shutdown() {
        scheduler.shutdown();
    }
}

设备控制器

java
package com.example.smarthome.controller;

import com.example.smarthome.actuator.*;
import com.example.smarthome.sensor.*;
import com.example.smarthome.automation.RuleEngine;
import com.pi4j.context.Context;
import java.util.concurrent.*;

public class HomeController {

    private final Context pi4j;
    private final SensorManager sensors;
    private final ActuatorManager actuators;
    private final RuleEngine ruleEngine;
    private final ScheduledExecutorService scheduler;
    
    public HomeController(Context pi4j, AppConfig config) {
        this.pi4j = pi4j;
        this.sensors = new SensorManager();
        this.actuators = new ActuatorManager();
        this.ruleEngine = new RuleEngine();
        this.scheduler = Executors.newScheduledThreadPool(4);
        
        initializeSensors();
        initializeActuators();
        initializeRules();
    }
    
    private void initializeSensors() {
        sensors.register("temperature", new TemperatureSensor(pi4j, 17));
        sensors.register("humidity", new HumiditySensor(pi4j, 17));
        sensors.register("light", new LightSensor(pi4j, 1, 0x23));
        sensors.register("motion_living", new MotionSensor(pi4j, 22));
        sensors.register("motion_bedroom", new MotionSensor(pi4j, 23));
        sensors.register("smoke", new SmokeSensor(pi4j, 24));
    }
    
    private void initializeActuators() {
        actuators.register("light_living", new Relay(pi4j, 25, true));
        actuators.register("light_bedroom", new Relay(pi4j, 5, true));
        actuators.register("ac", new Relay(pi4j, 6, true));
        actuators.register("fan", new Relay(pi4j, 12, true));
        actuators.register("curtain", new ServoMotor(pi4j, 13));
        actuators.register("lock", new ServoMotor(pi4j, 16));
    }
    
    private void initializeRules() {
        ruleEngine.addRule("auto_light", (sensors, actuators) -> {
            double light = sensors.getValue("light");
            boolean motion = sensors.getValue("motion_living") > 0;
            
            if (light < 100 && motion) {
                actuators.on("light_living");
            } else if (!motion) {
                actuators.off("light_living");
            }
        });
        
        ruleEngine.addRule("smoke_alarm", (sensors, actuators) -> {
            double smoke = sensors.getValue("smoke");
            if (smoke > 500) {
                actuators.on("fan");
                System.out.println("烟雾报警!启动排风扇");
            }
        });
    }
    
    public void start() {
        sensors.startPolling(5000);
        
        scheduler.scheduleAtFixedRate(() -> {
            ruleEngine.evaluate(sensors, actuators);
        }, 0, 1, TimeUnit.SECONDS);
    }
    
    public void shutdown() {
        sensors.shutdown();
        scheduler.shutdown();
    }
}

四、自动化规则 #

4.1 规则引擎 #

java
package com.example.smarthome.automation;

import com.example.smarthome.sensor.SensorManager;
import com.example.smarthome.actuator.ActuatorManager;
import java.util.*;
import java.util.function.BiConsumer;

public class RuleEngine {

    private final Map<String, BiConsumer<SensorManager, ActuatorManager>> rules = 
        new LinkedHashMap<>();
    
    public void addRule(String name, BiConsumer<SensorManager, ActuatorManager> rule) {
        rules.put(name, rule);
    }
    
    public void removeRule(String name) {
        rules.remove(name);
    }
    
    public void evaluate(SensorManager sensors, ActuatorManager actuators) {
        for (Map.Entry<String, BiConsumer<SensorManager, ActuatorManager>> entry : 
             rules.entrySet()) {
            try {
                entry.getValue().accept(sensors, actuators);
            } catch (Exception e) {
                System.err.println("规则执行错误: " + entry.getKey());
                e.printStackTrace();
            }
        }
    }
    
    public List<String> getRuleNames() {
        return new ArrayList<>(rules.keySet());
    }
}

五、远程控制 #

5.1 MQTT集成 #

java
package com.example.smarthome.network;

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import com.example.smarthome.controller.HomeController;

public class MQTTClient implements MqttCallback {

    private MqttAsyncClient client;
    private final String broker;
    private final String clientId;
    private HomeController controller;
    
    public MQTTClient(String broker, String clientId) {
        this.broker = broker;
        this.clientId = clientId;
    }
    
    public void connect() throws MqttException {
        client = new MqttAsyncClient(broker, clientId, 
            new MemoryPersistence());
        
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true);
        options.setAutomaticReconnect(true);
        
        client.setCallback(this);
        client.connect(options).waitForCompletion();
        
        client.subscribe("home/+/command", 1);
        client.subscribe("home/scene/activate", 1);
    }
    
    public void publish(String topic, String payload) throws MqttException {
        client.publish(topic, payload.getBytes(), 1, false);
    }
    
    @Override
    public void connectionLost(Throwable cause) {
        System.out.println("MQTT连接丢失: " + cause.getMessage());
    }
    
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        String payload = new String(message.getPayload());
        System.out.println("收到消息: " + topic + " -> " + payload);
        
        if (topic.endsWith("/command")) {
            handleCommand(topic, payload);
        } else if (topic.equals("home/scene/activate")) {
            handleScene(payload);
        }
    }
    
    private void handleCommand(String topic, String payload) {
        String[] parts = topic.split("/");
        if (parts.length >= 3) {
            String device = parts[1];
            String action = payload.toLowerCase();
            
            if ("on".equals(action)) {
                controller.turnOn(device);
            } else if ("off".equals(action)) {
                controller.turnOff(device);
            }
        }
    }
    
    private void handleScene(String sceneName) {
        controller.activateScene(sceneName);
    }
    
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
    }
    
    public void disconnect() throws MqttException {
        if (client != null && client.isConnected()) {
            client.disconnect();
        }
    }
}

六、总结 #

智能家居控制器项目要点:

  1. 模块化设计:传感器、执行器、控制器分离
  2. 事件驱动:使用事件机制处理传感器数据
  3. 规则引擎:灵活的自动化规则配置
  4. 远程通信:MQTT协议实现远程控制
  5. 资源管理:正确管理硬件资源生命周期

下一章我们将学习环境监测站项目。

最后更新:2026-03-27