赞
踩
随着智能家居技术的快速发展,越来越多的用户希望通过智能设备提升家居生活的便利性和智能化水平。本项目旨在搭建一个基于树莓派的AI接入文心一言智能家居中控系统。该系统能够根据AI获取的实时数据(如天气、温度、湿度等)自动控制家居设备,并支持用户通过可视化界面进行手动控制。
通过接入文心一言的AI接口,我们可以获取天气预报、空气质量等信息,进而智能化地控制家居设备。例如,当天气预报显示即将下雨时,系统可以自动关闭窗帘,或者在高温天气时启动空调。
将传感器和继电器模块连接至树莓派的GPIO接口。以DHT11为例,接线如下:
- sudo apt update
- sudo apt upgrade
sudo apt install python3 python3-pip
pip3 install Flask paho-mqtt requests
pip3 install Adafruit-DHT
使用SQLite创建数据库和表:
- import sqlite3
-
- conn = sqlite3.connect('smart_home.db')
- c = conn.cursor()
-
- # 创建设备状态表
- c.execute('''CREATE TABLE IF NOT EXISTS device_status
- (id INTEGER PRIMARY KEY, name TEXT, state INTEGER)''')
-
- conn.commit()
- conn.close()
以下是用于读取DHT11温湿度传感器数据并通过MQTT发布的代码:
- import Adafruit_DHT
- import paho.mqtt.client as mqtt
- import requests
- import time
- import sqlite3
-
- # 传感器设置
- DHT_SENSOR = Adafruit_DHT.DHT11
- DHT_PIN = 17
-
- # MQTT设置
- MQTT_BROKER = "localhost"
- MQTT_TOPIC = "home/sensors"
-
- # 文心一言API设置
- WENXIN_API_URL = "https://api.wenxinyiyan.com/weather" # 替换为实际的文心一言API URL
- WENXIN_API_KEY = "your_api_key" # 替换为你的文心一言API密钥
- def get_weather_data():
- """获取实时天气数据"""
- try:
- response = requests.get(WENXIN_API_URL, params={"apikey": WENXIN_API_KEY})
- if response.status_code == 200:
- return response.json() # 返回JSON数据
- else:
- print("获取天气数据失败:", response.status_code)
- return None
- except Exception as e:
- print("请求文心一言API时出错:", e)
- return None
-
- def read_sensor_and_control():
- """读取传感器数据并根据天气数据控制设备"""
- humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
- if humidity is not None and temperature is not None:
- mqtt_publish(temperature, humidity)
-
- # 获取天气数据
- weather_data = get_weather_data()
- if weather_data:
- # 根据天气数据做出智能决策
- if weather_data['weather'] == "Rain":
- control_device("窗帘", 0) # 关闭窗帘
- elif weather_data['temperature'] > 30:
- control_device("空调", 1) # 打开空调
- else:
- print("无法从湿度传感器获取数据")
-
- def mqtt_publish(temperature, humidity):
- """将温湿度数据发布到MQTT主题"""
- client = mqtt.Client() # 创建MQTT客户端
- client.connect(MQTT_BROKER) # 连接到MQTT代理
- client.publish(MQTT_TOPIC, f"Temperature: {temperature}°C, Humidity: {humidity}%") # 发布数据
- client.disconnect() # 断开连接
-
- def control_device(device_name, state):
- """根据设备名称和状态来控制设备"""
- conn = sqlite3.connect('smart_home.db')
- c = conn.cursor()
- c.execute("UPDATE device_status SET state=? WHERE name=?", (state, device_name)) # 更新设备状态
- conn.commit()
- conn.close()
-
- if __name__ == "__main__":
- while True:
- read_sensor_and_control() # 持续读取传感器数据并控制设备
- time.sleep(10) # 每10秒读取一次

