#include <Wire.h>const int BH1750address = 0x23; // BH1750默认I2C地址void setup() { Wire.begin(); // 初始化I2C通信 Serial.begin(9600); // 设置BH1750为连续高分辨率模式 Wire.beginTransmission(BH1750address); Wire.write(0x10); Wire.endTransmission(); delay(100);}void loop() { Wire.beginTransmission(BH1750address); Wire.write(0x00); Wire.endTransmission(); delay(120); // 等待测量完成 if(Wire.requestFrom(BH1750address, 2)) { int val = Wire.read() << 8; val |= Wire.read(); float lux = val / 1.2; // 转换为光照强度(lux) Serial.print("光照强度: "); Serial.print(lux); Serial.println(" lux"); } delay(1000);}#define MoisturePin 14 // 定义土壤湿度传感器引脚void setup() { Serial.begin(115200); // ESP32-S3常用波特率}void loop() { int soilMoistureValue = analogRead(MoisturePin); // 读取原始模拟值(0-4095) // 转换为百分比(需要根据实际校准调整) int moisturePercent = map(soilMoistureValue, 4095, 0, 0, 100); Serial.print("土壤湿度值: "); Serial.print(soilMoistureValue); Serial.print(" (0-4095) | "); Serial.print("湿度百分比: "); Serial.print(moisturePercent); Serial.println(" %"); delay(1000);}#include <esp_sleep.h>#define DHT_PIN 21 // DHT11温湿度传感器引脚#define SLEEP_INTERVAL 60000 // 1分钟睡眠间隔void setup() { Serial.begin(115200); // 配置GPIO为输入并启用内部上拉 pinMode(DHT_PIN, INPUT_PULLUP);}void loop() { // 采集传感器数据 // ... 此处添加传感器读取代码 // 设置定时器唤醒 esp_sleep_enable_timer_wakeup(SLEEP_INTERVAL); // 进入深度睡眠 esp_deep_sleep_start();}均值滤波:对连续多次采样值求平均
中值滤波:取连续采样值的中值
限幅滤波:限制相邻两次采样值的最大变化量
const int sampleCount = 10; // 采样次数int samples[sampleCount];int sampleIndex = 0;float getFilteredValue() { // 1. 采集原始数据 int rawValue = analogRead(MoisturePin); // 2. 限幅滤波 if (sampleIndex > 0) { int diff = abs(rawValue - samples[sampleIndex-1]); if (diff > 50) { // 限制最大变化量为50 rawValue = samples[sampleIndex-1] + (diff > 0 ? 50 : -50); } } // 3. 存储并更新采样缓冲区 samples[sampleIndex] = rawValue; sampleIndex = (sampleIndex + 1) % sampleCount; // 4. 计算中值 int sorted[sampleCount]; memcpy(sorted, samples, sizeof(sorted)); for (int i = 0; i < sampleCount; i++) { for (int j = i + 1; j < sampleCount; j++) { if (sorted[i] > sorted[j]) { int temp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = temp; } } } // 5. 计算均值(去除最高和最低值) int sum = 0; for (int i = 1; i < sampleCount - 1; i++) { sum += sorted[i]; } return (float)sum / (sampleCount - 2);}数据清洗:去除异常值和噪声,确保数据质量
特征提取:从原始传感器数据中提取关键特征
阈值检测:实时监测环境参数是否超出安全范围
本地决策:基于预设规则自动控制灌溉、通风等设备
import numpy as npdef data_preprocessing(raw_data): """ 农业传感器数据预处理函数 参数: raw_data - 原始传感器数据字典 返回: 处理后的数据字典 """ processed_data = {} # 1. 温度数据处理(单位:℃) temp_data = raw_data['temperature'] # 去除异常值(3σ原则) temp_cleaned = remove_outliers(temp_data, 3) # 计算平均值 temp_avg = np.mean(temp_cleaned) # 计算标准差 temp_std = np.std(temp_cleaned) processed_data['temperature'] = { 'avg': temp_avg, 'std': temp_std, 'cleaned_data': temp_cleaned.tolist() } # 2. 湿度数据处理(单位:%RH) humidity_data = raw_data['humidity'] humidity_cleaned = remove_outliers(humidity_data, 2.5) humidity_avg = np.mean(humidity_cleaned) processed_data['humidity'] = { 'avg': humidity_avg, 'cleaned_data': humidity_cleaned.tolist() } # 3. 土壤湿度处理(单位:%) soil_moisture = raw_data['soil_moisture'] # 应用土壤类型特定的校准公式 calibrated_moisture = soil_calibration(soil_moisture, soil_type='clay') processed_data['soil_moisture'] = { 'calibrated': calibrated_moisture, 'raw': soil_moisture } # 4. 计算环境舒适度指数 comfort_index = calculate_comfort_index(temp_avg, humidity_avg) processed_data['comfort_index'] = comfort_index return processed_datadef remove_outliers(data, sigma_threshold): """使用3σ原则去除异常值""" mean = np.mean(data) std = np.std(data) filtered = data[(data >= mean - sigma_threshold * std) & (data <= mean + sigma_threshold * std)] return filtereddef soil_calibration(raw_moisture, soil_type): """土壤湿度校准函数""" # 不同土壤类型的校准参数 calibration_params = { 'sand': {'a': 0.85, 'b': 5}, 'loam': {'a': 1.0, 'b': 0}, 'clay': {'a': 1.15, 'b': -8} } if soil_type in calibration_params: a, b = calibration_params[soil_type] return a * raw_moisture + b else: return raw_moisturedef calculate_comfort_index(temp, humidity): """计算环境舒适度指数(0-100分)""" # 基于温湿度的舒适度计算公式 # 最适温度:20-25℃,最适湿度:40-60%RH temp_score = max(0, min(100, 100 - abs(temp - 22.5) * 4)) humidity_score = max(0, min(100, 100 - abs(humidity - 50) * 2)) return (temp_score * 0.6 + humidity_score * 0.4)import paho.mqtt.client as mqttimport jsonimport time# MQTT服务器配置MQTT_BROKER = "mqtt.example.com"MQTT_PORT = 1883MQTT_USER = "username"MQTT_PASSWORD = "password"DEVICE_ID = "farm-001"# 创建MQTT客户端client = mqtt.Client(client_id=DEVICE_ID)client.username_pw_set(MQTT_USER, MQTT_PASSWORD)def on_connect(client, userdata, flags, rc): """连接回调函数""" if rc == 0: print("已连接到MQTT服务器") # 订阅控制指令主题 client.subscribe(f"{DEVICE_ID}/commands") else: print(f"连接失败,错误码:{rc}")def on_message(client, userdata, msg): """消息接收回调函数""" print(f"接收到指令:{msg.topic} - {msg.payload.decode()}") # 处理控制指令 process_command(msg.payload.decode())def process_command(command): """处理控制指令""" try: cmd_data = json.loads(command) if cmd_data['command'] == 'irrigation': status = cmd_data['status'] if status == 'on': print("开启灌溉系统") # 执行灌溉控制逻辑 elif status == 'off': print("关闭灌溉系统") except Exception as e: print(f"指令解析错误:{e}")# 设置回调函数client.on_connect = on_connectclient.on_message = on_message# 连接到MQTT服务器client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)# 启动MQTT循环client.loop_start()# 模拟传感器数据发布while True: # 生成模拟数据 sensor_data = { "timestamp": int(time.time()), "device_id": DEVICE_ID, "temperature": 25.5, "humidity": 60.2, "soil_moisture": 45.3, "light_intensity": 800 } # 发布到数据主题 topic = f"{DEVICE_ID}/data" payload = json.dumps(sensor_data) client.publish(topic, payload, qos=1) print(f"已发布数据:{payload}") time.sleep(60) # 每分钟发布一次import阿里云IoT设备SDK# 设备认证信息PRODUCT_KEY = "your_product_key"DEVICE_NAME = "your_device_name" DEVICE_SECRET = "your_device_secret"# 创建设备实例device = 阿里云IoT设备SDK.Device(PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET)# 连接到云端device.connect()# 上报属性数据property_data = { "Temperature": 25.5, "Humidity": 60.2, "SoilMoisture": 45.3}device.post_properties(property_data)# 接收云端指令def on_command(command): print(f"收到云端指令:{command}") # 执行相应的控制逻辑device.on_command = on_commandfrom influxdb import InfluxDBClient# InfluxDB配置INFLUXDB_HOST = "localhost"INFLUXDB_PORT = 8086INFLUXDB_USER = "admin"INFLUXDB_PASSWORD = "password"INFLUXDB_DBNAME = "agriculture"# 创建客户端client = InfluxDBClient(INFLUXDB_HOST, INFLUXDB_PORT, INFLUXDB_USER, INFLUXDB_PASSWORD)# 创建数据库client.create_database(INFLUXDB_DBNAME)client.switch_database(INFLUXDB_DBNAME)# 准备写入数据点def write_sensor_data(sensor_data): """写入传感器数据到InfluxDB""" json_body = [ { "measurement": "environmental_data", "tags": { "device_id": sensor_data["device_id"], "location": "greenhouse_1" }, "time": sensor_data["timestamp"], "fields": { "temperature": sensor_data["temperature"], "humidity": sensor_data["humidity"], "soil_moisture": sensor_data["soil_moisture"], "light_intensity": sensor_data["light_intensity"] } } ] try: client.write_points(json_body) print("数据写入成功") except Exception as e: print(f"数据写入失败:{e}")添加 InfluxDB 数据源,配置连接参数
创建仪表板,添加以下面板:
温度趋势图(折线图)
湿度仪表盘(Gauge)
土壤湿度热力图
环境参数统计表
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>农业环境监测仪表板</title> <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.1/dist/echarts.min.js"></script></head><body> <div id="tempChart" style="width: 800px; height: 400px;"></div> <div id="humidityChart" style="width: 800px; height: 400px;"></div> <script> // 初始化温度图表 var tempChart = echarts.init(document.getElementById('tempChart')); var humidityChart = echarts.init(document.getElementById('humidityChart')); // 温度数据(模拟) var tempData = { xAxis: { type: 'category', data: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'] }, yAxis: { type: 'value', name: '温度 (℃)' }, series: [{ data: [15.2, 13.5, 12.8, 16.5, 22.3, 25.8, 20.1, 17.6], type: 'line', smooth: true }] }; // 湿度数据(模拟) var humidityData = { xAxis: { type: 'category', data: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'] }, yAxis: { type: 'value', name: '湿度 (%)' }, series: [{ data: [85, 88, 92, 75, 68, 62, 70, 78], type: 'line', smooth: true }] }; tempChart.setOption(tempData); humidityChart.setOption(humidityData); </script></body></html>from flask import Flask, jsonify, request, render_templateimport sqlite3app = Flask(__name__)# 数据库配置(使用SQLite)DATABASE = 'agriculture.db'def get_db(): """获取数据库连接""" db = getattr(g, '_database', None) if db is None: db = g._database = sqlite3.connect(DATABASE) return db@app.teardown_appcontextdef close_connection(exception): """关闭数据库连接""" db = getattr(g, '_database', None) if db is not None: db.close()@app.route('/')def index(): """渲染主页""" return render_template('index.html')@app.route('/api/sensors', methods=['GET'])def get_sensors(): """获取传感器列表""" cursor = get_db().cursor() cursor.execute("SELECT id, name, type, location FROM sensors") sensors = cursor.fetchall() return jsonify([{ 'id': row[0], 'name': row[1], 'type': row[2], 'location': row[3] } for row in sensors])@app.route('/api/data/<int:sensor_id>', methods=['GET'])def get_sensor_data(sensor_id): """获取指定传感器的历史数据""" cursor = get_db().cursor() cursor.execute(""" SELECT timestamp, value FROM sensor_data WHERE sensor_id = ? ORDER BY timestamp DESC LIMIT 100 """, (sensor_id,)) data = cursor.fetchall() return jsonify([{ 'timestamp': row[0], 'value': row[1] } for row in data])if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)感知层:部署温湿度传感器、光照传感器、CO2 传感器、土壤传感器等
网络层:采用 WiFi 或 LoRa 技术实现数据传输
应用层:提供数据存储、分析、可视化和远程控制功能
// 温室环境监测系统 - Arduino代码#include <Wire.h>#include <DHT.h>#include <SPI.h>// 传感器定义#define DHT_PIN 2 // DHT11温湿度传感器#define DHT_TYPE DHT11DHT dht(DHT_PIN, DHT_TYPE);#define CO2_PIN A0 // CO2传感器模拟输出#define LIGHT_PIN A1 // 光照传感器模拟输出// 执行器定义#define FAN_PIN 9 // 风扇控制#define HEATER_PIN 10 // 加热器控制#define SHADING_PIN 11 // 遮阳帘控制#define IRRIGATION_PIN 12 // 灌溉控制// 环境参数设定值float target_temp = 22.5; // 目标温度 (℃)float target_humidity = 50; // 目标湿度 (%)float target_light = 800; // 目标光照强度 (lux)float co2_threshold = 1500; // CO2浓度阈值 (ppm)void setup() { Serial.begin(9600); dht.begin(); // 初始化执行器引脚 pinMode(FAN_PIN, OUTPUT); pinMode(HEATER_PIN, OUTPUT); pinMode(SHADING_PIN, OUTPUT); pinMode(IRRIGATION_PIN, OUTPUT); // 初始状态设置 digitalWrite(FAN_PIN, LOW); digitalWrite(HEATER_PIN, LOW); digitalWrite(SHADING_PIN, LOW); digitalWrite(IRRIGATION_PIN, LOW);}void loop() { // 1. 数据采集 float temperature = dht.readTemperature(); float humidity = dht.readHumidity(); int light_value = analogRead(LIGHT_PIN); int co2_value = analogRead(CO2_PIN); // 转换为实际物理量 float light_intensity = light_value * 50; // 假设传感器输出0-5V对应0-10000 lux float co2_concentration = map(co2_value, 0, 1023, 0, 5000); // 假设0-5V对应0-5000 ppm // 2. 环境控制逻辑 environmental_control(temperature, humidity, light_intensity, co2_concentration); // 3. 数据输出 Serial.print("温度: "); Serial.print(temperature); Serial.print("℃ | 湿度: "); Serial.print(humidity); Serial.print("% | 光照: "); Serial.print(light_intensity); Serial.print(" lux | CO2: "); Serial.print(co2_concentration); Serial.println(" ppm"); delay(60000); // 每分钟采集一次}void environmental_control(float temp, float humidity, float light, float co2) { // 温度控制 if (temp > target_temp + 1) { digitalWrite(FAN_PIN, HIGH); // 开风扇 digitalWrite(HEATER_PIN, LOW); // 关加热器 } else if (temp < target_temp - 1) { digitalWrite(FAN_PIN, LOW); // 关风扇 digitalWrite(HEATER_PIN, HIGH); // 开加热器 } else { digitalWrite(FAN_PIN, LOW); digitalWrite(HEATER_PIN, LOW); } // 湿度控制(简化逻辑) if (humidity < target_humidity - 5) { digitalWrite(IRRIGATION_PIN, HIGH); // 开启喷雾增湿 } else { digitalWrite(IRRIGATION_PIN, LOW); // 关闭喷雾 } // 光照控制 if (light < target_light) { digitalWrite(SHADING_PIN, LOW); // 收起遮阳帘 } else { digitalWrite(SHADING_PIN, HIGH); // 展开遮阳帘 } // CO2浓度监测(仅报警) if (co2 > co2_threshold) { Serial.println("警告:CO2浓度过高!"); }}实时监测土壤湿度、温度、EC 值
支持多种灌溉模式(定时、定量、自动)
具备故障检测和报警功能
支持远程控制和数据查询
// ESP32精准灌溉控制系统#include <WiFi.h>#include <PubSubClient.h>// WiFi配置const char* ssid = "your_wifi_ssid";const char* password = "your_wifi_password";// MQTT配置const char* mqtt_server = "mqtt.example.com";const int mqtt_port = 1883;const char* mqtt_user = "username";const char* mqtt_password = "password";const char* device_id = "irrigation-001";WiFiClient espClient;PubSubClient client(espClient);// 传感器定义#define SOIL_MOISTURE_PIN 34 // 土壤湿度传感器#define SOIL_TEMP_PIN 35 // 土壤温度传感器#define WATER_LEVEL_PIN 14 // 水位传感器#define VALVE_CONTROL_PIN 2 // 阀门控制// 灌溉参数float soil_moisture_threshold = 40; // 土壤湿度阈值 (%)int irrigation_duration = 60; // 单次灌溉时长 (秒)int water_level_min = 10; // 最低水位阈值 (cm)void setup() { Serial.begin(115200); // 初始化WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi连接成功"); // 初始化MQTT client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); connect_mqtt(); // 初始化传感器引脚 pinMode(SOIL_MOISTURE_PIN, INPUT); pinMode(SOIL_TEMP_PIN, INPUT); pinMode(WATER_LEVEL_PIN, INPUT); pinMode(VALVE_CONTROL_PIN, OUTPUT); digitalWrite(VALVE_CONTROL_PIN, LOW);}void loop() { if (!client.connected()) { reconnect(); } client.loop(); // 每10分钟进行一次灌溉检查 static unsigned long last_check_time = 0; if (millis() - last_check_time > 600000) { last_check_time = millis(); // 1. 数据采集 int soil_moisture_raw = analogRead(SOIL_MOISTURE_PIN); int soil_temp_raw = analogRead(SOIL_TEMP_PIN); int water_level_raw = analogRead(WATER_LEVEL_PIN); // 2. 数据转换(需要根据实际传感器特性校准) float soil_moisture = map(soil_moisture_raw, 0, 4095, 0, 100); float soil_temp = map(soil_temp_raw, 0, 4095, 0, 50); float water_level = map(water_level_raw, 0, 4095, 0, 50); // 3. 灌溉决策 if (soil_moisture < soil_moisture_threshold && water_level > water_level_min) { start_irrigation(); } // 4. 数据上报 publish_sensor_data(soil_moisture, soil_temp, water_level); }}void start_irrigation() { Serial.println("开始灌溉..."); digitalWrite(VALVE_CONTROL_PIN, HIGH); // 打开阀门 delay(irrigation_duration * 1000); // 灌溉指定时长 digitalWrite(VALVE_CONTROL_PIN, LOW); // 关闭阀门 Serial.println("灌溉结束"); // 上报灌溉事件 publish_irrigation_event(irrigation_duration);}void publish_sensor_data(float moisture, float temp, float level) { DynamicJsonDocument doc(1024); doc["device_id"] = device_id; doc["timestamp"] = millis() / 1000; doc["soil_moisture"] = moisture; doc["soil_temperature"] = temp; doc["water_level"] = level; char jsonBuffer[1024]; serializeJson(doc, jsonBuffer); client.publish("irrigation/sensors", jsonBuffer);}void publish_irrigation_event(int duration) { DynamicJsonDocument doc(512); doc["device_id"] = device_id; doc["timestamp"] = millis() / 1000; doc["event"] = "irrigation_started"; doc["duration"] = duration; char jsonBuffer[512]; serializeJson(doc, jsonBuffer); client.publish("irrigation/events", jsonBuffer);}void callback(char* topic, byte* payload, unsigned int length) { Serial.print("接收到命令: "); Serial.println(topic); String command(topic); if (command == "irrigation/control") { String payloadStr((char*)payload); if (payloadStr == "start") { start_irrigation(); } else if (payloadStr == "stop") { digitalWrite(VALVE_CONTROL_PIN, LOW); } }}void connect_mqtt() { while (!client.connected()) { Serial.print("连接MQTT..."); if (client.connect(device_id, mqtt_user, mqtt_password)) { Serial.println("连接成功"); client.subscribe("irrigation/control"); } else { Serial.print("连接失败,重试中..."); delay(5000); } }}void reconnect() { while (!client.connected()) { connect_mqtt(); }}气象监测站:部署风速、风向、雨量、温度、湿度等传感器
数据传输网络:采用 GPRS 或 NB-IoT 技术将数据传输到云端
预警算法:基于阈值检测和机器学习模型进行灾害预测
预警发布:通过短信、APP 推送等方式发送预警信息
import numpy as npimport pandas as pdfrom datetime import datetime, timedeltaimport matplotlib.pyplot as pltimport warningswarnings.filterwarnings('ignore')# 模拟的气象数据(历史数据 + 实时数据)def generate_meteorological_data(): """生成模拟的气象数据""" # 时间序列(过去7天 + 今天) timestamps = pd.date_range( start=datetime(2026, 1, 1), periods=7*24*4 + 24, # 7天历史数据 + 1天实时数据 freq='15T' ) # 温度数据(模拟冬季气温变化) base_temp = 10 daily_variation = 8 noise = np.random.normal(0, 1, len(timestamps)) temperature = base_temp + daily_variation * np.sin(2 * np.pi * np.arange(len(timestamps)) / (24*4)) + noise # 湿度数据 humidity = 60 + 20 * np.sin(2 * np.pi * np.arange(len(timestamps)) / (24*4)) + np.random.normal(0, 2, len(timestamps)) # 风速数据(m/s) wind_speed = 3 + 2 * np.sin(2 * np.pi * np.arange(len(timestamps)) / (24*4)) + np.random.normal(0, 0.5, len(timestamps)) # 降雨量(mm/15分钟) rainfall = np.zeros(len(timestamps)) # 设置一些降雨事件 rainfall[200:220] = np.random.uniform(0.5, 2, 20) # 第8天上午降雨 rainfall[300:320] = np.random.uniform(1, 3, 20) # 第9天下午降雨 # 气压数据(hPa) pressure = 1015 + 5 * np.sin(2 * np.pi * np.arange(len(timestamps)) / (24*4)) + np.random.normal(0, 0.5, len(timestamps)) df = pd.DataFrame({ 'timestamp': timestamps, 'temperature': temperature, 'humidity': humidity, 'wind_speed': wind_speed, 'rainfall': rainfall, 'pressure': pressure }) return df# 生成数据df = generate_meteorological_data()# 1. 数据预处理def preprocess_data(df): """数据预处理函数""" # 计算一些衍生特征 df['temp_change_1h'] = df['temperature'].diff(4) # 1小时温度变化 df['temp_change_3h'] = df['temperature'].diff(12) # 3小时温度变化 df['wind_gust'] = df['wind_speed'].rolling(window=4).max() # 阵风(1小时内最大值) df['rainfall_3h'] = df['rainfall'].rolling(window=12).sum() # 3小时累计降雨量 # 处理缺失值 df = df.fillna(method='ffill') # 前向填充 df = df.fillna(method='bfill') # 后向填充 return dfdf_processed = preprocess_data(df)# 2. 预警算法定义def weather_warning_system(df): """气象灾害预警系统""" warnings = [] # 最新数据 latest = df.iloc[-1] # 低温预警(霜冻风险) if latest['temperature'] < 2 and latest['humidity'] > 80: warnings.append({ 'type': '霜冻预警', 'level': '黄色', 'description': f'气温降至{latest["temperature"]:.1f}℃,湿度{latest["humidity"]:.0f}%,存在霜冻风险', 'recommendation': '建议覆盖地膜或搭建防冻设施' }) # 大风预警 if latest['wind_gust'] > 15: # 风速超过15m/s(6级风) level = '黄色' if latest['wind_gust'] < 20 else '橙色' if latest['wind_gust'] < 25 else '红色' warnings.append({ 'type': '大风预警', 'level': level, 'description': f'阵风达到{latest["wind_gust"]:.1f}m/s({int(latest["wind_gust"]*3.6)}km/h)', 'recommendation': '加固大棚,清理田间杂物' }) # 暴雨预警 if latest['rainfall_3h'] > 50: # 3小时降雨量超过50mm level = '黄色' if latest['rainfall_3h'] < 100 else '橙色' warnings.append({ 'type': '暴雨预警', 'level': level, 'description': f'3小时降雨量达{latest["rainfall_3h"]:.1f}mm', 'recommendation': '检查排水系统,及时排涝' }) # 温度骤降预警 if latest['temp_change_3h'] < -5: # 3小时降温超过5℃ warnings.append({ 'type': '强降温预警', 'level': '蓝色', 'description': f'3小时内降温{abs(latest["temp_change_3h"]):.1f}℃', 'recommendation': '注意作物保暖,适当增加覆盖' }) return warnings# 3. 实时预警检测warnings = weather_warning_system(df_processed)# 4. 预警信息发布def send_warning_notifications(warnings, farmer_phone='13812345678'): """发送预警通知""" print("=== 农业气象灾害预警系统 ===") print(f"预警时间: {datetime.now().strftime('%Y年%m月%d日 %H:%M')}") print("-" * 50) if not warnings: print("当前无预警信息") return for i, warn in enumerate(warnings, 1): print(f"{i}. {warn['type']} (级别: {warn['level']})") print(f" 描述: {warn['description']}") print(f" 建议: {warn['recommendation']}") print() # 模拟短信发送 if warnings: print(f"已向农户{farmer_phone}发送{len(warnings)}条预警信息")send_warning_notifications(warnings)# 5. 可视化历史数据和预警点def plot_weather_data_with_warnings(df, warnings): """绘制气象数据图表并标注预警点""" fig, axes = plt.subplots(3, 2, figsize=(15, 12)) fig.suptitle('农业气象监测与预警系统', fontsize=16, fontweight='bold') # 温度 ax1 = axes[0, 0] ax1.plot(df['timestamp'], df['temperature'], 'b-', label='温度(℃)') ax1.axhline(y=2, color='r', linestyle='--', label='霜冻警戒线') ax1.set_title('温度变化') ax1.set_ylabel('温度 (℃)') ax1.grid(True, alpha=0.3) ax1.legend() # 湿度 ax2 = axes[0, 1] ax2.plot(df['timestamp'], df['humidity'], 'g-', label='湿度(%)') ax2.set_title('湿度变化') ax2.set_ylabel('湿度 (%)') ax2.grid(True, alpha=0.3) ax2.legend() # 风速 ax3 = axes[1, 0] ax3.plot(df['timestamp'], df['wind_speed'], 'orange', label='风速(m/s)') ax3.plot(df['timestamp'], df['wind_gust'], 'r-', label='阵风(m/s)') ax3.set_title('风速变化') ax3.set_ylabel('风速 (m/s)') ax3.grid(True, alpha=0.3) ax3.legend() # 降雨量 ax4 = axes[1, 1] ax4.bar(df['timestamp'], df['rainfall'], width=0.01, label='15分钟降雨量') ax4.set_title('降雨情况') ax4.set_ylabel('降雨量 (mm)') ax4.grid(True, alpha=0.3) ax4.legend() # 累计降雨量 ax5 = axes[2, 0] ax5.plot(df['timestamp'], df['rainfall_3h'], 'purple', label='3小时累计降雨量') ax5.axhline(y=50, color='orange', linestyle='--', label='暴雨警戒线') ax5.set_title('累计降雨量') ax5.set_ylabel('降雨量 (mm)') ax5.set_xlabel('时间') ax5.grid(True, alpha=0.3) ax5.legend() # 预警标注 ax6 = axes[2, 1] ax6.axis('off') warning_text = "预警信息汇总:\n" + "-" * 30 + "\n" for i, warn in enumerate(warnings, 1): warning_text += f"{i}. {warn['type']} (级别: {warn['level']})\n" warning_text += f" {warn['description']}\n" warning_text += f" 建议: {warn['recommendation']}\n" + "-" * 30 + "\n" ax6.text(0.05, 0.95, warning_text, transform=ax6.transAxes, verticalalignment='top', fontsize=10, bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5)) plt.tight_layout() plt.show()# 绘制图表plot_weather_data_with_warnings(df_processed, warnings)# 6. 保存预警记录到数据库def save_warning_to_db(warnings): """将预警记录保存到数据库""" import sqlite3 conn = sqlite3.connect('weather_warnings.db') c = conn.cursor() # 创建表 c.execute('''CREATE TABLE IF NOT EXISTS warnings (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT, warning_type TEXT, level TEXT, description TEXT, recommendation TEXT)''') # 插入数据 current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') for warn in warnings: c.execute('''INSERT INTO warnings (timestamp, warning_type, level, description, recommendation) VALUES (?, ?, ?, ?, ?)''', (current_time, warn['type'], warn['level'], warn['description'], warn['recommendation'])) conn.commit() conn.close()save_warning_to_db(warnings)生理指标监测:茎流传感器、叶绿素传感器、叶面温度传感器
形态指标监测:植株高度、茎粗、叶面积指数(LAI)
健康状况监测:病虫害识别、营养缺乏诊断
环境因子监测:光照、CO2、土壤养分
import cv2import numpy as npimport matplotlib.pyplot as pltfrom datetime import datetimeimport json# 1. 图像预处理函数def preprocess_image(image_path): """图像预处理""" # 读取图像 img = cv2.imread(image_path) # 转换为RGB(用于matplotlib显示) img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换为HSV颜色空间 img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义绿色植物的HSV范围 lower_green = np.array([35, 43, 46]) upper_green = np.array([77, 255, 255]) # 创建掩码 mask = cv2.inRange(img_hsv, lower_green, upper_green) # 形态学操作(开运算去除噪声) kernel = np.ones((5, 5), np.uint8) mask_clean = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=2) return img_rgb, mask_clean# 2. 作物生长指标计算def calculate_growth_metrics(mask, original_image): """计算作物生长指标""" metrics = {} # 1. 植被覆盖度(%) total_pixels = mask.size green_pixels = np.sum(mask > 0) vegetation_coverage = (green_pixels / total_pixels) * 100 metrics['vegetation_coverage'] = vegetation_coverage # 2. 叶面积指数(LAI)估算(简化模型) # 基于绿色像素比例和图像尺寸 image_area_m2 = 1.0 # 假设图像覆盖1平方米 lai = vegetation_coverage * 0.01 * 3.5 # 经验系数 metrics['lai'] = lai # 3. 植株密度估算(基于连通区域分析) num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(mask_clean) plant_density = (num_labels - 1) / image_area_m2 # 减去背景 metrics['plant_density'] = plant_density # 4. 绿色度指数(归一化植被指数NDVI的简化版) # 从原始图像中提取绿色通道 green_channel = original_image[:, :, 1] # 计算绿色度指数(0-100) greenness_index = np.mean(green_channel[mask > 0]) / 255 * 100 metrics['greenness_index'] = greenness_index return metrics# 3. 病虫害检测(简化版)def detect_pest_disease(image, mask): """病虫害检测""" # 转换为灰度图像 gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 计算图像熵(衡量图像复杂度) hist = cv2.calcHist([gray], [0], mask, [256], [0, 256]) hist = hist / hist.sum() entropy = -np.sum(hist[hist > 0] * np.log2(hist[hist > 0])) # 基于熵值判断是否存在病虫害(阈值需要根据实际情况调整) if entropy > 6.5: return { 'status': '疑似病虫害', 'confidence': (entropy - 6.5) * 20, # 置信度百分比 'description': f'图像复杂度较高(熵值{entropy:.2f}),可能存在病虫害' } else: return { 'status': '健康', 'confidence': 100, 'description': '作物生长状态良好' }# 4. 主程序:处理图像并生成报告def process_crop_image(image_path): """处理作物图像并生成监测报告""" # 图像预处理 img_rgb, mask_clean = preprocess_image(image_path) # 计算生长指标 growth_metrics = calculate_growth_metrics(mask_clean, img_rgb) # 病虫害检测 health_status = detect_pest_disease(img_rgb, mask_clean) # 生成综合报告 report = { 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'image_path': image_path, 'growth_metrics': growth_metrics, 'health_status': health_status, 'recommendations': [] } # 添加建议 if growth_metrics['lai'] < 2.0: report['recommendations'].append('叶面积指数偏低,建议增加氮肥施用量') elif growth_metrics['lai'] > 4.5: report['recommendations'].append('叶面积指数过高,建议适当疏叶或控制水分') if health_status['status'] != '健康': report['recommendations'].append('发现病虫害迹象,建议及时防治') return report, img_rgb, mask_clean# 5. 示例运行if __name__ == "__main__": # 示例图像路径 image_path = "crop_images/crop_20260110_1430.jpg" # 处理图像 report, img_rgb, mask = process_crop_image(image_path) # 打印报告 print("=== 作物生长状态监测报告 ===") print(json.dumps(report, ensure_ascii=False, indent=2)) # 显示结果 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) # 原始图像 ax1.imshow(img_rgb) ax1.set_title('原始图像') ax1.axis('off') # 植被掩码 ax2.imshow(mask, cmap='gray') ax2.set_title('植被掩码(绿色部分)') ax2.axis('off') plt.tight_layout() plt.show() # 保存报告到文件 report_filename = f"reports/report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(report_filename, 'w', encoding='utf-8') as f: json.dump(report, f, ensure_ascii=False, indent=2) print(f"\n报告已保存至: {report_filename}")# 6. 批量处理文件夹中的图像def batch_process_images(folder_path): """批量处理图像文件夹""" import os from tqdm import tqdm image_extensions = ['.jpg', '.jpeg', '.png', '.JPG'] image_files = [] for root, dirs, files in os.walk(folder_path): for file in files: if any(file.lower().endswith(ext) for ext in image_extensions): image_files.append(os.path.join(root, file)) # 按时间排序(假设文件名包含时间信息) image_files.sort(key=lambda x: os.path.basename(x).split('_')[1]) print(f"发现{len(image_files)}张图像需要处理") # 处理进度条 progress_bar = tqdm(image_files, desc="处理进度", unit="张") results = [] for image_path in progress_bar: try: report, _, _ = process_crop_image(image_path) results.append(report) except Exception as e: print(f"处理{image_path}时出错: {e}") return results# 示例:批量处理一个文件夹# batch_results = batch_process_images("crop_images/")# 7. 数据可视化(生长趋势分析)def plot_growth_trend(reports): """绘制生长趋势图表""" timestamps = [] lai_values = [] coverage_values = [] greenness_values = [] for report in reports: timestamps.append(report['timestamp']) lai_values.append(report['growth_metrics']['lai']) coverage_values.append(report['growth_metrics']['vegetation_coverage']) greenness_values.append(report['growth_metrics']['greenness_index']) # 转换为datetime对象 timestamps = pd.to_datetime(timestamps) # 创建图表 fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 12)) # LAI趋势 ax1.plot(timestamps, lai_values, 'g-', marker='o', linewidth=2) ax1.axhline(y=2.0, color='r', linestyle='--', label='最低阈值') ax1.axhline(y=4.5, color='orange', linestyle='--', label='最高阈值') ax1.set_title('叶面积指数(LAI)变化趋势') ax1.set_ylabel('LAI') ax1.grid(True, alpha=0.3) ax1.legend() # 植被覆盖度 ax2.plot(timestamps, coverage_values, 'b-', marker='s', linewidth=2) ax2.set_title('植被覆盖度变化趋势') ax2.set_ylabel('覆盖度 (%)') ax2.grid(True, alpha=0.3) # 绿色度指数 ax3.plot(timestamps, greenness_values, 'g-', marker='^', linewidth=2) ax3.set_title('绿色度指数变化趋势') ax3.set_ylabel('绿色度指数 (0-100)') ax3.grid(True, alpha=0.3) # 健康状态汇总 health_counts = {} for report in reports: status = report['health_status']['status'] health_counts[status] = health_counts.get(status, 0) + 1 colors = {'健康': 'green', '疑似病虫害': 'red'} ax4.pie(health_counts.values(), labels=health_counts.keys(), colors=[colors.get(k, 'gray') for k in health_counts.keys()], autopct='%1.1f%%', startangle=90) ax4.set_title('健康状态分布') plt.tight_layout() plt.show()# 示例:加载历史报告并绘制趋势# with open('historical_reports.json', 'r', encoding='utf-8') as f:# historical_reports = json.load(f)# plot_growth_trend(historical_reports)云端平台层├── 阿里云IoT平台│ ├── 设备管理│ ├── 数据存储(时序数据库)│ ├── 规则引擎│ └── 应用服务└── 数据可视化(Grafana)边缘计算层├── ESP32网关│ ├── WiFi通信模块│ ├── 数据处理单元│ └── 本地控制逻辑└── Arduino扩展板 ├── 传感器接口 └── 执行器控制感知执行层├── 环境传感器│ ├── DHT11温湿度传感器│ ├── BH1750光照传感器│ ├── CO2传感器│ └── 土壤传感器└── 环境调控设备 ├── 风机 ├── 湿帘 ├── 遮阳帘 └── 灌溉系统ESP32-WROOM-32 作为主控制器
Arduino UNO 作为扩展板,通过 I2C 接口与 ESP32 连接
DHT11 温湿度传感器:连接到 Arduino 的数字引脚 2
BH1750 光照传感器:通过 I2C 接口连接(SDA 到 Arduino A4,SCL 到 Arduino A5)
CO2 传感器:模拟输出连接到 Arduino A0
土壤湿度传感器:模拟输出连接到 Arduino A1
风机控制:Arduino 数字引脚 9 通过继电器控制
湿帘控制:Arduino 数字引脚 10 通过继电器控制
遮阳帘控制:Arduino 数字引脚 11 通过继电器控制
灌溉系统:Arduino 数字引脚 12 通过继电器控制
ESP32 使用 5V USB 供电
Arduino 使用 5V 供电
传感器和执行器使用独立的 12V 电源供电
ESP32-WROOM-32├── TXD → Arduino RX├── RXD → Arduino TX├── 5V → Arduino VIN├── GND → Arduino GND└── 3V3 → Arduino 3V3Arduino UNO├── D2 → DHT11 DATA├── A4 → BH1750 SDA├── A5 → BH1750 SCL├── A0 → CO2传感器 OUT├── A1 → 土壤湿度传感器 OUT├── D9 → 风机继电器 IN├── D10 → 湿帘继电器 IN├── D11 → 遮阳帘继电器 IN└── D12 → 灌溉继电器 IN// ESP32温室环境监测系统主控代码#include <WiFi.h>#include <PubSubClient.h>#include <Arduino.h>// WiFi配置const char* ssid = "your_wifi_ssid";const char* password = "your_wifi_password";// MQTT配置const char* mqtt_server = "mqtt.example.com";const int mqtt_port = 1883;const char* mqtt_user = "username";const char* mqtt_password = "password";const char* device_id = "greenhouse-001";WiFiClient espClient;PubSubClient client(espClient);// 与Arduino通信的变量float temperature = 0;float humidity = 0;int light_intensity = 0;float co2_concentration = 0;float soil_moisture = 0;void setup() { Serial.begin(115200); delay(1000); // 连接WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi连接成功"); // 连接MQTT服务器 client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); connect_mqtt(); // 初始化与Arduino的串口通信 Serial2.begin(9600); // 使用硬件串口2}void loop() { if (!client.connected()) { reconnect(); } client.loop(); // 每10秒从Arduino读取一次数据 static unsigned long last_read_time = 0; if (millis() - last_read_time > 10000) { last_read_time = millis(); // 向Arduino发送数据请求 Serial2.println("REQUEST_DATA"); // 等待Arduino响应 delay(200); // 读取Arduino发送的数据 if (Serial2.available() > 0) { String data = Serial2.readStringUntil('\n'); parse_sensor_data(data); } // 向云端发送数据 publish_sensor_data(); } // 每5分钟执行一次环境控制逻辑 static unsigned long last_control_time = 0; if (millis() - last_control_time > 300000) { last_control_time = millis(); environmental_control(); }}void parse_sensor_data(String data) { // 解析Arduino发送的数据格式:TEMP:22.5,HUM:50.0,LIGHT:800,CO2:1200,SOIL:45.0 int comma_pos = data.indexOf(','); while (comma_pos != -1) { String part = data.substring(0, comma_pos); data = data.substring(comma_pos + 1); parse_data_part(part); comma_pos = data.indexOf(','); } parse_data_part(data); // 处理最后一个部分}void parse_data_part(String part) { int colon_pos = part.indexOf(':'); if (colon_pos != -1) { String key = part.substring(0, colon_pos); String value_str = part.substring(colon_pos + 1); if (key == "TEMP") { temperature = value_str.toFloat(); } else if (key == "HUM") { humidity = value_str.toFloat(); } else if (key == "LIGHT") { light_intensity = value_str.toInt(); } else if (key == "CO2") { co2_concentration = value_str.toFloat(); } else if (key == "SOIL") { soil_moisture = value_str.toFloat(); } }}void publish_sensor_data() { DynamicJsonDocument doc(1024); doc["device_id"] = device_id; doc["timestamp"] = millis() / 1000; doc["temperature"] = temperature; doc["humidity"] = humidity; doc["light_intensity"] = light_intensity; doc["co2_concentration"] = co2_concentration; doc["soil_moisture"] = soil_moisture; char jsonBuffer[1024]; serializeJson(doc, jsonBuffer); client.publish("greenhouse/sensors", jsonBuffer); Serial.println("数据已发布到云端");}void environmental_control() { // 环境控制逻辑 String control_command = "CONTROL,"; // 温度控制(目标22.5℃) if (temperature > 24) { control_command += "FAN_ON,"; } else if (temperature < 21) { control_command += "HEATER_ON,"; } else { control_command += "FAN_OFF,HEATER_OFF,"; } // 湿度控制(目标50%) if (humidity > 60) { control_command += "VENT_ON,"; } else if (humidity < 40) { control_command += "MIST_ON,"; } else { control_command += "VENT_OFF,MIST_OFF,"; } // 光照控制(目标800 lux) if (light_intensity > 1000) { control_command += "SHADE_ON,"; } else { control_command += "SHADE_OFF,"; } // 土壤湿度控制(目标45%) if (soil_moisture < 40) { control_command += "IRRIGATION_ON,"; } else { control_command += "IRRIGATION_OFF,"; } // 去除最后的逗号 if (control_command.endsWith(",")) { control_command.remove(control_command.length() - 1); } // 发送控制指令到Arduino Serial2.println(control_command); Serial.println("控制指令已发送: " + control_command);}void callback(char* topic, byte* payload, unsigned int length) { // 处理云端下发的指令 String command((char*)payload); if (command == "REBOOT") { ESP.restart(); } else if (command.startsWith("SET_")) { // 处理设置指令,如SET_TEMP:23.0 String param = command.substring(4); int colon_pos = param.indexOf(':'); if (colon_pos != -1) { String key = param.substring(0, colon_pos); String value = param.substring(colon_pos + 1); // 这里可以实现参数设置功能 Serial.println("收到云端设置指令: " + key + "=" + value); } }}void connect_mqtt() { while (!client.connected()) { Serial.print("连接MQTT服务器..."); if (client.connect(device_id, mqtt_user, mqtt_password)) { Serial.println("连接成功"); client.subscribe("greenhouse/commands/" + String(device_id)); } else { Serial.print("连接失败,错误码: "); Serial.print(client.state()); Serial.println(",重试中..."); delay(5000); } }}void reconnect() { while (!client.connected()) { connect_mqtt(); }}// Arduino温室环境监测从机代码#include <DHT.h>#include <Wire.h>#include <BH1750.h>// 传感器定义#define DHT_PIN 2 // DHT11温湿度传感器#define DHT_TYPE DHT11DHT dht(DHT_PIN, DHT_TYPE);BH1750 lightMeter; // BH1750光照传感器void setup() { Serial.begin(9600); Serial2.begin(9600); // 使用硬件串口2与ESP32通信 // 初始化传感器 dht.begin(); lightMeter.begin(); // 初始化执行器引脚 pinMode(9, OUTPUT); // 风机 pinMode(10, OUTPUT); // 湿帘 pinMode(11, OUTPUT); // 遮阳帘 pinMode(12, OUTPUT); // 灌溉 // 初始状态设置 digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, LOW);}void loop() { // 处理来自ESP32的指令 if (Serial2.available() > 0) { String command = Serial2.readStringUntil('\n'); process_command(command); } // 每秒更新一次传感器数据(仅在需要时发送) static unsigned long last_update_time = 0; if (millis() - last_update_time > 1000) { last_update_time = millis(); update_sensor_data(); }}void update_sensor_data() { // 读取传感器数据 float temp = dht.readTemperature(); float hum = dht.readHumidity(); int light = lightMeter.readLightLevel(); // CO2传感器(模拟输出,需要根据实际传感器特性校准) int co2_analog = analogRead(A0); float co2_ppm = map(co2_analog, 0, 1023, 0, 5000); // 土壤湿度传感器(模拟输出) int soil_analog = analogRead(A1); float soil_moisture = map(soil_analog, 0, 1023, 0, 100); // 数据缓存,等待ESP32请求 sensor_data = String("TEMP:") + temp + ",HUM:" + hum + ",LIGHT:" + light + ",CO2:" + co2_ppm + ",SOIL:" + soil_moisture;}void process_command(String command) { if (command == "REQUEST_DATA") { // 发送传感器数据给ESP32 Serial2.println(sensor_data); } else if (command.startsWith("CONTROL")) { // 处理控制指令 String control_part = command.substring(7); StringList parts; control_part.split(',', parts); for (int i = 0; i < parts.size(); i++) { String part = parts[i]; if (part == "FAN_ON") { digitalWrite(9, HIGH); } else if (part == "FAN_OFF") { digitalWrite(9, LOW); } else if (part == "HEATER_ON") { digitalWrite(10, HIGH); } else if (part == "HEATER_OFF") { digitalWrite(10, LOW); } else if (part == "SHADE_ON") { digitalWrite(11, HIGH); } else if (part == "SHADE_OFF") { digitalWrite(11, LOW); } else if (part == "IRRIGATION_ON") { digitalWrite(12, HIGH); } else if (part == "IRRIGATION_OFF") { digitalWrite(12, LOW); } } }}创建产品
产品名称:智能温室环境监测系统
产品类型:设备
数据格式:JSON
认证方式:设备证书认证
创建设备
设备名称:greenhouse-001
设备证书:自动生成
设备 Secret:保存备用
定义物模型
{ "properties": { "temperature": { "identifier": "temperature", "name": "温度", "type": "float", "unit": "℃", "description": "环境温度" }, "humidity": { "identifier": "humidity", "name": "湿度", "type": "float", "unit": "%", "description": "环境湿度" }, "light_intensity": { "identifier": "light_intensity", "name": "光照强度", "type": "int", "unit": "lux", "description": "光照强度" }, "co2_concentration": { "identifier": "co2_concentration", "name": "CO2浓度", "type": "float", "unit": "ppm", "description": "二氧化碳浓度" }, "soil_moisture": { "identifier": "soil_moisture", "name": "土壤湿度", "type": "float", "unit": "%", "description": "土壤湿度" } }}配置规则引擎
创建规则:当温度 > 25℃时,发送报警信息
触发条件:${temperature} > 25
动作:发送钉钉消息或邮件通知
添加 InfluxDB 数据源
数据库:agriculture
用户:admin
密码:password
创建仪表板
温度趋势图(折线图)
湿度仪表盘(Gauge)
光照强度柱状图
CO2 浓度趋势图
土壤湿度时间序列图
设置告警规则
温度过高告警:>25℃
温度过低告警:<15℃
湿度过高告警:>70%
湿度过低告警:<30%
检查电路连接
确保所有传感器和执行器正确连接
检查电源电压是否正常
测试各部件功能是否正常
代码上传与测试
首先上传 Arduino 代码,测试传感器数据采集
然后上传 ESP32 代码,测试与 Arduino 的通信
最后测试 WiFi 连接和 MQTT 通信
功能测试
手动控制测试:通过串口发送指令,测试各执行器功能
自动控制测试:模拟环境变化,测试自动控制逻辑
数据上传测试:检查云端是否收到数据
数据采集频率:1 秒 / 次
数据传输频率:10 秒 / 次
控制响应时间:<1 秒
系统功耗:平均 5W(待机),峰值 25W(全负载)
通信距离:WiFi 覆盖范围内
传感器数据异常
检查传感器连接是否正确
检查传感器供电是否正常
重新校准传感器
通信失败
检查 WiFi 信号强度
检查 MQTT 服务器地址和端口
检查设备证书和密钥
控制功能失效
检查执行器连接
检查继电器工作状态
检查控制逻辑是否正确
import numpy as npimport pandas as pdfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import LSTM, Densefrom sklearn.preprocessing import MinMaxScaler# 准备训练数据(假设有历史数据df)def prepare_data(df, lookback=60): """准备LSTM训练数据""" data = df[['temperature', 'humidity', 'light_intensity', 'co2_concentration']].values scaler = MinMaxScaler(feature_range=(0, 1)) data_scaled = scaler.fit_transform(data) X, y = [], [] for i in range(lookback, len(data_scaled)): X.append(data_scaled[i-lookback:i, :]) y.append(data_scaled[i, 0]) # 预测温度 X = np.array(X) y = np.array(y) return X, y, scaler# 构建LSTM模型def build_lstm_model(input_shape): """构建LSTM预测模型""" model = Sequential() model.add(LSTM(50, activation='relu', input_shape=input_shape, return_sequences=True)) model.add(LSTM(50, activation='relu')) model.add(Dense(1)) model.compile(optimizer='adam', loss='mse') return model# 训练模型def train_model(): """训练环境预测模型""" # 加载历史数据(从数据库读取) # 假设数据格式:timestamp, temperature, humidity, light_intensity, co2_concentration df = pd.read_csv('greenhouse_data.csv', parse_dates=['timestamp']) df = df.sort_values('timestamp') # 数据预处理 X, y, scaler = prepare_data(df) # 划分训练集和测试集 split_ratio = 0.8 split_index = int(len(X) * split_ratio) X_train, X_test = X[:split_index], X[split_index:] y_train, y_test = y[:split_index], y[split_index:] # 重塑数据为LSTM输入格式:[样本数, 时间步, 特征数] X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], X_train.shape[2])) X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], X_test.shape[2])) # 构建模型 model = build_lstm_model((lookback, 4)) # 训练模型 model.fit(X_train, y_train, epochs=50, batch_size=32, validation_data=(X_test, y_test)) # 保存模型和scaler model.save('temperature_prediction_model.h5') with open('scaler.pkl', 'wb') as f: pickle.dump(scaler, f) return model, scaler# 实时预测def predict_temperature(new_data, model, scaler, lookback=60): """实时温度预测""" # 数据预处理 new_data_scaled = scaler.transform(new_data) # 准备输入数据(最后60个时间步) input_data = new_data_scaled[-lookback:] input_data = np.reshape(input_data, (1, lookback, 4)) # 预测 predicted_scaled = model.predict(input_data) predicted_temp = scaler.inverse_transform(np.hstack([predicted_scaled, np.zeros((1, 3))]))[:, 0] return predicted_temp[0]import 'package:flutter/material.dart';import 'package:mqtt_client/mqtt_client.dart';import 'package:charts_flutter/flutter.dart' as charts;class GreenhouseMonitor extends StatefulWidget { @override _GreenhouseMonitorState createState() => _GreenhouseMonitorState();}class _GreenhouseMonitorState extends State<GreenhouseMonitor> { // MQTT配置 final String mqttServer = 'mqtt.example.com'; final int mqttPort = 1883; final String clientId = 'mobile-app-001'; final String topic = 'greenhouse/sensors'; MqttClient client; bool isConnected = false; // 传感器数据 List<SensorData> sensorDataList = []; double temperature = 0; double humidity = 0; int lightIntensity = 0; double co2Concentration = 0; double soilMoisture = 0; @override void initState() { super.initState(); connectToMqtt(); } void connectToMqtt() async { client = MqttClient(mqttServer, clientId); client.port = mqttPort; try { await client.connect(); setState(() { isConnected = true; }); client.subscribe(topic, MqttQos.atMostOnce); client.updates.listen((List<MqttReceivedMessage> c) { final message = c[0].payload as MqttPublishMessage; final payload = String.fromCharCodes(message.payload.message); updateSensorData(payload); }); } catch (e) { print('MQTT连接失败: $e'); setState(() { isConnected = false; }); } } void updateSensorData(String payload) { try { final data = jsonDecode(payload); setState(() { temperature = data['temperature'] ?? 0; humidity = data['humidity'] ?? 0; lightIntensity = data['light_intensity'] ?? 0; co2Concentration = data['co2_concentration'] ?? 0; soilMoisture = data['soil_moisture'] ?? 0; sensorDataList.add(SensorData( timestamp: DateTime.now(), temperature: temperature, humidity: humidity, )); // 保持最近100个数据点 if (sensorDataList.length > 100) { sensorDataList.removeAt(0); } }); } catch (e) { print('数据解析失败: $e'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('智能温室监控系统')), body: SingleChildScrollView( child: Padding( padding: EdgeInsets.all(16.0), child: Column( children: [ // 实时数据显示 Card( child: Padding( padding: EdgeInsets.all(16.0), child: Column( children: [ Text('实时环境数据', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ SensorDisplay( title: '温度', value: '$temperature℃', unit: '℃', icon: Icons.thermostat, ), SensorDisplay( title: '湿度', value: '$humidity%', unit: '%', icon: Icons.water_drop, ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ SensorDisplay( title: '光照', value: '$lightIntensity lux', unit: 'lux', icon: Icons.wb_sunny, ), SensorDisplay( title: 'CO2', value: '$co2Concentration ppm', unit: 'ppm', icon: Icons.cloud, ), ], ), SensorDisplay( title: '土壤湿度', value: '$soilMoisture%', unit: '%', icon: Icons.terrain, ), ], ), ), ), // 温度趋势图 Card( child: Padding( padding: EdgeInsets.all(16.0), child: Column( children: [ Text('温度变化趋势', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), SizedBox(height: 10), Container( height: 300, child: LineChart( [ charts.Series<SensorData, DateTime>( id: '温度', data: sensorDataList, domainFn: (SensorData data, _) => data.timestamp, measureFn: (SensorData data, _) => data.temperature, colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault, ), ], animate: true, defaultRenderer: charts.LineRendererConfig( includePoints: true, ), ), ), ], ), ), ), // 控制按钮 if (isConnected) ...[ Card( child: Padding( padding: EdgeInsets.all(16.0), child: Column( children: [ Text('远程控制', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ControlButton( title: '风机', onPressed: () => sendCommand('FAN_TOGGLE'), ), ControlButton( title: '湿帘', onPressed: () => sendCommand('MIST_TOGGLE'), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ControlButton( title: '遮阳', onPressed: () => sendCommand('SHADE_TOGGLE'), ), ControlButton( title: '灌溉', onPressed: () => sendCommand('IRRIGATION_TOGGLE'), ), ], ), ], ), ), ), ] else ...[ Center( child: Text('未连接到MQTT服务器', style: TextStyle(color: Colors.red)), ), ] ], ), ), ), ); } void sendCommand(String command) { if (isConnected) { final message = MqttClientPayloadBuilder().addString(command).payload; client.publishMessage('greenhouse/commands', MqttQos.atMostOnce, message); print('发送控制指令: $command'); } } @override void dispose() { if (client != null && client.connected) { client.disconnect(); } super.dispose(); }}class SensorDisplay extends StatelessWidget { final String title; final String value; final String unit; final IconData icon; SensorDisplay({ required this.title, required this.value, required this.unit, required this.icon, }); @override Widget build(BuildContext context) { return Column( children: [ Icon(icon, size: 48), SizedBox(height: 10), Text(title, style: TextStyle(fontSize: 14)), Text( '$value $unit', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ], ); }}class ControlButton extends StatelessWidget { final String title; final VoidCallback onPressed; ControlButton({ required this.title, required this.onPressed, }); @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( primary: Colors.blue, onPrimary: Colors.white, padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), ), ), child: Text(title), ); }}class SensorData { final DateTime timestamp; final double temperature; final double humidity; SensorData({ required this.timestamp, required this.temperature, required this.humidity, });}学习使用深度学习框架(如 TensorFlow、PyTorch)进行作物病虫害识别
掌握图像分割技术,用于计算叶面积指数(LAI)和植被覆盖度
学习使用 YOLO 等目标检测算法进行作物计数和生长状态评估
研究多光谱和高光谱图像处理技术,用于作物营养诊断
学习使用 TensorFlow Lite、ONNX Runtime 等框架在边缘设备上部署模型
研究模型量化和剪枝技术,优化模型在 MCU 上的运行效率
了解边缘计算框架(如 OpenVINO、TensorRT)的使用
实践在 ESP32 等设备上运行轻量级 AI 模型
深入学习 LPWAN 技术(LoRaWAN、NB-IoT、Sigfox)
研究 5G 和 5G-A 技术在农业中的应用
学习 Mesh 网络和自组织网络技术
了解低功耗通信协议和节能技术
学习使用大数据处理框架(如 Hadoop、Spark)处理海量农业数据
研究时间序列分析算法(如 ARIMA、Prophet)用于产量预测
了解机器学习算法(随机森林、梯度提升树)在农业中的应用
学习使用知识图谱和专家系统构建农业决策支持系统
学习区块链技术在农产品溯源中的应用
研究联邦学习在保护隐私的农业数据分析中的应用
了解密码学技术(如同态加密、安全多方计算)
实践使用 IPFS 等分布式存储技术
智能花盆系统:集成温湿度、光照、土壤湿度传感器,实现自动灌溉
家庭阳台种植监测:使用 ESP32 和手机 APP,实时监测植物生长状态
简易气象站:使用 Arduino 连接风速、雨量、温湿度传感器,数据上传云端
温室环境智能控制系统:实现温度、湿度、光照、CO2 的自动调节
精准灌溉原型系统:基于土壤湿度和气象预报,实现智能灌溉决策
作物生长监测系统:使用计算机视觉技术,定期监测作物生长指标
智慧农场综合管理平台:集成多个监测系统,提供统一的数据展示和管理界面
农业无人机监测系统:使用无人机搭载传感器,实现大面积农田的快速监测
智能温室物联网系统:构建完整的 "云 - 边 - 端" 架构,实现温室的无人值守管理
基于 AI 的作物病害预警系统:结合环境数据和图像识别,提前预测病害发生
自适应精准施肥系统:根据土壤检测数据和作物生长阶段,自动调整施肥方案
农产品质量追溯系统:使用区块链技术,记录农产品从种植到销售的全过程
注重代码规范和文档编写,养成良好的编程习惯
建立版本控制系统(如 Git),管理项目代码
学会使用调试工具和性能分析工具,提高开发效率
积极参与开源社区,学习他人的经验和代码
定期总结项目经验,形成自己的技术博客或作品集
