在上一面文章中分析了HSM的核心代码,本文章主要是对HSM的应用解析,以相机拍照为例子,对状态和事件的调用,实现拍照、查看照片、切换拍照模式、低电量关机等功能。

一、状态和事件

这个例子里面用了四种事件、六个状态,作用文章原文有解释:

 总结来说也就是举了个相机拍照的例子,相机有三个按键事件,分别为电源按键(PWR)、快门按键(RELEASE)和模式选择按键(MODE),一个被动触发事件,为电池电量低(LOWBATT);

相机有五个状态,分别为相机处于电源打开状态(on)、处于电源关闭状态(off)、处于相机拍照状态(OnShoot)、处于查看照片状态(OnDisplay)、处于查看菜单状态(OnDispMenu),OnDisp应该是OnDisplay和OnDispMenu状态的父状态;

二、代码解析

首先定义了程序中会用到的四种事件和六个状态的句柄,basic最原始的父状态句柄;

#include "hsm.h"
#include <stdio.h>// Camera HSM Events
#define HSME_PWR        (HSME_START)
#define HSME_RELEASE    (HSME_START + 1)
#define HSME_MODE       (HSME_START + 2)
#define HSME_LOWBATT    (HSME_START + 3)typedef struct CAMERA_T
{/*Class that implements the Camera HSM and inherits from the HSM classCreating a HSM requires the following steps:1) Initialize the base HSM class2) Define the HSM states hierarchy3) Set the starting state4) Define the state handlersa) State handler must return "None" if the event IS handledb) State handler must return "event" if the event IS NOT handledc) State handler may handle the ENTRY event for state setupd) State handler may handle the EXIT event for state teardown/cleanupe) State handler may handle the INIT for self transition to child statef) Self transition to child state MUST NOT be handled by ENTRY or EXIT eventg) Events ENTRY, EXIT and INIT do no need to return None for brevity*/// ParentHSM parent;// Child memberschar param1;char param2;
} CAMERA;CAMERA basic;
HSM_STATE CAMERA_StateOff;
HSM_STATE CAMERA_StateOn;
HSM_STATE CAMERA_StateOnShoot;
HSM_STATE CAMERA_StateOnDisp;
HSM_STATE CAMERA_StateOnDispPlay;
HSM_STATE CAMERA_StateOnDispMenu;

该函数注册了状态对应的回调处理函数,以"on"状态为例,使用HSM_STATE_Create函数对&CAMERA_StateOn句柄添加回调函数CAMERA_StateOnHndlr,只要处于"on"就会一直进入该函数进行事件的处理;在使用HSM_Create父状态,初始状态为&CAMERA_StateOff;

void CAMERA_Init(CAMERA *This, char *name)
{// Step 1: Create the HSM StatesHSM_STATE_Create(&CAMERA_StateOff, "Off", CAMERA_StateOffHndlr, NULL); //相机电源off 2HSM_STATE_Create(&CAMERA_StateOn, "On", CAMERA_StateOnHndlr, NULL);    //相机电源on 1HSM_STATE_Create(&CAMERA_StateOnShoot, "On.Shoot", CAMERA_StateOnShootHndlr, &CAMERA_StateOn);// 相机处于拍照状态 1-1HSM_STATE_Create(&CAMERA_StateOnDisp, "On.Disp", CAMERA_StateOnDispHndlr, &CAMERA_StateOn);   // 相机处于照片和菜单显示父状态 1-2 HSM_STATE_Create(&CAMERA_StateOnDispPlay, "On.Disp.Play", CAMERA_StateOnDispPlayHndlr, &CAMERA_StateOnDisp); //相机显示照片状态 1-2-1HSM_STATE_Create(&CAMERA_StateOnDispMenu, "On.Disp.Menu", CAMERA_StateOnDispMenuHndlr, &CAMERA_StateOnDisp); //相机显示菜单状态 1-2-2// Step 2: Initiailize the HSM and starting stateHSM_Create((HSM *)This, name, &CAMERA_StateOff);// Step 3: [Optional] Enable HSM debugHSM_SET_PREFIX((HSM *)This, "[DBG] ");HSM_SET_DEBUG((HSM *)This, HSM_SHOW_ALL);// Step 4: CAMERA member initializationThis->param1 = 0;This->param2 = 1;
}

以上六个状态的回调函数,执行代码如下

