本地定时功能开发实践

更新时间:2019-06-12 17:22:13

1. 概述

本文提供了一个插座本地定时功能的开发案例,开发者可以参考本文,实现任意设备的本地定时功能。
“本地定时”是相对”云端定时”而言的,是指当设备离线时,也能自动执行定时任务。要实现本地定时的效果,设备端和APP端可以按照本文推荐的方式进行实现。
设备端:按照平台标准数据格式,实现定时任务的增删改。
APP端:可以直接使用平台提供的“设备界面”插件,或“本地定时”APP插件,无需额外开发APP页面。

2. 准备工作

控制台-产品-人机交互-自动化和定时:


本地定时一列,勾选需要本地定时的功能,如主灯开关:


在功能参数中,可设置本地定时的最大条数(和设备端的存储、性能有关),消费者可能设置多条定时任务:

完成这个步骤,点击保存后,平台会在 功能定义 中,自动插入一个标准功能“本地定时”(LocalTimer),为JSON数组(JSON Array)格式,其中数组中的每个JSON都是一个定时任务,比如“每天6:00关闭空调”,并支持多个定时任务。
参数如下:
必选参数1:定时时间-Timer-(cron类型)字符串
必选参数2:启用-Enable-布尔
必选参数3:可执行-IsValid-布尔
可选参数4:定时动作-Targets-字符串
可选参数5:时区-TimezoneOffset-整数(-43200到50400,步进1)

参数名称 标识符 参数类型 参数描述
标准参数 定时时间 Timer 字符串 必选,不可删除,用于表示定时时间,使用corn格式
标准参数 启用 Enable 布尔 必选,不可删除,表明是否启用
标准参数 可执行 IsValid 布尔 必选,不可删除,表明这条定时任务是否需要展示给用户看(因为设备端会将所有定时的数据传给app端)
自定义参数 定时动作 Targets 字符串 可选,用来表明当次设置的定时任务的具体动作有哪些。如果没有添加Targets属性,那么用户在设置定时的时候必须把全部动作设置才能保存,添加Targets属性才可以设置任意数量的动作(最大值:2048,可以为空)
自定义参数 时差 TimezoneOffset 整数 可选,用来表示本地事件与UTC时间的差值,单位秒,取值范围为(-43200到50400,步进1)
自定义参数 如插孔开关1 SocketSwitch_1 布尔 定时的功能,必须和功能定义中的功能保持一致,如针对开关进行定时,此处设为 插孔开关1 - SocketSwitch_1 - 布尔型。
自定义参数 如插孔开关2 SocketSwitch_2 布尔 每个定时任务中,支持多个功能
自定义参数 不限数量


3. 设备开发和调试

  • 在云端控制台上定义好了LocalTimer的属性之后,设备端可以接收从云端下来的property set消息,从而获取定时任务的具体信息。

  • 获取aos1.3.4版本sdk,demo位于aos/example/linkkitapp/linkkit_example_solo.c

  • 设备收到定时任务的属性时,会进到user_property_set_event_handler中,如下图所示:

    /*
    * the handler of property changed
    * alink method: thing.service.property.set
    */
    static int user_property_set_event_handler(const int devid, const char *request, const int request_len)
    {
      int res = 0;
      user_example_ctx_t *user_example_ctx = user_example_get_ctx();
    
      EXAMPLE_TRACE("Property Set Received, Devid: %d, Request: %s", devid, request);
    
      cJSON * data_JSON = cJSON_Parse(request);
      if(cJSON_GetObjectItem(data_JSON,"LocalTimer") != NULL)
      {
          cJSON *localtime_arr = cJSON_GetObjectItem(data_JSON,"LocalTimer");
          uint32_t arrysize = cJSON_GetArraySize(localtime_arr);
          cJSON *arr_item = localtime_arr->child;
          for(int i = 0;i < arrysize; i++)
              handle_localtime(arr_item, i);
      }
    
      res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY,(unsigned char *)request, request_len);
      EXAMPLE_TRACE("Post Property Message ID: %d", res);
      cJSON_Delete(data_JSON);
    
      return 0;
    }
    
  • TSL示例

{
"LocalTimer": [{
"LightSwitch": 1,
"ColorTemperature": 2000,
"Timer": "5 4 1,2,3",
"TimezoneOffset": 43200,
"Brightness": 0,
"Enable": 1,
"Targets": "LightSwitch",
"WorkMode": 0,
"IsValid": 1
}, {
"LightSwitch": 0,
"ColorTemperature": 2000,
"Timer": "",
"TimezoneOffset": 43200,
"Brightness": 0,
"Enable": 0,
"Targets": "",
"WorkMode": 0,
"IsValid": 0
}, {
"LightSwitch": 0,
"ColorTemperature": 2000,
"Timer": "",
"TimezoneOffset": 43200,
"Brightness": 0,
"Enable": 0,
"Targets": "",
"WorkMode": 0,
"IsValid": 0
}, {
"LightSwitch": 0,
"ColorTemperature": 2000,
"Timer": "",
"TimezoneOffset": 43200,
"Brightness": 0,
"Enable": 0,
"Targets": "",
"WorkMode": 0,
"IsValid": 0
}, {
"LightSwitch": 0,
"ColorTemperature": 2000,
"Timer": "",
"TimezoneOffset": 43200,
"Brightness": 0,
"Enable": 0,
"Targets": "",
"WorkMode": 0,
"IsValid": 0
}]
}

  • 如上是设备端接收到的一个本地定时的示例,采用数组格式描叙,数组中共5条定时记录,其中"IsValid"定义该条是否有效,定时的逻辑处理可以参考如上实现,每一条详细处理,需要客户自己来实现。

4. 集成APP插件

本地定时插件的代码为:link://router/localTimer,可以将该代码复制到您的App代码中,调用该插件。
如何开通:
在living.aliyun.com网站里您的项目中,找到自有品牌APP模块,进入后,将会看到App界面这个导航。点进去后,在页面中可以看到目前所有的插件列表,点击每一个插件旁边的“生成代码”按钮,即可开通该插件在您的自有App中的调用权限。

5. 新版本地定时兼容问题

5.1 插件端

1.当前本地定时LocalTimer里如果添加了多个动作,那必须设置完所有动作,才能正常保存。
2.新版本地定时插件解决了该问题,当检测出功能定义里添加了Targets,设置任意(大于零)个动作就能正常保存,如果没有Targets则走以前的旧逻辑。(如 1 所述)

5.2 设备端

设备端在收到LocalTimer后,看Targets属性里的动作有哪些,根据这些动作来设定自己的定时任务。没有Targets或者Targets为空字符串,就执行LocalTimer里添加的全部动作(这些动作不是指Timer,Enable,IsValid这几个属性)。

results matching ""

    No results matching ""