## 数据模板业务逻辑开发 数据模板示例data_template_sample.c已实现数据、事件收发及响应的通用处理框架。可以基于此示例开发业务逻辑,上下行业务逻辑添加的入口函数分别为 deal_up_stream_user_logic 、deal_down_stream_user_logic。可以参考智能灯的场景示例 light_data_template_sample.c 添加业务处理逻辑。 - 属性 属性即对设备能力的描述,譬如智能灯,通过 `开关`、`颜色`、`亮度`三个属性实现对智能灯的能力描述,通过对属性的修改即可实现对设备的控制。 - 事件 设备发生特定情况,譬如灯的开关状态发生了变化,上报事件。应用侧收到事件后按预设逻辑推送事件。 - 行为 控制设备执行特定的行为,并将执行的结果返回。行为与属性的区别,概念上行为是数据和方法的组合,行为有执行结果的返回。属性只有数据,修改属性后设备侧是否执行成功很难在属性本身体现。 数据模板示例data_template_sample.c已实现属性、事件、动作的通用处理框架。可以基于此示例开发业务逻辑,上下行业务逻辑添加的入口函数分别为 deal_up_stream_user_logic 、deal_down_stream_user_logic。可以参考智能灯的场景示例 light_data_template_sample.c 添加业务处理逻辑。 ### 下行业务逻辑实现 - 服务端下行的数据,SDK已按数据模板协议完成了json数据的解析。ProductDataDefine是第三步中根据在平台定义的产品数据模板生成的模板结构体,由定义的各属性构成成员变量。入参pData所指向的属性数据,从服务端下行数据中,SDK已经按数据模板协议完成了属性数据的解析,用户在下行逻辑处理的函数里边可以直接使用解析好的数据添加业务逻辑即可。 - 用户根据数据模板数据pData进行相应的业务逻辑处理。 ``` /*用户需要实现的下行数据的业务逻辑,pData除字符串变量已实现用户定义的所有其他变量值解析赋值,待用户实现业务逻辑*/ static void deal_down_stream_user_logic(void *client, ProductDataDefine * pData) { Log_d("someting about your own product logic wait to be done"); } ``` - 示例用法: ``` /*智能灯属性数据模板*/ typedef struct _ProductDataDefine { TYPE_DEF_TEMPLATE_BOOL m_light_switch; TYPE_DEF_TEMPLATE_ENUM m_color; TYPE_DEF_TEMPLATE_INT m_brightness; TYPE_DEF_TEMPLATE_STRING m_name[MAX_STR_NAME_LEN+1]; } ProductDataDefine; /*示例灯光控制处理逻辑*/ static void deal_down_stream_user_logic(void *client,ProductDataDefine *light) { int i; const char * ansi_color = NULL; const char * ansi_color_name = NULL; char brightness_bar[] = "||||||||||||||||||||"; int brightness_bar_len = strlen(brightness_bar); /*灯光颜色*/ switch(light->m_color) { case eCOLOR_RED: ansi_color = ANSI_COLOR_RED; ansi_color_name = " RED "; break; case eCOLOR_GREEN: ansi_color = ANSI_COLOR_GREEN; ansi_color_name = "GREEN"; break; case eCOLOR_BLUE: ansi_color = ANSI_COLOR_BLUE; ansi_color_name = " BLUE"; break; default: ansi_color = ANSI_COLOR_YELLOW; ansi_color_name = "UNKNOWN"; break; } /* 灯光亮度显示条 */ brightness_bar_len = (light->m_brightness >= 100)?brightness_bar_len:(int)((light->m_brightness * brightness_bar_len)/100); for (i = brightness_bar_len; i < strlen(brightness_bar); i++) { brightness_bar[i] = '-'; } if(light->m_light_switch){ /* 灯光开启式,按照控制参数展示 */ HAL_Printf( "%s[ lighting ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,\ ansi_color,ansi_color_name,brightness_bar,light->m_name); }else{ /* 灯光关闭展示 */ HAL_Printf( ANSI_COLOR_YELLOW"[ light is off ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,\ ansi_color_name,brightness_bar,light->m_name); } #ifdef EVENT_POST_ENABLED if(eCHANGED == sg_DataTemplate[0].state){ if(light->m_light_switch){ memset(sg_message, 0, MAX_EVENT_STR_MESSAGE_LEN); strcpy(sg_message,"light on"); sg_status = 1; }else{ memset(sg_message, 0, MAX_EVENT_STR_MESSAGE_LEN); strcpy(sg_message,"light off"); sg_status = 0; } IOT_Event_setFlag(client, FLAG_EVENT0);/*灯的开关状态发生变化时置位事件,在eventPostCheck中会将置位的事件上报*/ } #endif } ``` ### 上行业务逻辑实现 - SDK提供了属性、事件、行为的上行接口,用户可以按数据模板协议自行构造数据,然后调用接口上报相应数据。 1. 属性上报接口`IOT_Template_Report` 2. 事件上报接口`IOT_Post_Event` 3. 行为回复接口`IOT_ACTION_REPLY` 4. - 数据模板示例data_template_sample.c已提供了属性、事件、行为数据构造和上报的框架。 1. 对于属性上报,修改对应的属性参数,调用数据模板的属性状态设置的方法`set_propery_state`将属性置为已变化`eCHANGED`,用户在`deal_up_stream_user_logic`上行处理逻辑中,调用`find_wait_report_property`汇总需要上报的属性列表,框架会调用`IOT_Template_JSON_ConstructReportArray`根据属性列表构建上报数据并调用`IOT_Template_Report`实现属性上报。 2. 对于事件,在事件产生的地方,调用`IOT_Event_setFlag`置位相应事件,框架会调用`eventPostCheck`将置位的事件自动上报。 3. 对于行为,在注册的行为回调`OnActionCallback`中,添加业务逻辑执行对应的行为,根据行为执行结果,修改给行为的输出参数,调用`IOT_ACTION_REPLY`回复行为执行结果。 ``` /*用户根据业务修改属性值,然后设置属性状态为eCHANGED*/ static void _refresh_local_property(void) { //add your local property refresh logic } /*用户需要实现的上行数据的业务逻辑,此处仅供示例*/ static int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount) { int i, j; /*监测是否需要更新本地数据*/ _refresh_local_property(); /*将变化的属性更新到上报列表*/ for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) { if(eCHANGED == sg_DataTemplate[i].state) { pReportDataList[j++] = &(sg_DataTemplate[i].data_property); sg_DataTemplate[i].state = eNOCHANGE; } } *pCount = j; return (*pCount > 0)?QCLOUD_RET_SUCCESS:QCLOUD_ERR_FAILURE; } ```