鸿蒙跨端家庭急救指导系统开发指南 原创

进修的泡芙
发布于 2025-6-22 17:12
浏览
0收藏

鸿蒙跨端家庭急救指导系统开发指南

一、系统架构设计

基于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的分布式技术,我们构建了一个智能化的急救指导系统,能够在紧急情况下提供专业指导,并支持多人协作,大大提高急救效率和成功率。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