简介
generic模型,就是sig mesh协议里面规定的一套通用功能模型,各个厂家只要按照协议去设计设备功能,设备之间即可兼容使用!
下面就用元素0x0106里面的“通用开关模型(generic_onoff_model)”来举例,了解并记录SDK里面,具体是如何应用generic模型的!
订阅、发布模式:
单播模式:
SDK代码参考
以下代码是一些代码片段,需要了解完整内容的话,可以在工程里面进行全局搜索!
只举例发布、订阅模式
客户端(gateway节点):
初始化
if (API_SUCCESS == retval)
{
/* Register Configuration model client */
retval = UI_register_config_model_client(element_handle);
}
if (API_SUCCESS == retval)
{
/* Register Generic OnOff model client */
retval = UI_register_generic_onoff_model_client(element_handle);
}
#ifdef USE_VENDORMODEL
if (API_SUCCESS == retval)
{
/* Register Vendor Defined model server */
retval = UI_register_vendor_defined_model_client(element_handle);
}
#endif
UI_config_client_appkey_binding(0,0,UI_appkey);//重点
printf("0x%08X 0x%08X 0x%02X\n",ms_iv_index.iv_index,ms_iv_index.iv_expire_time,ms_iv_index.iv_update_state);
UI_prov_data.uaddr = 0x0001;
//Get network key
retval = MS_access_cm_get_netkey_at_offset(0,0,UI_prov_data.netkey);
if(retval == ACCESS_NO_MATCH) //if can't find netkey,generate it
{
UI_netkey_generate(UI_prov_data.netkey);
}
//Get key refresh state
MS_access_cm_get_key_refresh_phase(0,&key_refresh_state);
key_refresh_state = (MS_ACCESS_KEY_REFRESH_PHASE_2 == key_refresh_state) ? 0x01 : 0x00;
UI_prov_data.ivindex = ms_iv_index.iv_index;
UI_prov_data.flags = ((ms_iv_index.iv_update_state & 0x01) << 1) | key_refresh_state;
retval = UI_set_provision_data(UI_prov_data.uaddr);
/* Set the Publish address for onoff and vendor model Client */
UI_prov_data.uaddr = 0xCFFF;//重点
UI_set_publish_address(UI_prov_data.uaddr, UI_generic_onoff_client_model_handle,MS_FALSE);//重点
UI_set_publish_address(UI_prov_data.uaddr, UI_vendor_defined_client_model_handle,MS_FALSE);
发送“generic_onoff_set”命令
void UI_generic_onoff_set(UCHAR state)
{
API_RESULT retval;
MS_GENERIC_ONOFF_SET_STRUCT param;
CONSOLE_OUT
("Send Generic Onoff Set\n");
param.onoff = state;
param.tid = 0;
param.optional_fields_present = 0x00;
retval = MS_generic_onoff_set(¶m);//重点
CONSOLE_OUT
("Retval - 0x%04X\n", retval);
}
#define MS_generic_onoff_set(param) \
MS_generic_onoff_client_send_reliable_pdu \
(\
MS_ACCESS_GENERIC_ONOFF_SET_OPCODE,\//重点
param,\
MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE\
)
处理generic_onoff回调
API_RESULT UI_generic_onoff_client_cb
(
/* IN */ MS_ACCESS_MODEL_HANDLE* handle,
/* IN */ UINT32 opcode,
/* IN */ UCHAR* data_param,
/* IN */ UINT16 data_len
)
{
API_RESULT retval;
retval = API_SUCCESS;
CONSOLE_OUT (
"[GENERIC_ONOFF_CLIENT] Callback. Opcode 0x%04X\n", opcode);
appl_dump_bytes(data_param, data_len);
switch(opcode)
{
case MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE://重点
{
CONSOLE_OUT(
"MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE\n");
}
break;
}
return retval;
}
服务端(light节点):
初始化
if (API_SUCCESS == retval)
{
/* Register Generic OnOff model server */
retval = UI_register_generic_onoff_model_server(element_handle);
}
绑定appkey
API_RESULT UI_sample_binding_app_key(void)
{
MS_APPKEY_HANDLE handle;
UINT8* key;
UINT8 aid;
DECL_CONST UINT8 t_key[16] = {0};
API_RESULT retval;
CONSOLE_OUT("Fetching App Key for Handle 0x0000\n");
handle = 0x0000;
retval = MS_access_cm_get_app_key
(
handle,
&key,
&aid
);
/* Check Retval. Print App Key */
if (API_SUCCESS == retval)
{
CONSOLE_OUT("App Key[0x%02X]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
handle, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
if (0 == EM_mem_cmp(key, t_key, 16))
{
/* NO AppKey Bound */
retval = API_FAILURE;
}
else
{
/* Found a Valid App Key */
/* Keeping the retval as API_SUCCESS */
retval=MS_access_bind_model_app(UI_generic_onoff_server_model_handle, handle);//重点
#ifdef USE_LIGHTNESS
retval=MS_access_bind_model_app(UI_light_lightness_server_model_handle, handle);
CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_light_lightness_server_model_handle,handle);
#endif
#ifdef USE_CTL
retval=MS_access_bind_model_app(UI_light_ctl_server_model_handle, handle);
CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_light_ctl_server_model_handle,handle);
#endif
#ifdef USE_HSL
retval=MS_access_bind_model_app(UI_light_hsl_server_model_handle, handle);
CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_light_hsl_server_model_handle,handle);
#endif
#ifdef USE_SCENE
retval=MS_access_bind_model_app(UI_scene_server_model_handle, handle);
CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_scene_server_model_handle,handle);
#endif
#ifdef USE_VENDORMODEL
retval=MS_access_bind_model_app(UI_vendor_defined_server_model_handle, handle);
CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_vendor_defined_server_model_handle,handle);
#endif
}
}
#ifdef EASY_BOUNDING
//Provision ok,stop provision/config timeout handler by hq
CONSOLE_OUT("Stop timer\n");
EM_stop_timer(&procfg_timer_handle);
blebrr_prov_started = MS_FALSE;
#endif
return retval;
}
订阅0xCFFF
vm_subscriptiong_add (0xCFFF);//重点
void vm_subscriptiong_add (MS_NET_ADDR addr)
{
CONSOLE_OUT("vm_subscriptiong_add:%x\n",addr);
MS_ACCESS_ADDRESS sub_addr;
sub_addr.use_label=0;
sub_addr.addr=addr;
MS_access_ps_store_disable(MS_TRUE);
MS_access_cm_add_model_subscription(UI_generic_onoff_server_model_handle,&sub_addr);
#ifdef USE_LIGHTNESS
MS_access_cm_add_model_subscription(UI_light_lightness_server_model_handle,&sub_addr);
#endif
#ifdef USE_CTL
MS_access_cm_add_model_subscription(UI_light_ctl_server_model_handle,&sub_addr);
MS_access_cm_add_model_subscription(UI_light_ctl_setup_server_model_handle,&sub_addr);
#endif
#ifdef USE_HSL
MS_access_cm_add_model_subscription(UI_light_hsl_server_model_handle,&sub_addr);
MS_access_cm_add_model_subscription(UI_light_hsl_setup_server_model_handle,&sub_addr);
#endif
#ifdef USE_SCENE
MS_access_cm_add_model_subscription(UI_scene_server_model_handle,&sub_addr);
MS_access_cm_add_model_subscription(UI_scene_setup_server_model_handle,&sub_addr);
#endif
MS_access_ps_store_disable(MS_FALSE);
MS_access_ps_store_all_record();
}
回调处理
static API_RESULT UI_generic_onoff_server_cb
(
/* IN */ MS_ACCESS_MODEL_REQ_MSG_CONTEXT* ctx,
/* IN */ MS_ACCESS_MODEL_REQ_MSG_RAW* msg_raw,
/* IN */ MS_ACCESS_MODEL_REQ_MSG_T* req_type,
/* IN */ MS_ACCESS_MODEL_STATE_PARAMS* state_params,
/* IN */ MS_ACCESS_MODEL_EXT_PARAMS* ext_params
)
{
MS_STATE_GENERIC_ONOFF_STRUCT param;
MS_ACCESS_MODEL_STATE_PARAMS current_state_params;
API_RESULT retval;
retval = API_SUCCESS;
/* Check message type */
if (MS_ACCESS_MODEL_REQ_MSG_T_GET == req_type->type)
{
CONSOLE_OUT("[GENERIC_ONOFF] GET Request.\n");
UI_generic_onoff_model_state_get(state_params->state_type, 0, ¶m, 0);
current_state_params.state_type = state_params->state_type;
current_state_params.state = ¶m;
/* Using same as target state and remaining time as 0 */
}
else if (MS_ACCESS_MODEL_REQ_MSG_T_SET == req_type->type)//重点
{
CONSOLE_OUT("[GENERIC_ONOFF] SET Request.\n");
retval = UI_generic_onoff_model_state_set(state_params->state_type, 0, (MS_STATE_GENERIC_ONOFF_STRUCT*)state_params->state, 0);//重点
current_state_params.state_type = state_params->state_type;
current_state_params.state = (MS_STATE_GENERIC_ONOFF_STRUCT*)state_params->state;
}
/* See if to be acknowledged */
if (0x01 == req_type->to_be_acked)
{
CONSOLE_OUT("[GENERIC_ONOFF] Sending Response.\n");
/* Parameters: Request Context, Current State, Target State (NULL: to be ignored), Remaining Time (0: to be ignored), Additional Parameters (NULL: to be ignored) */
retval = MS_generic_onoff_server_state_update(ctx, ¤t_state_params, NULL, 0, NULL);
}
return retval;
}
static API_RESULT UI_generic_onoff_model_state_set(UINT16 state_t, UINT16 state_inst, void* param, UINT8 direction)
{
API_RESULT retval;
UCHAR proxy_state;
retval = API_SUCCESS;
switch (state_t)
{
case MS_STATE_GENERIC_ONOFF_T:
{
MS_STATE_GENERIC_ONOFF_STRUCT* param_p;
param_p = (MS_STATE_GENERIC_ONOFF_STRUCT*)param;
/* Instantaneous Change */
UI_generic_onoff.onoff = param_p->onoff;
*param_p = UI_generic_onoff;
CONSOLE_OUT("[state] current: 0x%02X\n", UI_generic_onoff.onoff);
CONSOLE_OUT("[state] target: 0x%02X\n", UI_generic_onoff.target_onoff);
CONSOLE_OUT("[state] remaining_time: 0x%02X\n", UI_generic_onoff.transition_time);
proxy_state = UI_proxy_state_get();
if(proxy_state==MS_PROXY_CONNECTED)
{
EM_start_timer (&proxy_dly_thandle, (EM_TIMEOUT_MILLISEC | 100), proxy_dly_generic_onoff, NULL, 0);
}
else
{
generic_onoff_set_pl(param_p->onoff);//重点
}
/* Ignoring Instance and direction right now */
}
break;
default:
break;
}
return retval;
}