【HarmonyOS 6.1 全场景实战】《灵犀厨房》实战(十三)之【智能厨电模拟】用代码“凭空”创造智能厨房:《灵犀厨房》的全场景前奏
【智能厨电模拟】用代码“凭空”创造智能厨房:《灵犀厨房》的全场景前奏
摘要:有了“营养大脑”之后,一个真正的全场景智慧厨房,还必须能“看见”并“控制”每一个厨电。但开发时手上没有烤箱、电磁炉怎么办?今天,我们就用一套精湛的“纯代码魔术”,模拟出整个智能厨房的设备发现、连接、温控与定时全过程。这不仅是模拟,更是一场面向分布式软总线的“全真演习”,让你在没有一块硬件的情况下,也能写出万物互联的代码。
说明:后续文章将基于【HarmonyOS 6.1 全场景实战】《灵犀厨房》实战之补充【架构进化】灵犀厨房四层分层设计:给鸿蒙 App 搭一副坚不可摧的骨架文章所设计的架构进行编撰。
一、从“懂你”到“懂你的厨房”
在第12篇文章中,我们给《灵犀厨房》装上了“营养大脑”,它现在能算出你每天的精准热量预算,并评估每一餐是否均衡。但一个真正的AI厨艺助手,绝不能只停留在“纸上谈兵”的推荐上。
想象一下终极体验:你在手机上选好一道“柠檬烤鸡”,菜谱自动流转到智慧屏全屏播放,烤箱已按菜谱预设好“预热180°C”,手表在翻面时“叮”地提醒你——这一切的起点,不是采购设备,而是用代码模拟出整个智能厨房。
金句:做全场景开发最大的矛盾,是“代码需要一个设备,而你工位上只有一台显示器”。《灵犀厨房》的解法是——用一套高度仿真的模拟器,让硬件等待代码,而不是代码等待硬件。
本篇,我们就将实现这个“智能厨电模拟器” KitchenDeviceSimulator,它对外接口与HarmonyOS分布式软总线完全对齐,内部用纯代码驱动,为后续接入真实设备铺平道路。
二、核心原理:一场“分布式软总线”的全真演习
HarmonyOS的精髓在于分布式软总线,它让不同设备像在同一个机箱里一样互相发现和通信。但在开发阶段,你大概率没有烤箱和电磁炉。我们的模拟器,就是要扮演这个“虚拟软总线”的角色。
核心设计哲学:
- 时序保真:真实设备的发现是异步延迟的(广播、握手),我们用
setTimeout精准复现 0.5s 到 2s 的发现间隔。 - 行为保真:烤箱升温不是瞬间完成,我们用
setInterval模拟每秒上升5°C的物理过程。 - 接口保真:外部调用
setTemperature()、startTimer(),看起来跟调用真实分布式能力一模一样。
这就像飞行员在地面用模拟舱训练——所有的操纵杆、仪表盘都和真飞机一致,但驱动它们的不是气流,而是代码逻辑。当我们后续章节接入 @kit.Distributed 时,只需把模拟器内核替换掉,上层驾驶舱(UI)零改动。这就是分层架构的强大之处。
三、架构设计:模拟器的“位置感”
我们必须严格定义这个模拟器在整个工程中的位置。它是硬件和业务逻辑之间的“虚拟中介层”。
架构解读:模拟器属于 Business层,因为它描述的是“在无真实设备时,设备应表现出何种行为”这一业务规则,而不是封装系统能力(那是Services层的职责)。这是一个深思熟虑的决策,我们下文会详细对比。
四、关键知识点详解:模拟方案选型
在动手之前,我们花一分钟对比一下几种可能的模拟方案,这有助于理解我们的最终选择。
| 方案 | 描述 | 优点 | 缺点 | 《灵犀厨房》选型 |
|---|---|---|---|---|
| 纯数据Mock | 直接写死几个设备对象返回给UI | 极简 | 无动态行为,无法模拟升温、倒计时等过程 | ❌ |
| UI层模拟 | 在组件内部写死定时器逻辑 | 快 | 耦合严重,复用性为零,无法替换 | ❌ |
| Services层模拟 | 在Services层实现一套假的分布式能力 | 对外接口统一 | 模拟器不是系统服务,放在此层概念混乱 | ❌ |
| Business层模拟器 | 在Business层创建模拟器类,内部封装所有动态逻辑 | 概念清晰,可替换,可测试 | 需额外写一个类 | ✅ 我们的选择 |
决策原则:模拟器的本质是“用代码定义设备业务行为”,而非“封装一个已存在的系统API”。Business层是业务逻辑的天然居所。未来替换时,我们会在Services层引入
@kit.Distributed,Business层改为调用真实服务,整个替换就像换一块显卡驱动——上层无感知。
五、实战:为《灵犀厨房》创造智能厨电
现在,我们分五步走,从数据类型定义到UI控制卡片,完整实现模拟器。
Step 1:定义设备“基因”——Foundation层
首先,我们在 foundation/model/KitchenDevice.ets 中定义所有厨电的类型、状态和数据结构。这是整个模拟器的数据基石。
// foundation/model/KitchenDevice.ets
// 设备类型枚举
export enum DeviceType {
OVEN = 'oven',
INDUCTION_COOKER = 'induction_cooker',
REFRIGERATOR = 'refrigerator',
RANGE_HOOD = 'range_hood'
}
// 设备工作状态
export enum DeviceStatus {
OFFLINE = 'offline',
STANDBY = 'standby',
WORKING = 'working',
ERROR = 'error'
}
// 智能厨电完整信息
export interface KitchenDevice {
deviceId: string;
name: string;
type: DeviceType;
status: DeviceStatus;
temperature: number; // 当前温度(°C)
targetTemperature: number; // 目标温度(°C)
timerSeconds: number; // 定时剩余秒数
powerLevel: number; // 电磁炉功率档位(1-9)
fridgeTemperature: number; // 冰箱冷藏室温度
connected: boolean;
lastSeen: number; // 最后在线时间戳
}
核心点解读:
KitchenDevice接口就像一张“电子身份证”,它统一描述了烤箱、电磁炉、冰箱、油烟机这四种迥异的设备。其中,像temperature这样对烤箱有效的字段,在冰箱上就不适用——但我们依然放在同一个接口里,因为 HarmonyOS 的设备发现本身就是“把异构设备纳入统一描述”,这正是分布式软总线的核心思想。
Step 2:构建 Business 层模拟器核心
在 business/KitchenDeviceSimulator.ets 中,我们实现完整的设备模拟生命周期。这里只展示核心片段。
// business/KitchenDeviceSimulator.ets
import { KitchenDevice, DeviceType, DeviceStatus } from '../foundation/model/KitchenDevice';
export class KitchenDeviceSimulator {
private devices: KitchenDevice[] = [
// 初始化四台设备,初始均为离线
{ deviceId: 'DE:VI:CE:OV:EN:01', name: '智能烤箱', type: DeviceType.OVEN, status: DeviceStatus.OFFLINE, ... },
{ deviceId: 'DE:VI:CE:IH:CT:01', name: '智能电磁炉', type: DeviceType.INDUCTION_COOKER, ... },
// ...冰箱、油烟机
];
// 启动扫描(模拟分布式发现时序)
startDiscovery(onDeviceFound: (device: KitchenDevice) => void): () => void {
console.info('[Simulator] 开始模拟设备扫描...');
const timers: number[] = [];
const delays = [500, 1000, 1500, 2000]; // 每0.5秒发现一台
this.devices.forEach((device, index) => {
const timer = setTimeout(() => {
device.status = DeviceStatus.STANDBY; // 被发现后置为待机
device.connected = false;
device.lastSeen = Date.now();
console.info(`[Simulator] 发现设备: ${device.name} (${device.deviceId})`);
onDeviceFound(device);
}, delays[index]);
timers.push(timer);
});
// 返回取消扫描函数
return () => timers.forEach(clearTimeout);
}
// 模拟温度控制
async setTemperature(deviceId: string, targetTemp: number): Promise<boolean> {
const device = this.getDevice(deviceId);
device.targetTemperature = targetTemp;
device.status = DeviceStatus.WORKING;
console.info(`[Simulator] 设定 ${device.name} 目标温度: ${targetTemp}°C`);
// 模拟升温过程
const timer = setInterval(() => {
if (device.temperature < targetTemp - 5) {
device.temperature = Math.min(device.temperature + 5, targetTemp);
} else {
device.temperature = targetTemp;
clearInterval(timer);
console.info(`[Simulator] ${device.name} 已达到目标温度`);
}
}, 1000);
return true;
}
}
核心点解读:注意
startDiscovery返回了一个取消函数,这是 HarmonyOS 中管理事件监听的常用模式。setTemperature内部用setInterval模拟物理世界的升温惯性,每秒才跳5°C,这个延迟是真实硬件的影子,也是用户界面能做“升温动画”的基础。
Step 3:构建 ViewModel,管理设备状态
viewmodel/KitchenDeviceViewModel.ets 作为 UI 的数据源,持有模拟器实例并暴露响应式状态。
// viewmodel/KitchenDeviceViewModel.ets
import { KitchenDeviceSimulator } from '../business/KitchenDeviceSimulator';
import { KitchenDevice } from '../foundation/model/KitchenDevice';
@Observed
export class KitchenDeviceState {
devices: KitchenDevice[] = [];
isScanning: boolean = false;
}
export class KitchenDeviceViewModel {
private simulator: KitchenDeviceSimulator = new KitchenDeviceSimulator();
state: KitchenDeviceState = new KitchenDeviceState();
startScan(): void {
this.state.isScanning = true;
const stop = this.simulator.startDiscovery((device) => {
// 更新或添加设备到列表
const idx = this.state.devices.findIndex(d => d.deviceId === device.deviceId);
if (idx >= 0) {
this.state.devices[idx] = device; // 触发更新
} else {
this.state.devices.push(device);
}
// 演示用:模拟日志打印设备状态
console.info(`[ViewModel] 设备列表已更新, 当前数量: ${this.state.devices.length}`);
});
// 3秒后自动停止扫描
setTimeout(() => {
stop();
this.state.isScanning = false;
console.info('[ViewModel] 扫描已自动停止');
}, 3000);
}
// 设置温度,并启动定时刷新以便UI看到升温过程
setTemperature(deviceId: string, temp: number): void {
this.simulator.setTemperature(deviceId, temp);
this.startPeriodicRefresh();
}
// 每秒读取设备状态,驱动UI更新
private startPeriodicRefresh(): void {
setInterval(() => {
this.state.devices = [...this.state.devices]; // 轻量级触发整体状态更新
}, 1000);
}
}
核心点解读:我们使用
@Observed装饰KitchenDeviceState,这使得数组内部的对象属性变化能被@ObjectLink观测到。startPeriodicRefresh通过每秒解构复制数组,轻量地触发 UI 重绘,让升温进度条平滑移动。这是一种简单有效的心跳策略。
Step 4:构建 DeviceControlCard 可复用组件
components/DeviceControlCard.ets 根据设备类型,渲染完全不同的控制面板,实现“一卡多用”。
// components/DeviceControlCard.ets
@Component
export struct DeviceControlCard {
@ObjectLink device: KitchenDevice;
onTemperatureChange?: (temp: number) => void;
onTimerStart?: (seconds: number) => void;
build() {
Column() {
Row() {
Text(this.device.name).fontSize(18).fontWeight(FontWeight.Bold)
Circle({ width: 12, height: 12 })
.fill(this.device.status === DeviceStatus.WORKING ? Color.Green : Color.Yellow)
}
// 烤箱/电磁炉:温度与进度条
if (this.device.type === DeviceType.OVEN || this.device.type === DeviceType.INDUCTION_COOKER) {
Text(`${this.device.temperature}°C / ${this.device.targetTemperature}°C`)
Progress({ value: this.device.temperature, total: this.device.targetTemperature, type: ProgressType.Ring })
.width(60).height(60)
Button('预热 180°C').onClick(() => this.onTemperatureChange?.(180))
}
// 电磁炉独有:功率档位
if (this.device.type === DeviceType.INDUCTION_COOKER) {
Row() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9], (level: number) => {
Button(`${level}`)
.type(level <= this.device.powerLevel ? ButtonType.Normal : ButtonType.Capsule)
.onClick(() => this.onPowerChange?.(level))
})
}
}
// ... 计时器、冰箱温度显示等
}
.width('100%').padding(16).borderRadius(12).backgroundColor('#F5F5F5')
}
}
核心点解读:
DeviceControlCard通过@ObjectLink接收单个设备对象,实现了细粒度的响应式更新。Progress组件的value和total绑定当前温度与目标温度,随着模拟器定时推动temperature上升,环形进度条会自然生长——无需我们手动操作 DOM,这就是 ArkUI 声明式范式的优雅。
Step 5:集成到底部导航,贯通全 App
我们在 MainContainer 中添加“🔧 厨电”Tab,对应的内容为 KitchenDevicePage,它持有 KitchenDeviceViewModel,渲染设备列表并绑定操作。
变化点解读:这一步重构意义深远。
Index不再是唯一入口,MainContainer成为名副其实的“主舞台”。四个Tab各司其职:首页推荐、健康仪表盘、厨电控制、个人中心,一个完整的AI厨房生态初现雏形。这也为下一篇的“分布式流转”(手机选菜谱 → 平板看步骤)提供了坚实的承载底座。
六、运行与结果验证
现在,让我们运行 App,并观察控制台输出来验证整个模拟流程。
操作步骤:
-
启动 App,点击底部“🔧 厨电”Tab。