HSM_EVENT CAMERA_StateOffHndlr(HSM *This, HSM_EVENT event, void *param)
{if (event == HSME_ENTRY){printf("\tEnter Low Power Mode\n");}else if (event == HSME_EXIT){printf("\tExit Low Power Mode\n");}else if (event == HSME_PWR){HSM_Tran(This, &CAMERA_StateOn, 0, NULL);return 0;}return event;
}HSM_EVENT CAMERA_StateOnHndlr(HSM *This, HSM_EVENT event, void *param)
{if (event == HSME_ENTRY){printf ("\tOpen Lens\n");}else if (event == HSME_EXIT){printf ("\tClose Lens\n");}else if (event == HSME_INIT){HSM_Tran(This, &CAMERA_StateOnShoot, 0, NULL);}else if (event == HSME_PWR){HSM_Tran(This, &CAMERA_StateOff, 0, NULL);return 0;}else if (event == HSME_LOWBATT){printf("\tBeep low battery warning\n");return 0;}return event;
}HSM_EVENT CAMERA_StateOnShootHndlr(HSM *This, HSM_EVENT event, void *param)
{if (event == HSME_ENTRY){printf("\tEnable Sensor\n");}else if (event == HSME_EXIT){printf("\tDisable Sensor\n");}else if (event == HSME_RELEASE){printf("\tCLICK!, save photo\n");return 0;}else if (event == HSME_MODE){HSM_Tran(This, &CAMERA_StateOnDispPlay, 0, NULL);return 0;}return event;
}HSM_EVENT CAMERA_StateOnDispHndlr(HSM *This, HSM_EVENT event, void *param)
{if (event == HSME_ENTRY){printf("\tTurn on LCD\n");}else if (event == HSME_EXIT){printf("\tTurn off LCD\n");}return event;
}HSM_EVENT CAMERA_StateOnDispPlayHndlr(HSM *This, HSM_EVENT event, void *param)
{if (event == HSME_ENTRY){printf("\tDisplay Pictures\n");}else if (event == HSME_MODE){HSM_Tran(This, &CAMERA_StateOnDispMenu, 0, NULL);return 0;}return event;
}HSM_EVENT CAMERA_StateOnDispMenuHndlr(HSM *This, HSM_EVENT event, void *param)
{if (event == HSME_ENTRY){printf("\tDisplay Menu\n");}else if (event == HSME_MODE){HSM_Tran(This, &CAMERA_StateOnShoot, 0, NULL);return 0;}return event;
}

下面开始介绍程序主函数,执行步骤如注释

void main(void)
{// 1-Instantiate CameraCAMERA_Init(&basic, "Canon");// 2-Turn on the PowerCAMERA_Run(&basic, HSME_PWR, 0);// 3-Take a pictureCAMERA_Run(&basic, HSME_RELEASE, 0);// 4-Take another pictureCAMERA_Run(&basic, HSME_RELEASE, 0);// 5-Playback the photoCAMERA_Run(&basic, HSME_MODE, 0);// 6-Oops, pushed the release button by accidentCAMERA_Run(&basic, HSME_RELEASE, 0);// 7-Go to menu settingsCAMERA_Run(&basic, HSME_MODE, 0);// 8-Uh oh, low batteryCAMERA_Run(&basic, HSME_LOWBATT, 0);// 9-Time to turn it offCAMERA_Run(&basic, HSME_PWR, 0);
}

三、编译运行验证

查看源码文件

编译源码

运行代码

步骤1:处于低电量关机模式。初始化一个相机HSM实例为Canon,默认进入Canon[off]状态。

步骤2:等待拍照,打开相机电源开关,打开传感器,。Canon[off](HSME_PWR)事件触发,最终进入Canon[on](INIT)状态,再进入Canon[on.shoot](INIT)状态。

步骤3:拍照按键触发,拍下一张照片。触发Canon[on.shoot](HSME_RELEASE)事件。

步骤4:拍照按键触发,拍下另一张照片。触发Canon[on.shoot](HSME_RELEASE)事件。

步骤5:屏幕查看照片,关闭镜头传感器,打开屏幕LCD,显示图片。Canon[on.shoot](HSME_MODE)事件触发,进入Canon[on.Dis.Play](HSME_MODE)事件。

步骤6:拍照按键触发,由于处于查看照片模式,不响应拍照事件。Canon[on.Dis.Play](HSME_RELEASE)事件触发,但是遍历Canon[on.shoot]的状态和父状态都找不到该事件,不做处理。

步骤7:屏幕切换到菜单模式。Canon[on.Dis.Play](HSME_MODE)触发,切换到Canon[on.Disp.Memu](INIT)。

步骤8:相机电池电量低,蜂鸣器报警。触发HSME_LOWBATT事件,Canon[on.Disp.Memu]没有该事件,遍历其父状态,在Canon[on](HSME_LOWBATT)触发。

步骤9:相机电源按键触发,屏幕LCD关闭,镜头传感器关闭,切换回关机模式。HSME_PWR事件触发,Canon[on.Disp.Memu]找不到该状态,遍历其父状态在Canon[on](HSME_PWR)触发关机。

四、总结