接下来,我们需要实现Flask后端,以便用户可以通过HTTP请求与系统交互。
- from flask import Flask, jsonify, request
- import sqlite3
- import requests
-
- app = Flask(__name__)
-
- def init_db():
- """初始化数据库,创建设备状态表"""
- conn = sqlite3.connect('smart_home.db')
- c = conn.cursor()
- c.execute('''CREATE TABLE IF NOT EXISTS device_status
- (id INTEGER PRIMARY KEY, name TEXT, state INTEGER)''')
- conn.commit()
- conn.close()
-
- @app.route('/devices', methods=['GET'])
- def get_devices():
- """获取所有设备的状态"""
- conn = sqlite3.connect('smart_home.db')
- c = conn.cursor()
- c.execute("SELECT * FROM device_status")
- devices = c.fetchall() # 获取所有设备状态
- conn.close()
- return jsonify(devices) # 以JSON格式返回设备状态
-
- @app.route('/devices/<int:device_id>', methods=['POST'])
- def control_device(device_id):
- """控制设备的开关状态"""
- data = request.json
- state = data.get('state')
-
- conn = sqlite3.connect('smart_home.db')
- c = conn.cursor()
- c.execute("UPDATE device_status SET state=? WHERE id=?", (state, device_id)) # 更新设备状态
- conn.commit()
- conn.close()
-
- return jsonify({"message": "设备状态已更新"}), 200 # 返回成功消息
-
- @app.route('/weather', methods=['GET'])
- def get_weather():
- """获取天气信息"""
- weather_data = get_weather_data() # 调用获取天气数据的函数
- if weather_data:
- return jsonify(weather_data) # 返回天气数据
- else:
- return jsonify({"error": "无法获取天气数据"}), 500
-
- if __name__ == "__main__":
- init_db() # 初始化数据库
- app.run(host='0.0.0.0', port=5000) # 启动Flask应用

首先,创建一个HTML文件来构建用户界面:
- <!DOCTYPE html>
- <html lang="zh">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>智能家居控制中心</title>
- <link rel="stylesheet" href="style.css"> <!-- 引入CSS样式 -->
- <script src="script.js" defer></script> <!-- 引入JavaScript文件 -->
- </head>
- <body>
- <h1>智能家居控制中心</h1>
- <h2>设备状态</h2>
- <div id="device-list"></div> <!-- 显示设备状态的区域 -->
- <button id="refresh-button">刷新设备状态</button> <!-- 刷新按钮 -->
-
- <h2>当前天气</h2>
- <div id="weather-info"></div> <!-- 显示天气信息的区域 -->
-
- <script>
- // 页面加载时自动获取设备状态和天气信息
- window.onload = function() {
- fetchDevices();
- fetchWeather();
- };
- </script>
- </body>
- </html>

代码说明:
fetchDevices()
和fetchWeather()
函数以获取设备状态和天气信息。接下来,创建一个CSS文件来美化页面。
- body {
- font-family: Arial, sans-serif; /* 设置字体 */
- margin: 0;
- padding: 20px;
- background-color: #f4f4f4; /* 背景颜色 */
- }
-
- h1 {
- color: #333; /* 标题颜色 */
- }
-
- h2 {
- color: #555; /* 副标题颜色 */
- }
-
- #device-list {
- margin-top: 20px; /* 设备列表的间距 */
- }
-
- .device {
- background-color: #fff; /* 每个设备的背景颜色 */
- border: 1px solid #ccc; /* 边框样式 */
- border-radius: 5px;
- padding: 10px;
- margin-bottom: 10px; /* 设备之间的间距 */
- }
-
- button {
- padding: 10px 15px; /* 按钮内边距 */
- background-color: #007bff; /* 按钮背景颜色 */
- border: none;
- color: white; /* 按钮文本颜色 */
- border-radius: 5px; /* 按钮圆角 */
- cursor: pointer; /* 鼠标悬停时显示为手型 */
- }
-
- button:hover {
- background-color: #0056b3; /* 鼠标悬停时的背景颜色 */
- }

