本地定时功能开发实践
更新时间:2019-01-16 14:20:56
1. 概述
本文提供了一个插座本地定时功能的开发案例,开发者可以参考本文,实现任意设备的本地定时功能。
“本地定时”是相对”云端定时”而言的,是指当设备离线时,也能自动执行定时任务。要实现本地定时的效果,设备端和APP端可以按照本文推荐的方式进行实现。
设备端:按照平台标准数据格式,实现定时任务的增删改。
APP端:可以直接使用平台提供的“设备界面”插件,或“本地定时”APP插件,无需额外开发APP页面。
2. 准备工作
控制台中注册您的产品,详细参考 产品注册,本文以插座为例。在 功能定义 中,需要选择标准功能“本地定时”(LocalTimer),为JSON数组(JSON Array)格式,其中数组中的每个JSON都是一个定时任务,比如“每天6:00关闭空调”,并支持多个定时任务。
参数如下:
必选参数1:定时时间-Timer-(cron类型)字符串
必选参数2:启用-Enable-布尔
必选参数3:可执行-IsValid-布尔
可选参数4:定时动作-Targets-字符串
参数名称 | 标识符 | 参数类型 | 参数描述 | |
---|---|---|---|---|
标准参数 | 定时时间 | Timer | 字符串 | 必选,不可删除,用于表示定时时间,使用corn格式 |
标准参数 | 启用 | Enable | 布尔 | 必选,不可删除,表明是否启用 |
标准参数 | 可执行 | IsValid | 布尔 | 必选,不可删除,表明这条定时任务是否需要展示给用户看(因为设备端会将所有定时的数据传给app端) |
自定义参数 | 定时动作 | Targets | 字符串 | 可选,用来表明当次设置的定时任务的具体动作有哪些。如果没有添加Targets属性,那么用户在设置定时的时候必须把全部动作设置才能保存,添加Targets属性才可以设置任意数量的动作(最大值:2048,可以为空) |
自定义参数 | 如插孔开关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", "Brightness": 0, "Enable": 1, "Targets": "LightSwitch", "WorkMode": 0, "IsValid": 1
}, {
"LightSwitch": 0, "ColorTemperature": 2000, "Timer": "", "Brightness": 0, "Enable": 0, "Targets": "", "WorkMode": 0, "IsValid": 0
}, {
"LightSwitch": 0, "ColorTemperature": 2000, "Timer": "", "Brightness": 0, "Enable": 0, "Targets": "", "WorkMode": 0, "IsValid": 0
}, {
"LightSwitch": 0, "ColorTemperature": 2000, "Timer": "", "Brightness": 0, "Enable": 0, "Targets": "", "WorkMode": 0, "IsValid": 0
}, {
"LightSwitch": 0, "ColorTemperature": 2000, "Timer": "", "Brightness": 0, "Enable": 0, "Targets": "", "WorkMode": 0, "IsValid": 0
}]
}如上是设备端接收到的一个本地定时的示例,采用数组格式描叙,数组中共5条定时记录,其中"IsValid"定义该条是否有效,定时的逻辑处理可以参考如上实现,每一条详细处理,需要客户自己来实现。
4. 集成APP插件
本地定时插件的代码为:link://router/localTimer,可以将该代码复制到您的App代码中,调用该插件。
如何开通:
在living.aliyun.com网站里您的项目中,找到自有品牌APP模块,进入后,将会看到App界面这个导航。点进去后,在页面中可以看到目前所有的插件列表,点击每一个插件旁边的“生成代码”按钮,即可开通该插件在您的自有App中的调用权限。
新版本地定时兼容问题
插件端
1.当前本地定时LocalTimer里如果添加了多个动作,那必须设置完所有动作,才能正常保存。
2.新版本地定时插件解决了该问题,当检测出功能定义里添加了Targets,设置任意(大于零)个动作就能正常保存,如果没有Targets则走以前的旧逻辑。(如 1 所述)
2.设备端
设备端在收到LocalTimer后,看Targets属性里的动作有哪些,根据这些动作来设定自己的定时任务。没有Targets或者Targets为空字符串,就执行LocalTimer里添加的全部动作(这些动作不是指Timer,Enable,IsValid这几个属性)。