
鸿蒙跨端家庭急救指导系统开发指南 原创
鸿蒙跨端家庭急救指导系统开发指南
一、系统架构设计
基于HarmonyOS的AI能力和分布式技术,构建智能急救指导系统:
图像识别层:识别伤情和急救场景
指导引擎层:提供急救步骤指导
多人协作层:支持多设备协同急救操作
跨端同步层:实时同步急救状态和操作指引
!https://example.com/harmony-firstaid-system-arch.png
二、核心代码实现
急救指导服务
// FirstAidService.ets
import ai from ‘@ohos.ai’;
import distributedData from ‘@ohos.distributedData’;
import { FirstAidScenario, FirstAidStep, EmergencyCase } from ‘./FirstAidTypes’;
class FirstAidService {
private static instance: FirstAidService = null;
private modelManager: ai.ModelManager;
private dataManager: distributedData.DataManager;
private listeners: FirstAidListener[] = [];
private currentCase: EmergencyCase | null = null;
private constructor() {
this.initModelManager();
this.initDataManager();
public static getInstance(): FirstAidService {
if (!FirstAidService.instance) {
FirstAidService.instance = new FirstAidService();
return FirstAidService.instance;
private initModelManager(): void {
try {
this.modelManager = ai.createModelManager(getContext());
// 加载急救场景识别模型
this.modelManager.loadModel({
modelName: 'firstaid_scenario',
modelPath: 'resources/rawfile/firstaid_scenario.model',
callback: (err, data) => {
if (err) {
console.error('加载急救模型失败:', JSON.stringify(err));
}
});
catch (err) {
console.error('初始化模型管理器失败:', JSON.stringify(err));
}
private initDataManager(): void {
this.dataManager = distributedData.createDataManager({
bundleName: ‘com.example.firstaid’,
area: distributedData.Area.GLOBAL,
isEncrypted: true
});
this.dataManager.registerDataListener('firstaid_sync', (data) => {
this.handleSyncData(data);
});
public async requestPermissions(): Promise<boolean> {
try {
const permissions = [
'ohos.permission.USE_AI',
'ohos.permission.CAMERA',
'ohos.permission.DISTRIBUTED_DATASYNC'
];
const result = await abilityAccessCtrl.requestPermissionsFromUser(
getContext(),
permissions
);
return result.grantedPermissions.length === permissions.length;
catch (err) {
console.error('请求权限失败:', JSON.stringify(err));
return false;
}
public async analyzeEmergency(imageData: ArrayBuffer): Promise<EmergencyCase> {
try {
const input = {
data: imageData,
width: 224,
height: 224,
format: ‘RGB’
};
const output = await this.modelManager.runModel({
modelName: 'firstaid_scenario',
input: input
});
const scenario: FirstAidScenario = output.result.scenario;
const steps = this.getStepsForScenario(scenario);
const emergencyCase: EmergencyCase = {
id: Date.now().toString(),
scenario: scenario,
currentStep: 0,
steps: steps,
imageData: imageData,
timestamp: Date.now(),
helpers: [],
status: 'in_progress'
};
this.currentCase = emergencyCase;
this.syncCase(emergencyCase);
return emergencyCase;
catch (err) {
console.error('急救场景识别失败:', JSON.stringify(err));
throw err;
}
private getStepsForScenario(scenario: FirstAidScenario): FirstAidStep[] {
// 实际应用中应从数据库或配置文件中获取
const scenarios = {
‘burn’: [
id: 1, instruction: ‘用冷水冲洗伤处15-20分钟’, image: ‘burn_step1.jpg’ },
id: 2, instruction: ‘不要使用冰块或油脂涂抹’, image: ‘burn_step2.jpg’ },
id: 3, instruction: ‘用干净纱布轻轻覆盖伤处’, image: ‘burn_step3.jpg’ }
],
'cut': [
id: 1, instruction: ‘用干净布按压止血’, image: ‘cut_step1.jpg’ },
id: 2, instruction: ‘清洁伤口周围皮肤’, image: ‘cut_step2.jpg’ },
id: 3, instruction: ‘用消毒纱布包扎’, image: ‘cut_step3.jpg’ }
],
'choking': [
id: 1, instruction: ‘站在患者身后,双臂环绕其腰部’, image: ‘choking_step1.jpg’ },
id: 2, instruction: ‘一手握拳,拇指侧抵住腹部中线’, image: ‘choking_step2.jpg’ },
id: 3, instruction: ‘快速向上冲击’, image: ‘choking_step3.jpg’ }
};
return scenarios[scenario] || [];
public async nextStep(helper: PlayerInfo): Promise<EmergencyCase> {
if (!this.currentCase) {
throw new Error('当前没有急救案例');
const updatedCase: EmergencyCase = {
...this.currentCase,
currentStep: this.currentCase.currentStep + 1,
helpers: [...this.currentCase.helpers, helper],
status: this.currentCase.currentStep + 1 >= this.currentCase.steps.length
‘completed’
‘in_progress’
};
this.currentCase = updatedCase;
this.syncCase(updatedCase);
return updatedCase;
public async addHelper(helper: PlayerInfo): Promise<EmergencyCase> {
if (!this.currentCase) {
throw new Error('当前没有急救案例');
const updatedCase: EmergencyCase = {
...this.currentCase,
helpers: [...this.currentCase.helpers, helper]
};
this.currentCase = updatedCase;
this.syncCase(updatedCase);
return updatedCase;
private syncCase(emergencyCase: EmergencyCase): void {
this.dataManager.syncData('firstaid_sync', {
type: 'emergency_case',
data: emergencyCase,
timestamp: Date.now()
});
private handleSyncData(data: any): void {
if (!data || data.type !== 'emergency_case') return;
this.currentCase = data.data;
this.notifyListeners(data.data);
private notifyListeners(caseData: EmergencyCase): void {
this.listeners.forEach(listener => {
listener.onCaseUpdated?.(caseData);
});
public addListener(listener: FirstAidListener): void {
if (!this.listeners.includes(listener)) {
this.listeners.push(listener);
}
public removeListener(listener: FirstAidListener): void {
this.listeners = this.listeners.filter(l => l !== listener);
}
interface FirstAidListener {
onCaseUpdated?(caseData: EmergencyCase): void;
export const firstAidService = FirstAidService.getInstance();
相机服务封装
// CameraService.ets
import camera from ‘@ohos.multimedia.camera’;
import image from ‘@ohos.multimedia.image’;
class CameraService {
private static instance: CameraService = null;
private cameraManager: camera.CameraManager;
private cameraInput: camera.CameraInput;
private previewOutput: camera.PreviewOutput;
private captureSession: camera.CaptureSession;
private imageReceiver: image.ImageReceiver;
private constructor() {
this.initCamera();
public static getInstance(): CameraService {
if (!CameraService.instance) {
CameraService.instance = new CameraService();
return CameraService.instance;
private initCamera(): void {
try {
const context = getContext() as common.Context;
this.cameraManager = camera.getCameraManager(context);
// 获取后置摄像头
const cameras = this.cameraManager.getSupportedCameras();
const backCamera = cameras.find(cam => cam.position === camera.CameraPosition.BACK);
if (!backCamera) {
throw new Error('未找到后置摄像头');
// 创建相机输入
this.cameraInput = this.cameraManager.createCameraInput(backCamera);
// 创建预览输出
const previewProfile = this.cameraManager.getSupportedOutputCapability(backCamera)
.previewProfiles[0];
this.previewOutput = this.cameraManager.createPreviewOutput(previewProfile);
// 创建图像接收器
this.imageReceiver = image.createImageReceiver(
224, 224,
image.ImageFormat.RGB_888,
);
// 创建捕获会话
this.captureSession = this.cameraManager.createCaptureSession();
this.captureSession.beginConfig();
this.captureSession.addInput(this.cameraInput);
this.captureSession.addOutput(this.previewOutput);
this.captureSession.commitConfig();
this.captureSession.start();
catch (err) {
console.error('初始化相机失败:', JSON.stringify(err));
}
public async captureFrame(): Promise<ArrayBuffer> {
try {
const image = await this.imageReceiver.readNextImage();
const buffer = await image.getComponent(image.ComponentType.RGB);
image.release();
return buffer.byteArray;
catch (err) {
console.error('捕获帧失败:', JSON.stringify(err));
throw err;
}
public startPreview(surfaceId: string): void {
this.previewOutput.start(surfaceId);
public stopPreview(): void {
this.previewOutput.stop();
public release(): void {
this.captureSession.stop();
this.cameraInput.release();
this.previewOutput.release();
this.captureSession.release();
}
export const cameraService = CameraService.getInstance();
主界面实现
// MainScreen.ets
import { firstAidService } from ‘./FirstAidService’;
import { cameraService } from ‘./CameraService’;
import { EmergencyCase, PlayerInfo } from ‘./FirstAidTypes’;
@Component
export struct MainScreen {
@State hasPermission: boolean = false;
@State isAnalyzing: boolean = false;
@State currentCase: EmergencyCase | null = null;
@State previewSurfaceId: string = ‘’;
@State showHelp: boolean = false;
// 模拟玩家信息
private localPlayer: PlayerInfo = {
deviceId: ‘device_001’,
nickname: ‘主操作者’,
avatar: ‘resources/rawfile/avatar_doctor.png’
};
build() {
Column() {
// 标题栏
Row() {
Text(‘家庭急救指导’)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Button(this.hasPermission ? '帮助' : '授权')
.width(80)
.onClick(() => {
if (this.hasPermission) {
this.showHelp = !this.showHelp;
else {
this.requestPermissions();
})
.padding(10)
.width('100%')
// 帮助信息
if (this.showHelp) {
Column() {
Text('使用说明')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('1. 将摄像头对准伤处\n2. 系统自动识别伤情\n3. 按照步骤指导操作\n4. 可邀请家人协助')
.fontSize(16)
.textAlign(TextAlign.Start)
.padding(15)
.width('90%')
.backgroundColor('#F5F5F5')
.borderRadius(8)
.margin({ bottom: 20 })
// 相机预览区域
Stack() {
if (this.hasPermission) {
// 相机预览Surface
Surface({
id: this.previewSurfaceId,
type: SurfaceType.SURFACE_TEXTURE,
width: '100%',
height: 300
})
.onAppear(() => {
this.previewSurfaceId = preview_${Date.now()};
cameraService.startPreview(this.previewSurfaceId);
})
.onDisappear(() => {
cameraService.stopPreview();
})
// 分析按钮
if (!this.currentCase && !this.isAnalyzing) {
Button('识别伤情')
.width(150)
.height(50)
.fontSize(20)
.backgroundColor('#FF5252')
.position({ x: '50%', y: '80%' })
.margin({ left: -75 })
.onClick(() => {
this.startAnalysis();
})
else if (this.isAnalyzing) {
Column() {
Progress({})
.width(50)
.height(50)
Text('分析中...')
.fontSize(16)
.margin({ top: 10 })
.width(‘100%’)
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
} else {
Column() {
Text('需要权限')
.fontSize(18)
.margin({ bottom: 10 })
Text('请点击右上角"授权"按钮,允许应用访问相机和AI功能')
.fontSize(16)
.fontColor('#666666')
.padding(20)
.width('90%')
.backgroundColor('#F5F5F5')
.borderRadius(8)
.margin({ top: 50 })
}
.width('100%')
.height(300)
.margin({ bottom: 20 })
// 急救指导区域
if (this.currentCase) {
Column() {
// 伤情识别结果
Row() {
Text('识别结果:')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ right: 10 })
Text(this.getScenarioName(this.currentCase.scenario))
.fontSize(16)
.fontColor('#FF5252')
.margin({ bottom: 20 })
// 当前步骤
Column() {
Text(步骤 {this.currentCase.currentStep + 1}/{this.currentCase.steps.length})
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text(this.currentCase.steps[this.currentCase.currentStep].instruction)
.fontSize(16)
.margin({ bottom: 15 })
Image(this.currentCase.steps[this.currentCase.currentStep].image)
.width('100%')
.height(200)
.objectFit(ImageFit.Contain)
.margin({ bottom: 20 })
if (this.currentCase.currentStep < this.currentCase.steps.length - 1) {
Button('下一步')
.width(200)
.height(50)
.fontSize(18)
.backgroundColor('#FF5252')
.onClick(() => {
firstAidService.nextStep(this.localPlayer);
})
else {
Column() {
Text('急救完成')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#4CAF50')
.margin({ bottom: 10 })
Text('请根据情况决定是否需要专业医疗帮助')
.fontSize(14)
.fontColor('#666666')
.width(‘100%’)
.padding(15)
.backgroundColor('#E8F5E9')
.borderRadius(8)
}
.padding(20)
.width('100%')
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#FFEBEE' })
.borderRadius(8)
// 协助者信息
if (this.currentCase.helpers.length > 0) {
Column() {
Text('协助者')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Row() {
ForEach(this.currentCase.helpers, (helper) => {
Column() {
Image(helper.avatar)
.width(40)
.height(40)
.borderRadius(20)
Text(helper.nickname)
.fontSize(12)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ right: 15 })
})
}
.width('100%')
.margin({ top: 20 })
}
.width('100%')
}
.width('100%')
.height('100%')
.padding(20)
.onAppear(() => {
this.checkPermissions();
firstAidService.addListener({
onCaseUpdated: (caseData) => {
this.handleCaseUpdated(caseData);
});
})
.onDisappear(() => {
firstAidService.removeListener({
onCaseUpdated: (caseData) => {
this.handleCaseUpdated(caseData);
});
cameraService.release();
})
private getScenarioName(scenario: FirstAidScenario): string {
const names = {
'burn': '烧伤',
'cut': '割伤',
'choking': '窒息',
'fracture': '骨折',
'bleeding': '大出血'
};
return names[scenario] || '紧急情况';
private async checkPermissions(): Promise<void> {
try {
const permissions = [
'ohos.permission.USE_AI',
'ohos.permission.CAMERA',
'ohos.permission.DISTRIBUTED_DATASYNC'
];
const result = await abilityAccessCtrl.verifyPermissions(
getContext(),
permissions
);
this.hasPermission = result.every(perm => perm.granted);
catch (err) {
console.error('检查权限失败:', JSON.stringify(err));
this.hasPermission = false;
}
private async requestPermissions(): Promise<void> {
this.hasPermission = await firstAidService.requestPermissions();
if (!this.hasPermission) {
prompt.showToast({ message: '授权失败,无法使用急救指导功能' });
}
private async startAnalysis(): Promise<void> {
try {
this.isAnalyzing = true;
// 捕获当前帧
const frame = await cameraService.captureFrame();
// 分析急救场景
this.currentCase = await firstAidService.analyzeEmergency(frame);
catch (err) {
console.error('伤情分析失败:', JSON.stringify(err));
prompt.showToast({ message: '分析失败,请重试' });
finally {
this.isAnalyzing = false;
}
private handleCaseUpdated(caseData: EmergencyCase): void {
this.currentCase = caseData;
}
类型定义
// FirstAidTypes.ets
export type FirstAidScenario = ‘burn’ ‘cut’ ‘choking’ ‘fracture’
‘bleeding’;
export interface FirstAidStep {
id: number;
instruction: string;
image: string;
export interface PlayerInfo {
deviceId: string;
nickname: string;
avatar: string;
export interface EmergencyCase {
id: string;
scenario: FirstAidScenario;
currentStep: number;
steps: FirstAidStep[];
imageData: ArrayBuffer;
timestamp: number;
helpers: PlayerInfo[];
status: ‘in_progress’ | ‘completed’;
三、项目配置与权限
权限配置
// module.json5
“module”: {
"requestPermissions": [
“name”: “ohos.permission.USE_AI”,
"reason": "使用AI模型识别伤情"
},
“name”: “ohos.permission.CAMERA”,
"reason": "拍摄伤处照片"
},
“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,
"reason": "同步急救状态"
],
"abilities": [
“name”: “MainAbility”,
"type": "page",
"visible": true
},
“name”: “CameraAbility”,
"type": "service",
"backgroundModes": ["camera"]
]
}
四、总结与扩展
本急救指导系统实现了以下核心功能:
智能伤情识别:准确识别常见急救场景
分步操作指导:提供清晰的急救步骤指引
多人协作模式:支持多设备协同急救操作
实时状态同步:所有参与者的操作实时同步
扩展方向:
AR操作指引:通过AR技术展示急救操作
急救知识库:集成更多急救场景和知识
紧急呼叫功能:一键呼叫急救服务
语音指导:提供语音操作指引
急救演练模式:模拟急救场景进行训练
医疗记录同步:与医院系统对接传输急救记录
通过HarmonyOS的分布式技术,我们构建了一个智能化的急救指导系统,能够在紧急情况下提供专业指导,并支持多人协作,大大提高急救效率和成功率。