代码说明:
.device
类用于设置设备状态显示的样式。- const apiUrl = "http://<树莓派IP>:5000/devices"; // 替换为你的树莓派IP地址
- const weatherApiUrl = "http://<树莓派IP>:5000/weather"; // 替换为你的树莓派IP地址
-
- // 页面加载时自动获取设备状态和天气信息
- window.onload = function() {
- fetchDevices();
- fetchWeather();
- };
-
- // 获取设备状态的函数
- async function fetchDevices() {
- try {
- const response = await fetch(apiUrl); // 发起GET请求获取设备状态
- const devices = await response.json(); // 解析JSON响应
- displayDevices(devices); // 显示设备状态
- } catch (error) {
- console.error("获取设备状态失败:", error); // 错误处理
- }
- }
-
- // 显示设备状态的函数
- function displayDevices(devices) {
- const deviceList = document.getElementById("device-list");
- deviceList.innerHTML = ""; // 清空之前的内容
-
- devices.forEach(device => {
- const deviceDiv = document.createElement("div");
- deviceDiv.className = "device"; // 设置设备样式
- deviceDiv.innerHTML = `
- <h2>${device[1]}</h2> <!-- 设备名称 -->
- <p>状态: ${device[2] === 1 ? "开" : "关"}</p> <!-- 设备状态 -->
- <button onclick="toggleDevice(${device[0]}, ${device[2]})">
- ${device[2] === 1 ? "关闭" : "打开"}
- </button>
- `; // 创建设备状态和控制按钮
- deviceList.appendChild(deviceDiv); // 添加到设备列表中
- });
- }
-
- // 切换设备状态的函数
- async function toggleDevice(deviceId, currentState) {
- const newState = currentState === 1 ? 0 : 1; // 切换状态
- try {
- const response = await fetch(`http://<树莓派IP>:5000/devices/${deviceId}`, { // 替换为你的树莓派IP
- method: 'POST', // 指定请求方法为POST
- headers: {
- 'Content-Type': 'application/json', // 设置请求头为JSON格式
- },
- body: JSON.stringify({ state: newState }) // 将新状态转为JSON格式
- });
-
- if (response.ok) {
- fetchDevices(); // 更新设备状态
- alert("设备状态已更新!"); // 提示用户设备状态已更新
- } else {
- alert("设备状态更新失败!"); // 提示用户更新失败
- }
- } catch (error) {
- console.error("更新设备状态时出错:", error); // 错误处理
- }
- }
-
- // 获取天气信息的函数
- async function fetchWeather() {
- try {
- const response = await fetch(weatherApiUrl); // 发起GET请求获取天气信息
- const weatherData = await response.json(); // 解析JSON响应
- displayWeather(weatherData); // 显示天气信息
- } catch (error) {
- console.error("获取天气信息失败:", error); // 错误处理
- }
- }
-
- // 显示天气信息的函数
- function displayWeather(weatherData) {
- const weatherInfo = document.getElementById("weather-info");
- weatherInfo.innerHTML = ""; // 清空之前的内容
-
- // 显示天气信息
- if (weatherData) {
- weatherInfo.innerHTML = `
- <p>温度: ${weatherData.temperature} °C</p>
- <p>天气: ${weatherData.weather}</p>
- <p>湿度: ${weatherData.humidity} %</p>
- `;
- } else {
- weatherInfo.innerHTML = "<p>无法获取天气信息</p>"; // 显示错误信息
- }
- }
-
- // 刷新设备状态的按钮功能
- document.getElementById("refresh-button").addEventListener("click", function() {
- fetchDevices(); // 刷新设备状态
- fetchWeather(); // 刷新天气信息
- });

代码说明:
fetchDevices()
:
fetch
API发起GET请求,获取当前设备的状态数据。displayDevices(devices)
函数将设备信息显示在页面上。displayDevices(devices)
:
div
元素来展示设备的名称、状态(开/关)和对应的控制按钮。onclick
事件绑定到toggleDevice(deviceId, currentState)
函数,以便用户可以通过点击按钮来切换设备的状态。div
元素添加到设备列表中。toggleDevice(deviceId, currentState)
:
fetch
API发起POST请求,向后端发送更新设备状态的请求。http://<树莓派IP>:5000/devices/${deviceId}
,其中deviceId
是要控制的设备的ID。fetchDevices()
刷新设备状态并显示更新后的信息,同时弹出提示框通知用户设备状态已更新。fetchWeather()
:
fetch
API发起GET请求,获取天气信息。displayWeather(weatherData)
函数将天气信息显示在页面上。displayWeather(weatherData)
:
刷新按钮功能:
fetchDevices()
和fetchWeather()
函数,以获取最新的设备状态和天气信息,确保用户界面始终显示最新的数据。通过本项目,我们成功搭建了一个基于树莓派的AI接入文心一言智能家居中控系统。该系统能够实时获取环境数据,并根据获取的天气信息自动控制家居设备。同时,用户可以通过可视化界面方便地查看设备状态和手动控制设备开关。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。