电池服务 Battery Servcie

小技巧

如果图片看不清楚。你可以 在图片上点击鼠标右键 –> 在新标签页中打开图片 ,然后你可以放大、缩小、移动图片。

battery_service.h , battery_service.c , voltage_monitor.h , voltage_monitor.c , battery_example.c

概述

电池服务 Battery Service,是 外设服务 Periph Service 的子类。

  • 前者完全是按后者的框架实现的。
  • 后者实现时基本上完全覆盖(或继承)前者的方法。
  • 除了创建 Create 与特殊 API 要调用外设子服务的API;一般都调用音频服务的 API。

类图

../_images/d34db5707c8515d9d63604f440727e17ed38af9c70f5234854390830598566bb.svg

我们用类图的形式,描述电池服务 Battery Service 的实现(实际上代码是用 C 语言实现的):

Battery_Servcie 类

  • 结构体 battery_service_t ,是内部私有数据。

    • .serv_q: API 等向内部任务 battery_task 发送消息的消息队列。
    • .sync_events: battery_task 向 API 等发送事件的 Event Group 。
    • .vol_monitor: 也就是 class Voltage_Monitor 。 电池服务内部的另一个用于监测电池电压的定时器任务。见下文 Voltage_Monitor 类
  • private method 部分,是 Battery Servcie 内部函数。这些函数的实现大部分都很简单:

    • battery_task(): 内部任务。
    • _battery_start(): 启动 Battery Service。
    • _battery_stop(): 停止 Battery Service。
    • _battery_destroy(): 销毁 Battery Service。
  • public method 部分,是 DuerOS Servcie 的提供的 API 函数。这些函数的实现大部分都很简单:

    • battery_service_create() 的实现略微复杂一点,看这里 API
    • battery_service_vol_report_switch() 开关电量上报。
    • battery_service_set_vol_report_freq() 设置电量上报频率。

Voltage_Monitor 类

  • 结构体 vol_monitor_ctx_t ,是内部私有数据。

    • .mutex: 锁,用于保护结构体内的其它字段,防止 API 与 定时器同时访问/修改这些变量。

    • .config: 一些配置,如下所示:

      /**
      * @brief Battery adc configure
      */
      typedef struct {
          bool (*init)(void *);   /*!< Voltage read init */
          bool (*deinit)(void *); /*!< Voltage read deinit */
          int (*vol_get)(void *); /*!< Voltage read interface */
          void *user_data;        /*!< Parameters for callbacks */
          int read_freq;          /*!< Voltage read frequency, unit: s*/
          int report_freq;        /*!< Voltage report frequency, voltage will be report with a interval calculate by (`read_freq` * `report_freq`) */
          int vol_full_threshold; /*!< Voltage threshold to report, unit: mV */
          int vol_low_threshold;  /*!< Voltage threshold to report, unit: mV */
      } vol_monitor_param_t;
      
    • .event_cb: 事件回调,用于与 battery_task() 通信 。

    • .user_ctx: 事件回调上下文参数 。

    • .check_timer: 定时器 。

  • private method 部分,是 Voltage Monitor 内部函数。

    • vol_check_timer_hdlr(): 定时器任务。
  • public method 部分,是 Voltage Monitor 的提供的 API 函数。这些函数的实现大部分都很简单:

    • vol_monitor_create(vol_monitor_param_t *config) 创建电压监测功能 。
    • vol_monitor_destroy() 销毁电压监测能。
    • vol_monitor_set_event_cb() 设置电压监测事件回调。
    • vol_monitor_start_freq_report() 下始电压监测周期上报。
    • vol_monitor_stop_freq_report() 停止电压监测周期上报。
    • vol_monitor_set_report_freq() 设置电压监测上报频率。

序列图

../_images/0897859b0c9acc6fc710f7b09bb036af08eac2357b061dae7798a37b428ce340.svg

对像说明:

  • battery_example.c: 某个应用程序
  • battery_service.c: 电池服务
  • battery_task(): 电池服务的内部任务
  • voltage_monitor.c:电量监测
  • vol_check_timer_hdlr():电量监测内部的定时器