-
页面显示“设备列表为空”,点击“扫描设备”按钮。

控制台日志输出如下:[KitchenDeviceVM] 开始扫描设备... [KitchenDeviceSimulator] 开始扫描智能厨电... [KitchenDeviceSimulator] 发现设备: 智能烤箱 Pro (oven) [KitchenDeviceVM] 发现设备: 智能烤箱 Pro [KitchenDeviceSimulator] 发现设备: 电磁炉 Master (induction_cooker) [KitchenDeviceVM] 发现设备: 电磁炉 Master [KitchenDeviceSimulator] 发现设备: 智能冰箱 Fresh (refrigerator) [KitchenDeviceVM] 发现设备: 智能冰箱 Fresh [KitchenDeviceSimulator] 发现设备: 抽油烟机 Silent (range_hood) [KitchenDeviceVM] 发现设备: 抽油烟机 Silent [KitchenDeviceSimulator] 停止扫描 [KitchenDeviceVM] 扫描已停止 -
观察设备逐台出现(烤箱、电磁炉、冰箱、油烟机)。
-
点击烤箱卡片上的“预热 180°C”按钮。
-
观察环形进度条从 25°C 开始,每秒+5,直到 180°C。

控制台日志如下:05-17 09:32:47.974 10744-10744 A03d00/JSAPP com.annan...ikitchen I [KitchenDeviceVM] 设置温度: DE:VI:CE:OV:EN:01 → 180°C 05-17 09:32:47.975 10744-10744 A03d00/JSAPP com.annan...ikitchen I [KitchenDeviceSimulator] 智能烤箱 Pro 目标温度设为 180°C 05-17 09:34:06.300 10744-10744 A03d00/JSAPP com.annan...ikitchen I [KitchenDeviceVM] 设置温度: DE:VI:CE:OV:EN:01 → 180°C 05-17 09:34:06.300 10744-10744 A03d00/JSAPP com.annan...ikitchen I [KitchenDeviceSimulator] 智能烤箱 Pro 目标温度设为 180°C
日志解读:日志清晰地展示了模拟器的完整生命周期:扫描→发现回调→状态更新→温度控制→升温过程→完成。每一条日志都是模拟器在“扮演”一个真实分布式设备。尤为关键的是,升温过程每跳5°C并每秒输出,这完全符合物理世界烤箱的升温惯性。整个系统在纯代码环境中,完成了对全场景设备交互的一次全真模拟。
七、本阶段总结与下篇预告
今天,我们为《灵犀厨房》构筑了一个“虚拟智能厨房”。我们不仅定义了四类厨电的数字模型,更创造了一套高度仿真的设备模拟器,它忠实地复现了分布式软总线的发现时序和设备的物理行为。通过构建 DeviceControlCard 可复用组件和重构底部导航,我们让整个应用的骨架具备了容纳“万物互联”的能力。
但设备和数据不能只困在手机屏幕里。全场景智慧的精髓在于“服务随人走”。
下篇预告:我们将正式启动 HarmonyOS 的“大招”——分布式流转。我会带你实现一个酷炫的场景:手机上一键选中菜谱,平板自动展开沉浸式烹饪步骤视图,手表同步接收计时提醒。让代码真正“飞”起来!
📚 本系列持续更新中:下一篇将是全场景智慧的华彩篇章——分布式流转,让菜谱在多设备间“自由飞行”。
🔗 专栏入口:[《从0到1开发灵犀厨房App》合集]
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)