至此层次状态机-HSM应用解析到此结束,上一篇文章和本文章是紧密结合的,必须看懂前者才能看明白上述的相机工作例子。理解HSM的状态调度机制和事件调度机制非常重要,笔者总结能力有限,可能没办法很清晰的描述出来,但是建议读者使用笔将整个状态和事件关系列举出来,相信会有不一样的收获哦。后续估计会再写一篇关于HSM的文章,不过是在C++中使用HSM,本人觉得HSM更适合结合C++封装继承特性去使用。

GitHub源码链接:GitHub - howard-chan/HSM: Hierarchical State Machine

层次状态机-HSM应用解析相关推荐

  1. 层次状态机-HSM代码解析

    有限状态机在学习和工作中经常能够遇到,前面的文章也有使用到.但是对于层次状态机网上的学习资源却很少,导致一直不理解这个工作机制,后面偶然在GitHub看到一篇文章,深入学习后发现层次状态机太实用了,如 ...

  2. 有限状态机FSM详解(5)——层次状态机HSM

    [前言] 回顾前文,我们解决了添加新的状态需要改变原有代码的问题,使得我们在添加新状态是只需在客户端(即player类)中增加代码,而不需要更改状态机的任何代码. 以攻击为例,跳跃攻击.行走攻击是不一 ...

  3. Android系统自带的层次状态机StateMachine(Hierarchical State Machine)

    Android系统自带的层次状态机StateMachine(Hierarchical State Machine) Android在framework层自己实现一套层次状态机,总共有三个类:State ...

  4. 详解android framework中StateMachine(HSM层次状态机)的实现

    [转载文章出处:https://segmentfault.com/a/1190000020386485?utm_source=tag-newest 作者:emonn] [最近在看状态机相关的问题,看到 ...

  5. Android官方实现的层次状态机Hierarchical State Machine源代码

    Android官方内部的源代码中实现了一套层次状态机(Hierarchical State Machine),总共有三个代码文件:IState.java , State.java, StateMach ...

  6. 使用C++实现一套简单的状态机模型——原理解析

    在上一文中,我们介绍了该状态机模型的使用方法.通过例子,我们发现可以使用该模型快速构建满足基本业务需求的状态机.本文我们将解析该模型的基础代码,以便大家可以根据自己状态机特点进行修改.(转载请指明出于 ...

  7. 【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析

    作者 : 韩曙亮 转载请著名出处 :  http://blog.csdn.net/shulianghan/article/details/38487967 一. MediaPlayer 状态机 介绍 ...

  8. 层次状态机编程二:设计QM状态机的基本约定

    1.消息在头文件中定义为如下格式: enum GameSignals { /* signals used in the game / TIME_TICK_SIG = Q_USER_SIG, / pub ...

  9. java statemachine_StateMachine 状态机机制深入解析

    前言 Spring StateMachine 让状态机结构更加层次化,可以帮助开发者简化状态机的开发过程. 之前,我们使用二维数组实现状态机机制,现在,我们来用 Spring StateMachine ...

最新文章

  1. 初识java-循环结构(二):6
  2. 通过正则表达式分句提取中文内容
  3. linux运维相关操作(centos/Ubuntu)
  4. pytorch torch.nn.TransformerEncoder
  5. C# Winform控件对透明图片重叠时导致图片不透明的解决方法
  6. 蓝牙设备一键切换工具ToothFairy for Mac中文
  7. Java代码:调用外部接口(使用Json格式传递参数)的方法
  8. 线性回归中的梯度爆炸
  9. ai人工智能图片修复_潜在客户追踪已中断,以及如何使用AI和自动化进行修复...
  10. 宝塔php7.1安装ioncube,如何使用宝塔安装ionCube扩展
  11. CSR8811A12-ICXR-R蓝牙芯片
  12. Keil 保护视力背景颜色设置
  13. 让coreseek支持拼音检索
  14. 纯手工html+css实现静态游戏网首页(免费拿源码)
  15. 百度开放大数据平台接口,传统企业看到了新曙光。
  16. Android 原生分享图片文字到微信
  17. Java8 jvm参数
  18. electron解决下载慢(亲测有效)
  19. Java闲杂笔记摘抄
  20. php根据日期判断星座if函数,js根据日期判断星座的代码

热门文章

  1. CPU、内存、缓存的关系
  2. 介绍一款数据库管理软件
  3. 多个html文件转换为excel,如何Excel批量转为Html或者Html转换成Excel
  4. ImageMagick将多张图片拼接成一张图片_爱剪辑如何把图片制作成视频
  5. 声源定位系统设计(一)——MVDR波束形成算法
  6. 【Python代码】文件查重(01)-简易版
  7. 数组的方法-push(),pop(),unshift(),shift()
  8. Java中的魔法值介绍及解决办法
  9. Pandas详解十之Dropna滤除缺失数据
  10. 匿名内部类的格式和理解