Files
Dorm-Air-Conditioner-Smart-…/core.h
2025-09-20 16:57:16 +08:00

281 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef CORE_H
#define CORE_H
#include <Arduino.h>
#include <Preferences.h>
// 包含所有必要的模块头文件
#include "DHT11control.h"
#include "RTC_Module.h"
#include "LunarCalendarAndHolidayJudge.h"
#include "audio_model_esp32.h"
#include "microphone.h"
// 核心判断结果枚举
typedef enum {
JUDGE_NO_ACTION = 0, // 无需操作
JUDGE_TURN_ON_COOLING = 1, // 开启制冷
JUDGE_TURN_ON_HEATING = 2, // 开启制暖
JUDGE_TURN_OFF_AC = 3, // 关闭空调
JUDGE_ADJUST_TEMP = 4, // 除湿
JUDGE_ERROR = -1 // 错误状态
} JudgeResult;
// 环境数据结构
typedef struct {
float temperature; // 当前温度
float humidity; // 当前湿度
int year; // 当前年份
int month; // 当前月份
int day; // 当前日期
int hour; // 当前小时
int minute; // 当前分钟
int second; // 当前秒数
bool is_holiday; // 是否为节假日
AudioClassType audio_class; // AI音频识别结果
float audio_confidence; // 音频识别置信度
bool data_valid; // 数据是否有效
} EnvironmentData;
// 全局麦克风对象
static INMP441Microphone microphone(14, 15, 32, 16000, 1024);
// 初始化核心模块
bool initializeCore() {
Serial.println("正在初始化核心模块...");
// 初始化音频模型
if (audio_model_init() != 0) {
Serial.println("音频模型初始化失败!");
return false;
}
// 初始化麦克风
if (!microphone.begin()) {
Serial.println("麦克风初始化失败!");
return false;
}
Serial.println("核心模块初始化完成");
return true;
}
// 获取环境数据
bool getEnvironmentData(EnvironmentData* env_data) {
if (env_data == NULL) {
return false;
}
// 初始化数据结构
memset(env_data, 0, sizeof(EnvironmentData));
env_data->data_valid = false;
// 获取温湿度数据
float* temp_humidity = getTempAndHumidity();
if (temp_humidity[0] == -999 || temp_humidity[1] == -999) {
Serial.println("温湿度传感器读取失败!");
return false;
}
env_data->temperature = temp_humidity[0];
env_data->humidity = temp_humidity[1];
// 获取RTC时间
RtcDateTime current_time = getRTCTime();
if (!current_time.IsValid()) {
Serial.println("RTC时间读取失败!");
return false;
}
env_data->year = current_time.Year();
env_data->month = current_time.Month();
env_data->day = current_time.Day();
env_data->hour = current_time.Hour();
env_data->minute = current_time.Minute();
env_data->second = current_time.Second();
// 判断是否为节假日
env_data->is_holiday = LunarCalendar::isHoliday(env_data->year, env_data->month, env_data->day);
env_data->data_valid = true;
return true;
}
// 执行AI音频识别
bool performAudioRecognition(EnvironmentData* env_data) {
if (env_data == NULL) {
return false;
}
Serial.println("开始音频识别...");
// 分配音频缓冲区 (2秒 * 16000Hz = 32000 samples)
const size_t audio_buffer_size = 32000;
int16_t* audio_buffer = (int16_t*)malloc(audio_buffer_size * sizeof(int16_t));
if (audio_buffer == NULL) {
Serial.println("音频缓冲区分配失败!");
return false;
}
// 采集2秒音频数据
size_t samples_read = 0;
unsigned long start_time = millis();
while (samples_read < audio_buffer_size && (millis() - start_time) < 2100) {
size_t chunk_size = microphone.readAudioData(
audio_buffer + samples_read,
min(1024, (int)(audio_buffer_size - samples_read))
);
samples_read += chunk_size;
delay(1); // 短暂延时避免过度占用CPU
}
Serial.printf("采集到 %d 个音频样本\n", samples_read);
// 执行AI预测
AudioPredictionResult prediction_result;
int predict_status = audio_model_predict(audio_buffer, samples_read, &prediction_result);
// 释放音频缓冲区
free(audio_buffer);
if (predict_status != 0 || !prediction_result.is_valid) {
Serial.println("音频预测失败!");
env_data->audio_class = AUDIO_CLASS_PERSON_ABSENT;
env_data->audio_confidence = 0.0f;
return false;
}
env_data->audio_class = prediction_result.predicted_class;
env_data->audio_confidence = prediction_result.confidence;
Serial.printf("音频识别结果: %s (置信度: %.2f)\n",
get_class_name_cn(env_data->audio_class),
env_data->audio_confidence);
return true;
}
// 核心判断函数
int judge() {
Serial.println("=== 开始核心判断流程 ===");
// 获取环境数据
EnvironmentData env_data;
if (!getEnvironmentData(&env_data)) {
Serial.println("环境数据获取失败!");
return JUDGE_ERROR;
}
// 执行音频识别
if (!performAudioRecognition(&env_data)) {
Serial.println("音频识别失败,使用默认值");
// 继续执行,但音频数据可能不准确
}
// 打印当前环境状态
Serial.println("=== 当前环境状态 ===");
Serial.printf("时间: %04d-%02d-%02d %02d:%02d:%02d\n",
env_data.year, env_data.month, env_data.day,
env_data.hour, env_data.minute, env_data.second);
Serial.printf("温度: %.1f°C, 湿度: %.1f%%\n", env_data.temperature, env_data.humidity);
Serial.printf("节假日: %s\n", env_data.is_holiday ? "" : "");
Serial.printf("音频识别: %s (置信度: %.2f)\n",
get_class_name_cn(env_data.audio_class), env_data.audio_confidence);
// 核心判断逻辑
JudgeResult result = JUDGE_NO_ACTION;
// 获取用户设置的温度范围 (从Preferences读取)
Preferences prefs;
prefs.begin("DACSC", true); // 只读模式
float min_temp = prefs.getFloat("min_temp", 5.0); // 默认最低温度22°C
float max_temp = prefs.getFloat("max_temp", 28.0); // 默认最高温度26°C
prefs.end();
// 判断逻辑:基于节假日、音频识别、时间、温度和湿度的智能控制
// 规则1节假日规则优先级最高
if (env_data.is_holiday) {
result = JUDGE_NO_ACTION;
Serial.println("判断结果: 节假日,系统不进行任何操作");
}
// 规则2-9非节假日规则
else {
// 检查是否有人在室内(包括"室内有人"和"有人进门"
bool person_present = (env_data.audio_class == AUDIO_CLASS_PERSON_PRESENT ||
env_data.audio_class == AUDIO_CLASS_KEY_JINGLING) &&
env_data.audio_confidence > 0.6;
// 检查是否无人在室内(包括"室内无人"和"有人出门"
bool person_absent = (env_data.audio_class == AUDIO_CLASS_PERSON_ABSENT ||
env_data.audio_class == AUDIO_CLASS_DOOR_CLOSING) &&
env_data.audio_confidence > 0.6;
// 检查是否为白天时间8:00-22:00
bool is_daytime = (env_data.hour >= 8 && env_data.hour <= 22);
if (person_absent) {
// 规则10无人时关闭空调优先级高
result = JUDGE_TURN_OFF_AC;
Serial.println("判断结果: 检测到无人或有人出门,关闭空调以节能");
}
else if (person_present) {
if (is_daytime) {
// 白天有人的规则规则2-5
if (env_data.temperature < min_temp) {
result = JUDGE_TURN_ON_HEATING;
Serial.println("判断结果: 白天有人且温度过低,开启制热");
}
else if (env_data.temperature > max_temp) {
result = JUDGE_TURN_ON_COOLING;
Serial.println("判断结果: 白天有人且温度过高,开启制冷");
}
else if (env_data.humidity > 70.0) {
result = JUDGE_ADJUST_TEMP;
Serial.println("判断结果: 白天有人、温度舒适但湿度过高,开启除湿");
}
else {
result = JUDGE_NO_ACTION;
Serial.println("判断结果: 白天有人、温度舒适且湿度正常,无需操作");
}
}
else {
// 晚上有人的规则规则6-9
if (env_data.temperature < min_temp) {
result = JUDGE_TURN_ON_HEATING;
Serial.println("判断结果: 晚上有人但温度过低,开启制热");
}
else if (env_data.temperature > max_temp) {
result = JUDGE_TURN_ON_COOLING;
Serial.println("判断结果: 晚上有人但温度过高,开启制冷");
}
else if (env_data.humidity > 70.0) {
result = JUDGE_ADJUST_TEMP;
Serial.println("判断结果: 晚上有人、温度舒适但湿度过高,开启除湿");
}
else {
result = JUDGE_NO_ACTION;
Serial.println("判断结果: 晚上有人、温度舒适且湿度正常,无需操作以节能");
}
}
}
else {
// 音频识别不确定或置信度不够时的默认处理
result = JUDGE_NO_ACTION;
Serial.println("判断结果: 音频识别不确定,保持当前状态");
}
}
Serial.printf("=== 判断完成,返回值: %d ===\n", result);
return result;
}
// 清理核心模块资源
void cleanupCore() {
Serial.println("清理核心模块资源...");
microphone.end();
audio_model_cleanup();
Serial.println("核心模块资源清理完成");
}
#endif // CORE_H