
鸿蒙智能空调自动调温系统开发指南 原创
鸿蒙智能空调自动调温系统开发指南
一、系统架构设计
基于HarmonyOS的分布式能力,我们设计了一套智能空调控制系统,主要功能包括:
红外编码学习:支持学习各种品牌空调遥控器信号
室温预测:基于历史数据和环境因素预测温度变化
人体检测:通过多传感器融合检测室内人员存在
跨设备控制:多终端同步空调状态和控制权
智能场景:根据用户习惯自动调节温度
!https://example.com/harmony-ac-controller-arch.png
二、核心代码实现
红外编码学习服务
// InfraredService.ets
import infrared from ‘@ohos.infrared’;
import storage from ‘@ohos.data.storage’;
class InfraredService {
private static instance: InfraredService;
private learnedCodes: Map<string, InfraredCode> = new Map();
private currentBrand: string = ‘’;
private constructor() {
this.loadLearnedCodes();
private async loadLearnedCodes(): Promise<void> {
try {
const codes = await storage.get('learnedIrCodes');
if (codes) {
this.learnedCodes = new Map(JSON.parse(codes));
} catch (error) {
console.error('Failed to load IR codes:', error);
}
public static getInstance(): InfraredService {
if (!InfraredService.instance) {
InfraredService.instance = new InfraredService();
return InfraredService.instance;
public async startLearning(brand: string): Promise<void> {
this.currentBrand = brand;
await infrared.startLearning({
carrierFrequency: 38000, // 38kHz是常见红外载频
onCodeReceived: (code) => this.handleLearnedCode(code)
});
private async handleLearnedCode(code: InfraredCode): Promise<void> {
if (!this.currentBrand) return;
// 保存学习到的编码
this.learnedCodes.set({this.currentBrand}_{code.function}, code);
try {
// 持久化存储
await storage.set('learnedIrCodes',
JSON.stringify(Array.from(this.learnedCodes.entries())));
catch (error) {
console.error('Failed to save IR code:', error);
// 发送学习完成事件
EventBus.emit('irCodeLearned', {
brand: this.currentBrand,
function: code.function
});
public async sendCode(brand: string, functionName: string): Promise<void> {
const codeKey = {brand}_{functionName};
const code = this.learnedCodes.get(codeKey);
if (!code) {
throw new Error(未学习{brand}品牌的{functionName}功能编码);
await infrared.transmit(code);
public getLearnedBrands(): string[] {
const brands = new Set<string>();
this.learnedCodes.forEach((_, key) => {
brands.add(key.split('_')[0]);
});
return Array.from(brands);
public getBrandFunctions(brand: string): string[] {
const functions: string[] = [];
this.learnedCodes.forEach((_, key) => {
if (key.startsWith(${brand}_)) {
functions.push(key.split('_')[1]);
});
return functions;
public deleteCode(brand: string, functionName: string): void {
this.learnedCodes.delete({brand}_{functionName});
storage.set('learnedIrCodes',
JSON.stringify(Array.from(this.learnedCodes.entries())));
}
export const irService = InfraredService.getInstance();
室温预测服务
// TemperaturePredictionService.ets
import neuralNetwork from ‘@ohos.ai.neuralNetwork’;
import sensor from ‘@ohos.sensor’;
class TemperaturePredictionService {
private static instance: TemperaturePredictionService;
private model: neuralNetwork.Model | null = null;
private history: TemperatureData[] = [];
private predictionInterval: number = 30 60 1000; // 30分钟预测一次
private constructor() {
this.initModel();
this.startPredictionLoop();
private async initModel(): Promise<void> {
try {
// 加载预训练的轻量级温度预测模型
this.model = await neuralNetwork.loadModel({
modelPath: 'models/temp_predict_lite.nn',
quantization: true
});
// 加载历史数据
this.loadHistory();
catch (error) {
console.error('Failed to load prediction model:', error);
}
private async loadHistory(): Promise<void> {
const history = await storage.get(‘temperatureHistory’);
if (history) {
this.history = JSON.parse(history);
}
public static getInstance(): TemperaturePredictionService {
if (!TemperaturePredictionService.instance) {
TemperaturePredictionService.instance = new TemperaturePredictionService();
return TemperaturePredictionService.instance;
private startPredictionLoop(): void {
setInterval(() => {
this.predictTemperature();
}, this.predictionInterval);
public async recordCurrentTemperature(temp: number): Promise<void> {
const now = Date.now();
const data: TemperatureData = {
timestamp: now,
temperature: temp,
humidity: sensor.getHumidity(),
outdoorTemp: await this.getOutdoorTemp(),
acStatus: acService.getCurrentStatus()
};
this.history.push(data);
// 保留最近7天数据
if (this.history.length > 7 24 2) { // 每30分钟一条记录
this.history.shift();
// 保存数据
await storage.set('temperatureHistory', JSON.stringify(this.history));
private async predictTemperature(): Promise<void> {
if (!this.model || this.history.length < 24) return; // 至少需要24条记录
try {
// 准备输入数据
const input = this.prepareInput();
// 运行预测
const output = await this.model.run(input);
// 解析预测结果
const predictions = this.parseOutput(output);
// 触发预测事件
EventBus.emit('temperaturePredicted', predictions);
catch (error) {
console.error('Temperature prediction failed:', error);
}
private prepareInput(): neuralNetwork.Tensor {
// 使用最近24小时数据预测未来3小时
const recentData = this.history.slice(-24);
return {
data: this.normalizeData(recentData),
shape: [1, 24, 5] // [批次, 时间步, 特征]
};
private normalizeData(data: TemperatureData[]): number[] {
// 简单归一化处理
const maxTemp = Math.max(...data.map(d => d.temperature));
const maxHumidity = Math.max(...data.map(d => d.humidity));
return data.flatMap(d => [
d.temperature / 50, // 假设最高50°C
d.humidity / 100,
d.outdoorTemp / 50,
d.acStatus.temperature / 30,
d.acStatus.power ? 1 : 0
]);
private parseOutput(output: neuralNetwork.Tensor): TemperaturePrediction[] {
const data = output.data as number[];
const now = Date.now();
return [
time: now + 3600000, temperature: data[0] * 50 }, // 1小时后
time: now + 7200000, temperature: data[1] * 50 }, // 2小时后
time: now + 10800000, temperature: data[2] * 50 } // 3小时后
];
private async getOutdoorTemp(): Promise<number> {
// 从天气服务获取室外温度
try {
const weather = await weatherService.getCurrentWeather();
return weather.temperature;
catch (error) {
console.error('Failed to get outdoor temp:', error);
return 25; // 默认值
}
public getHistory(): TemperatureData[] {
return […this.history];
public getLatestPrediction(): TemperaturePrediction | null {
const predictions = EventBus.getLastEvent('temperaturePredicted');
return predictions ? predictions[0] : null;
}
export const tempPrediction = TemperaturePredictionService.getInstance();
人体检测服务
// PresenceDetectionService.ets
import sensor from ‘@ohos.sensor’;
import neuralNetwork from ‘@ohos.ai.neuralNetwork’;
import power from ‘@ohos.power’;
class PresenceDetectionService {
private static instance: PresenceDetectionService;
private model: neuralNetwork.Model | null = null;
private isPresent: boolean = false;
private lastDetectionTime: number = 0;
private powerMode: power.Mode = power.Mode.NORMAL;
private constructor() {
this.initModel();
this.initSensors();
this.initPowerListener();
private async initModel(): Promise<void> {
try {
// 加载轻量级人体存在检测模型
this.model = await neuralNetwork.loadModel({
modelPath: 'models/presence_detection.nn',
quantization: true
});
catch (error) {
console.error('Failed to load presence model:', error);
}
private initSensors(): void {
// 使用PIR(被动红外)传感器
sensor.on(sensor.SensorType.SENSOR_TYPE_ID_PIR, (data) => {
this.handlePirData(data);
}, { interval: 1000 });
// 使用毫米波雷达(如果可用)
if (sensor.hasSensor(sensor.SensorType.SENSOR_TYPE_ID_MMWAVE)) {
sensor.on(sensor.SensorType.SENSOR_TYPE_ID_MMWAVE, (data) => {
this.handleMmWaveData(data);
}, { interval: 2000 });
}
private initPowerListener(): void {
power.on(‘powerModeChange’, (mode) => {
this.powerMode = mode;
this.adjustDetectionParams();
});
private adjustDetectionParams(): void {
// 根据电源模式调整检测参数
switch (this.powerMode) {
case power.Mode.POWER_SAVE:
sensor.off(sensor.SensorType.SENSOR_TYPE_ID_MMWAVE);
sensor.setInterval(sensor.SensorType.SENSOR_TYPE_ID_PIR, 3000);
break;
case power.Mode.PERFORMANCE:
if (sensor.hasSensor(sensor.SensorType.SENSOR_TYPE_ID_MMWAVE)) {
sensor.on(sensor.SensorType.SENSOR_TYPE_ID_MMWAVE, (data) => {
this.handleMmWaveData(data);
}, { interval: 1000 });
sensor.setInterval(sensor.SensorType.SENSOR_TYPE_ID_PIR, 500);
break;
default:
sensor.setInterval(sensor.SensorType.SENSOR_TYPE_ID_PIR, 1000);
}
public static getInstance(): PresenceDetectionService {
if (!PresenceDetectionService.instance) {
PresenceDetectionService.instance = new PresenceDetectionService();
return PresenceDetectionService.instance;
private handlePirData(data: sensor.PirResponse): void {
if (data.value > 0.8 && Date.now() - this.lastDetectionTime > 5000) {
this.detectPresence();
}
private handleMmWaveData(data: sensor.MmWaveResponse): void {
if (data.motionLevel > 0.7 && Date.now() - this.lastDetectionTime > 3000) {
this.detectPresence();
}
private async detectPresence(): Promise<void> {
if (!this.model) return;
try {
// 获取环境传感器数据
const envData = await this.getEnvironmentData();
// 准备模型输入
const input: neuralNetwork.Tensor = {
data: this.normalizeInput(envData),
shape: [1, 1, 5] // [批次, 时间步, 特征]
};
// 运行模型
const output = await this.model.run(input);
const presenceProb = (output.data as number[])[0];
// 更新状态
this.isPresent = presenceProb > 0.7;
this.lastDetectionTime = Date.now();
// 触发事件
EventBus.emit('presenceChanged', this.isPresent);
catch (error) {
console.error('Presence detection failed:', error);
}
private async getEnvironmentData(): Promise<EnvData> {
return {
temperature: sensor.getTemperature(),
humidity: sensor.getHumidity(),
lightLevel: sensor.getLight(),
soundLevel: sensor.getSound(),
co2Level: sensor.getCO2()
};
private normalizeInput(data: EnvData): number[] {
return [
data.temperature / 50,
data.humidity / 100,
data.lightLevel / 1000,
data.soundLevel / 100,
data.co2Level / 2000
];
public isPersonPresent(): boolean {
return this.isPresent;
public getLastDetectionTime(): number {
return this.lastDetectionTime;
public getDetectionConfidence(): number {
// 基于最后检测时间和传感器数据计算置信度
const timeSinceLast = Date.now() - this.lastDetectionTime;
return Math.max(0, 1 - timeSinceLast / 600000); // 10分钟后置信度降为0
}
export const presenceDetection = PresenceDetectionService.getInstance();
跨设备同步服务
// SyncService.ets
import distributedData from ‘@ohos.data.distributedData’;
import deviceManager from ‘@ohos.distributedHardware.deviceManager’;
class SyncService {
private static instance: SyncService;
private kvManager: distributedData.KVManager;
private kvStore: distributedData.KVStore;
private connectedDevices: string[] = [];
private constructor() {
this.initKVStore();
this.initDeviceListener();
private async initKVStore(): Promise<void> {
const config = {
bundleName: 'com.example.accontroller',
userInfo: { userId: 'default' }
};
this.kvManager = distributedData.createKVManager(config);
this.kvStore = await this.kvManager.getKVStore('ac_sync', {
createIfMissing: true,
backup: false,
autoSync: true,
kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
});
this.kvStore.on('dataChange', (data) => {
this.handleRemoteChanges(data);
});
private initDeviceListener(): void {
deviceManager.on('deviceStateChange', (data) => {
this.handleDeviceStateChange(data);
});
this.updateConnectedDevices();
private async updateConnectedDevices(): Promise<void> {
const devices = await deviceManager.getTrustedDeviceList();
this.connectedDevices = devices.map(d => d.deviceId);
private handleDeviceStateChange(data: deviceManager.DeviceStateChangeData): void {
if (data.deviceState === deviceManager.DeviceState.ONLINE) {
if (!this.connectedDevices.includes(data.deviceId)) {
this.connectedDevices.push(data.deviceId);
} else if (data.deviceState === deviceManager.DeviceState.OFFLINE) {
this.connectedDevices = this.connectedDevices.filter(id => id !== data.deviceId);
}
public static getInstance(): SyncService {
if (!SyncService.instance) {
SyncService.instance = new SyncService();
return SyncService.instance;
public async syncACStatus(status: ACStatus): Promise<void> {
const change: SyncChange = {
type: 'acStatus',
value: status,
timestamp: Date.now(),
deviceId: deviceManager.getLocalDevice().id
};
await this.kvStore.put('current_status', JSON.stringify(change));
public async syncTemperature(temp: number): Promise<void> {
const change: SyncChange = {
type: 'temperature',
value: temp,
timestamp: Date.now(),
deviceId: deviceManager.getLocalDevice().id
};
await this.kvStore.put(temp_${Date.now()}, JSON.stringify(change));
public async syncPresence(present: boolean): Promise<void> {
const change: SyncChange = {
type: 'presence',
value: present,
timestamp: Date.now(),
deviceId: deviceManager.getLocalDevice().id
};
await this.kvStore.put(presence_${Date.now()}, JSON.stringify(change));
private handleRemoteChanges(data: distributedData.ChangeInfo): void {
if (data.deviceId === deviceManager.getLocalDevice().id) return;
try {
const change = JSON.parse(data.value) as SyncChange;
switch (change.type) {
case 'acStatus':
EventBus.emit('remoteACStatus', change.value);
break;
case 'temperature':
EventBus.emit('remoteTemperature', change.value);
break;
case 'presence':
EventBus.emit('remotePresence', change.value);
break;
} catch (error) {
console.error('Failed to parse sync data:', error);
}
public async getConnectedDevices(): Promise<string[]> {
await this.updateConnectedDevices();
return […this.connectedDevices];
public async broadcastCommand(command: ACCommand): Promise<void> {
const change: SyncChange = {
type: 'command',
value: command,
timestamp: Date.now(),
deviceId: deviceManager.getLocalDevice().id
};
await this.kvStore.put(command_${Date.now()}, JSON.stringify(change));
}
export const syncService = SyncService.getInstance();
三、主界面实现
空调控制主界面
// ACControlView.ets
@Component
struct ACControlView {
@State currentTemp: number = 26;
@State targetTemp: number = 26;
@State isOn: boolean = false;
@State mode: ACMode = ‘cool’;
@State fanSpeed: FanSpeed = ‘auto’;
@State isPersonPresent: boolean = false;
@State connectedDevices: number = 0;
aboutToAppear() {
this.initEventListeners();
this.loadInitialState();
build() {
Column() {
// 状态显示
Row() {
Text(当前温度: ${this.currentTemp}°C)
.fontSize(16)
.layoutWeight(1)
Text(this.isPersonPresent ? '有人' : '无人')
.fontSize(16)
.fontColor(this.isPersonPresent ? '#4CAF50' : '#F44336')
.margin({ right: 16 })
.margin({ top: 16, bottom: 8 })
// 温度控制
Row() {
Button('-')
.onClick(() => this.adjustTemp(-1))
.width(48)
.height(48)
Text(${this.targetTemp}°C)
.fontSize(32)
.fontWeight(FontWeight.Bold)
.margin({ left: 16, right: 16 })
Button('+')
.onClick(() => this.adjustTemp(1))
.width(48)
.height(48)
.margin({ bottom: 24 })
// 模式选择
ModeSelector({
currentMode: this.mode,
onChange: (mode) => this.changeMode(mode)
})
.margin({ bottom: 16 })
// 风速选择
FanSpeedSelector({
currentSpeed: this.fanSpeed,
onChange: (speed) => this.changeFanSpeed(speed)
})
.margin({ bottom: 24 })
// 电源按钮
Button(this.isOn ? '关闭' : '开启')
.onClick(() => this.togglePower())
.width(200)
.height(48)
.backgroundColor(this.isOn ? '#F44336' : '#4CAF50')
// 设备连接状态
if (this.connectedDevices > 0) {
Text(${this.connectedDevices}设备连接中)
.fontSize(14)
.fontColor('#666666')
.margin({ top: 16 })
}
.padding(16)
private initEventListeners(): void {
EventBus.on('remoteACStatus', (status) => {
this.updateStatus(status);
});
EventBus.on('remoteTemperature', (temp) => {
this.currentTemp = temp;
});
EventBus.on('remotePresence', (present) => {
this.isPersonPresent = present;
});
private loadInitialState(): void {
const status = acService.getCurrentStatus();
this.isOn = status.power;
this.mode = status.mode;
this.fanSpeed = status.fanSpeed;
this.targetTemp = status.temperature;
this.currentTemp = tempSensor.getCurrentTemp();
this.isPersonPresent = presenceDetection.isPersonPresent();
this.connectedDevices = syncService.getConnectedDevices().length;
private updateStatus(status: ACStatus): void {
this.isOn = status.power;
this.mode = status.mode;
this.fanSpeed = status.fanSpeed;
this.targetTemp = status.temperature;
private adjustTemp(delta: number): void {
this.targetTemp += delta;
this.targetTemp = Math.max(16, Math.min(30, this.targetTemp));
acService.setTemperature(this.targetTemp);
private changeMode(mode: ACMode): void {
this.mode = mode;
acService.setMode(mode);
private changeFanSpeed(speed: FanSpeed): void {
this.fanSpeed = speed;
acService.setFanSpeed(speed);
private togglePower(): void {
this.isOn = !this.isOn;
if (this.isOn) {
acService.turnOn();
else {
acService.turnOff();
}
@Component
struct ModeSelector {
private currentMode: ACMode;
private onChange: (mode: ACMode) => void;
build() {
Row() {
ModeButton({
mode: ‘cool’,
active: this.currentMode === ‘cool’,
onClick: () => this.onChange(‘cool’)
})
.margin({ right: 8 })
ModeButton({
mode: 'heat',
active: this.currentMode === 'heat',
onClick: () => this.onChange('heat')
})
.margin({ right: 8 })
ModeButton({
mode: 'dry',
active: this.currentMode === 'dry',
onClick: () => this.onChange('dry')
})
.margin({ right: 8 })
ModeButton({
mode: 'fan',
active: this.currentMode === 'fan',
onClick: () => this.onChange('fan')
})
}
@Component
struct ModeButton {
private mode: ACMode;
private active: boolean;
private onClick: () => void;
build() {
Button(this.getModeText())
.onClick(() => this.onClick())
.width(80)
.height(36)
.backgroundColor(this.active ? ‘#2196F3’ : ‘#FFFFFF’)
.fontColor(this.active ? ‘#FFFFFF’ : ‘#000000’)
private getModeText(): string {
switch (this.mode) {
case 'cool': return '制冷';
case 'heat': return '制热';
case 'dry': return '除湿';
case 'fan': return '送风';
default: return '';
}
@Component
struct FanSpeedSelector {
private currentSpeed: FanSpeed;
private onChange: (speed: FanSpeed) => void;
build() {
Row() {
FanSpeedButton({
speed: ‘auto’,
active: this.currentSpeed === ‘auto’,
onClick: () => this.onChange(‘auto’)
})
.margin({ right: 8 })
FanSpeedButton({
speed: 'low',
active: this.currentSpeed === 'low',
onClick: () => this.onChange('low')
})
.margin({ right: 8 })
FanSpeedButton({
speed: 'medium',
active: this.currentSpeed === 'medium',
onClick: () => this.onChange('medium')
})
.margin({ right: 8 })
FanSpeedButton({
speed: 'high',
active: this.currentSpeed === 'high',
onClick: () => this.onChange('high')
})
}
@Component
struct FanSpeedButton {
private speed: FanSpeed;
private active: boolean;
private onClick: () => void;
build() {
Button(this.getSpeedText())
.onClick(() => this.onClick())
.width(80)
.height(36)
.backgroundColor(this.active ? ‘#2196F3’ : ‘#FFFFFF’)
.fontColor(this.active ? ‘#FFFFFF’ : ‘#000000’)
private getSpeedText(): string {
switch (this.speed) {
case 'auto': return '自动';
case 'low': return '低风';
case 'medium': return '中风';
case 'high': return '高风';
default: return '';
}
智能设置界面
// SmartSettingsView.ets
@Component
struct SmartSettingsView {
@State autoAdjust: boolean = true;
@State presenceControl: boolean = true;
@State learningEnabled: boolean = true;
@State preferredTemp: number = 24;
@State tempOffset: number = 0;
build() {
Column() {
// 自动调节开关
Row() {
Text(‘智能调温’)
.fontSize(16)
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.autoAdjust })
.onChange((isOn) => this.toggleAutoAdjust(isOn))
.margin({ top: 16, bottom: 16 })
// 人体感应控制
Row() {
Text('人体感应控制')
.fontSize(16)
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.presenceControl })
.onChange((isOn) => this.togglePresenceControl(isOn))
.margin({ bottom: 16 })
// 学习模式
Row() {
Text('学习使用习惯')
.fontSize(16)
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.learningEnabled })
.onChange((isOn) => this.toggleLearning(isOn))
.margin({ bottom: 24 })
// 偏好温度
Text('偏好温度')
.fontSize(16)
.margin({ bottom: 8 })
Slider({
value: this.preferredTemp,
min: 18,
max: 30,
step: 1
})
.onChange((value) => this.changePreferredTemp(value))
.margin({ bottom: 24 })
// 温度补偿
Text('温度补偿: ' + (this.tempOffset > 0 ? '+' : '') + this.tempOffset + '°C')
.fontSize(16)
.margin({ bottom: 8 })
Slider({
value: this.tempOffset + 2, // -2到+2范围
min: 0,
max: 4,
step: 0.5
})
.onChange((value) => this.changeTempOffset(value - 2))
.padding(16)
private toggleAutoAdjust(enabled: boolean): void {
this.autoAdjust = enabled;
smartControl.setAutoAdjust(enabled);
private togglePresenceControl(enabled: boolean): void {
this.presenceControl = enabled;
smartControl.setPresenceControl(enabled);
private toggleLearning(enabled: boolean): void {
this.learningEnabled = enabled;
smartControl.setLearningEnabled(enabled);
private changePreferredTemp(temp: number): void {
this.preferredTemp = temp;
smartControl.setPreferredTemp(temp);
private changeTempOffset(offset: number): void {
this.tempOffset = offset;
smartControl.setTempOffset(offset);
}
四、高级功能实现
智能控制服务
// SmartControlService.ets
import { acService } from ‘./ACService’;
import { presenceDetection } from ‘./PresenceDetectionService’;
import { tempPrediction } from ‘./TemperaturePredictionService’;
class SmartControlService {
private static instance: SmartControlService;
private isAutoAdjust: boolean = true;
private isPresenceControl: boolean = true;
private isLearning: boolean = true;
private preferredTemp: number = 24;
private tempOffset: number = 0;
private userHabits: UserHabit[] = [];
private constructor() {
this.initEventListeners();
this.loadUserHabits();
private initEventListeners(): void {
EventBus.on('temperaturePredicted', (predictions) => {
if (this.isAutoAdjust) {
this.adjustBasedOnPrediction(predictions);
});
EventBus.on('presenceChanged', (present) => {
if (this.isPresenceControl) {
this.handlePresenceChange(present);
});
EventBus.on('acStatusChanged', (status) => {
if (this.isLearning) {
this.recordUserHabit(status);
});
private async loadUserHabits(): Promise<void> {
const habits = await storage.get('userHabits');
if (habits) {
this.userHabits = JSON.parse(habits);
}
public static getInstance(): SmartControlService {
if (!SmartControlService.instance) {
SmartControlService.instance = new SmartControlService();
return SmartControlService.instance;
public setAutoAdjust(enabled: boolean): void {
this.isAutoAdjust = enabled;
public setPresenceControl(enabled: boolean): void {
this.isPresenceControl = enabled;
public setLearningEnabled(enabled: boolean): void {
this.isLearning = enabled;
public setPreferredTemp(temp: number): void {
this.preferredTemp = temp;
public setTempOffset(offset: number): void {
this.tempOffset = offset;
private adjustBasedOnPrediction(predictions: TemperaturePrediction[]): void {
const nextHourTemp = predictions[0].temperature;
const targetTemp = this.calculateIdealTemp(nextHourTemp);
if (Math.abs(targetTemp - acService.getCurrentTemp()) > 1) {
acService.setTemperature(targetTemp);
}
private calculateIdealTemp(outdoorTemp: number): number {
// 简单算法: 室内外温差保持在8-10度
let idealTemp: number;
if (outdoorTemp > 30) { // 炎热天气
idealTemp = this.preferredTemp - 1;
else if (outdoorTemp < 10) { // 寒冷天气
idealTemp = this.preferredTemp + 1;
else {
idealTemp = this.preferredTemp;
return idealTemp + this.tempOffset;
private handlePresenceChange(present: boolean): void {
if (!present && acService.isOn()) {
// 无人时调高温度(制冷)或调低温度(制热)以节能
const currentTemp = acService.getCurrentTemp();
const newTemp = acService.getMode() === 'cool' ?
Math.min(28, currentTemp + 2) :
Math.max(18, currentTemp - 2);
acService.setTemperature(newTemp);
else if (present && !acService.isOn()) {
// 有人时恢复偏好温度
acService.turnOn();
acService.setTemperature(this.preferredTemp);
}
private recordUserHabit(status: ACStatus): void {
const now = new Date();
const hour = now.getHours();
const dayOfWeek = now.getDay();
const weather = weatherService.getCurrentWeather();
const habit: UserHabit = {
timestamp: now.getTime(),
hour,
dayOfWeek,
weather,
status
};
this.userHabits.push(habit);
// 保留最近3个月数据
if (this.userHabits.length > 90 * 24) {
this.userHabits.shift();
// 保存数据
storage.set('userHabits', JSON.stringify(this.userHabits));
public getSuggestedSettings(): ACSettings {
if (this.userHabits.length === 0) {
return {
temperature: this.preferredTemp,
mode: 'cool',
fanSpeed: 'auto'
};
// 简单推荐: 使用最频繁的设置组合
const settingCounts = new Map<string, number>();
this.userHabits.forEach(habit => {
const key = {habit.status.temperature}_{habit.status.mode}_${habit.status.fanSpeed};
settingCounts.set(key, (settingCounts.get(key) || 0) + 1);
});
let maxCount = 0;
let bestSetting = '';
settingCounts.forEach((count, key) => {
if (count > maxCount) {
maxCount = count;
bestSetting = key;
});
const [temp, mode, fanSpeed] = bestSetting.split('_');
return {
temperature: parseFloat(temp),
mode: mode as ACMode,
fanSpeed: fanSpeed as FanSpeed
};
}
export const smartControl = SmartControlService.getInstance();
空调控制服务
// ACService.ets
import { irService } from ‘./InfraredService’;
import { syncService } from ‘./SyncService’;
class ACService {
private static instance: ACService;
private currentStatus: ACStatus = {
power: false,
mode: ‘cool’,
temperature: 26,
fanSpeed: ‘auto’,
brand: ‘default’
};
private constructor() {
this.loadLastStatus();
private async loadLastStatus(): Promise<void> {
const status = await storage.get('lastACStatus');
if (status) {
this.currentStatus = JSON.parse(status);
}
public static getInstance(): ACService {
if (!ACService.instance) {
ACService.instance = new ACService();
return ACService.instance;
public turnOn(): void {
if (this.currentStatus.power) return;
this.currentStatus.power = true;
this.sendCommand('power');
this.saveAndSync();
public turnOff(): void {
if (!this.currentStatus.power) return;
this.currentStatus.power = false;
this.sendCommand('power');
this.saveAndSync();
public setMode(mode: ACMode): void {
if (this.currentStatus.mode === mode) return;
this.currentStatus.mode = mode;
this.sendCommand(mode);
this.saveAndSync();
public setTemperature(temp: number): void {
if (this.currentStatus.temperature === temp) return;
this.currentStatus.temperature = temp;
this.sendCommand('temperature');
this.saveAndSync();
public setFanSpeed(speed: FanSpeed): void {
if (this.currentStatus.fanSpeed === speed) return;
this.currentStatus.fanSpeed = speed;
this.sendCommand(speed);
this.saveAndSync();
private sendCommand(command: string): void {
try {
irService.sendCode(this.currentStatus.brand, command);
catch (error) {
console.error('Failed to send IR command:', error);
}
private saveAndSync(): void {
storage.set(‘lastACStatus’, JSON.stringify(this.currentStatus));
syncService.syncACStatus(this.currentStatus);
EventBus.emit(‘acStatusChanged’, this.currentStatus);
public getCurrentStatus(): ACStatus {
return { ...this.currentStatus };
public isOn(): boolean {
return this.currentStatus.power;
public getCurrentTemp(): number {
return this.currentStatus.temperature;
public getMode(): ACMode {
return this.currentStatus.mode;
public getFanSpeed(): FanSpeed {
return this.currentStatus.fanSpeed;
public setBrand(brand: string): void {
this.currentStatus.brand = brand;
this.saveAndSync();
}
export const acService = ACService.getInstance();
五、总结
本智能空调控制系统实现了以下核心价值:
万能遥控:学习支持各种品牌空调的红外编码
智能预测:基于环境数据预测温度变化趋势
人体感知:多传感器融合检测室内人员存在
跨端协同:多设备实时同步空调状态和控制
节能优化:根据使用习惯和场景自动调节
扩展方向:
增加语音控制功能
开发基于地理围栏的智能控制
集成到智能家居场景联动
添加能耗统计和节能报告
支持更多家电设备的控制
注意事项:
红外学习需要对准遥控器发射头
温度预测准确度依赖传感器数据质量
人体检测可能存在误判
多设备控制需登录相同账号
首次使用建议进行完整设置向导