流程说明:

  1. 应用程序 battery_example.c 调用 voltage_monitor.c 电量检测 vol_monitor_create()。同时传入与电量检测相关的三个函数。
  2. voltage_monitor.c 调用初始函数 .config->init()
  3. 创建锁。
  4. 创建定时器 .check_timer 。该定时器超时后会调用 vol_check_timer_hdlr()
  5. 启动定时器 .check_timer 。该定时器超时每 .config->read_freq 会超时一次。
  1. 应用程序 battery_example.c 调用 Battery Service 电池服务 battery_service_create()
  2. 创建内部通信的消息队列。
  3. 创建内部通信的事件组。
  4. battery_service.c 调用 periph_service_create(), 并会将 .service_destroy.service_start , .service_stop , 等回调函数作为参数的字段传入。 同时也会将自已的地址,作为 .user_data 参数字段传入。 因 Battery Service 需要创建内部任务,也会将内部任务函数 battery_task() 作为 .task_func 参数字段传入。
  5. periph_service.c 将上述回调函数和 .user_data 保存下来。因为 .task_func 不为空(实际上是 .task_stack > 0),故同时创建内部任务。
  6. battery_service.c 调用 periph_service_set_callback({.evt_cb}) 注册事件回调函数。
  1. battery_example.c 调用 periph_service_start() 开始电池服务。
  2. .service_start 不为空,被执行( 实际上是执行 _battery_start() )。
  3. battery_service.c 发送消息 BATTERY_SERVICE_START 给内部任务。
  4. 内部任务 battery_task() 调用 vol_monitor_set_event_cb(battery_vol_monitor_cb) 设置电量监测的事件回调函数。battery_vol_monitor_cb() 就是该事件回调函数。
  5. voltage_monitor.c 保存该事件回调函数。
  1. battery_example.c 调用 battery_service_vol_report_switch(true) 开始电量上报。
  2. battery_service.c 发送消息 BATTERY_VOL_REPORT_START 给内部任务。
  3. 内部任务 battery_task() 调用 vol_monitor_start_freq_report() 开始周期上报。
  4. voltage_monitor.c 保存新的电量上报周期。
  1. battery_example.c 调用 battery_service_set_vol_report_freq(freq) 修改电量上报周期。
  2. battery_service.c 发送消息 BATTERY_VOL_SET_REPORT_FREQ 给内部任务。
  3. 内部任务 battery_task() 调用 vvol_monitor_set_report_freq(freq) 修改电量上报周期。
  4. voltage_monitor.c 保存新的电量上报周期。
  1. 定时器周期超时。

  2. 定时器调用 .event_cb(VOL_MONITOR_EVENT_FREQ_REPORT) (实际上是调用 battery_vol_monitor_cb() ) 周期上报电量。

  3. battery_service.c 向内部任务 battery_task 发送消息 BATTERY_VOL_REPORT_FREQ ,携带电量信息 。

  4. 内部任务 battery_task 调用 periph_service_callback(BAT_SERV_EVENT_VOL_REPOR).

  5. periph_service.c 调用应用的事件回调函数 battery_service_cb()

    45~48, 49~52 的流程与 40~44 完全类似,只不过是携带的信息不同: 电量低或电量满。

  1. battery_example.c 调用 battery_service_vol_report_switch(false) 开始电量上报。
  2. battery_service.c 发送消息 BATTERY_VOL_REPORT_STOP 给内部任务。
  3. 内部任务 battery_task() 调用 vol_monitor_stop_freq_report() 开始周期上报。
  4. voltage_monitor.c 保存新的电量上报周期。
  1. 应用调用(实际上无些调用) periph_service_stop() 停止电池服务。
  2. .service_stop 不为空,被执行( 实际上是执行 _battery_stop() )。
  3. battery_service.c 发送消息 BATTERY_SERVICE_STOP 给内部任务。
  4. 内部任务 battery_task() 调用 vol_monitor_set_event_cb(NULL) 清除电量监测的事件回调函数。
  5. voltage_monitor.c 清除该事件回调函数。
  1. battery_example.c 调用 periph_service_destroy(), 销毁 Battery Service。
  2. .service_destroy 不为空, 其被 periph_service.c 调用( 实际上是执行 _battery_destory() )。
  3. battery_server.c 发送 BATTERY_SERVICE_DESTROY 消息给内部任务。
  4. 内部任务 battery_task() 调用 vol_monitor_set_event_cb(NULL) 清除电量监测的事件回调函数。
  5. voltage_monitor.c 清除该事件回调函数。。
  6. battery_service.c 中止内部任务 battery_task() 。
  7. battery_service.c 清除消息队列。
  8. battery_service.c 清除事件组。
  1. 应用程序 battery_example.c 调用 voltage_monitor.c 电量检测 vol_monitor_destory()
  2. voltage_monitor.c 停止定时器 .check_timer
  3. voltage_monitor.c 销毁定时器 .check_timer
  4. voltage_monitor.c 调用反初始化函数 .config->deinit()
  5. voltage_monitor.c 删除锁 。

API

  • vol_monitor_create()

    ../_images/f3a067b1c1e6391620ca07043e86c3fa82900a4ef88a3e8d9a0d56942e8424ef.svg
  • battery_service_create()

    ../_images/13f8bd8284ec99478ebb9957bd6c174120382088ebd60d1bcadd955eb3c1330e.svg
  • periph_service_start()

    ../_images/a9bb5409cdb5c69f5194f3e7c3e5e53a47c3228029bfe8d92b2e8ba3840264b6.svg
  • battery_service_vol_report_switch(true)

    ../_images/f244f898886052be496cb9049356fe913a6dda734ce334e7c779a84b99c3a971.svg
  • battery_service_set_vol_report_freq()

    ../_images/5b289015ffdd4cb9c53488fd6ddbf98344f0f80681230d57467234300fae79e2.svg
  • battery_service_cb() (事件回调)

    ../_images/d3bfba21ba753e3575e24b7aa80ae0278da5f1a25afb6e87484453004acf9c39.svg
  • battery_service_vol_report_switch(false)

    ../_images/994050f28c1ffc7641f1951467bec5e3bde714bac9b786b2c6740eafcee63027.svg
  • periph_service_stop()

    ../_images/3a59ffd4b00c79be7443d25cbe0092e56a861e60a1562d6bf86d5f79d36f8211.svg
  • periph_service_destroy()

    ../_images/66b194f7f9cbb5e89f663b87452e30998a96c204c09b184ca2f40895f9e6c511.svg
  • vol_monitor_destroy()

    ../_images/313bde713d34771c5ea549735699952b6439473f09824409ba6b1dfafa23a0c5.svg