简介

generic模型,就是sig mesh协议里面规定的一套通用功能模型,各个厂家只要按照协议去设计设备功能,设备之间即可兼容使用!
下面就用元素0x0106里面的“通用开关模型(generic_onoff_model)”来举例,了解并记录SDK里面,具体是如何应用generic模型的!

订阅、发布模式:

image.png

单播模式:

image.png

SDK代码参考

以下代码是一些代码片段,需要了解完整内容的话,可以在工程里面进行全局搜索!
只举例发布、订阅模式

客户端(gateway节点):
初始化

  1. if (API_SUCCESS == retval)
  2. {
  3. /* Register Configuration model client */
  4. retval = UI_register_config_model_client(element_handle);
  5. }
  6. if (API_SUCCESS == retval)
  7. {
  8. /* Register Generic OnOff model client */
  9. retval = UI_register_generic_onoff_model_client(element_handle);
  10. }
  11. #ifdef USE_VENDORMODEL
  12. if (API_SUCCESS == retval)
  13. {
  14. /* Register Vendor Defined model server */
  15. retval = UI_register_vendor_defined_model_client(element_handle);
  16. }
  17. #endif
  18. UI_config_client_appkey_binding(0,0,UI_appkey);//重点
  19. 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);
  20. UI_prov_data.uaddr = 0x0001;
  21. //Get network key
  22. retval = MS_access_cm_get_netkey_at_offset(0,0,UI_prov_data.netkey);
  23. if(retval == ACCESS_NO_MATCH) //if can't find netkey,generate it
  24. {
  25. UI_netkey_generate(UI_prov_data.netkey);
  26. }
  27. //Get key refresh state
  28. MS_access_cm_get_key_refresh_phase(0,&key_refresh_state);
  29. key_refresh_state = (MS_ACCESS_KEY_REFRESH_PHASE_2 == key_refresh_state) ? 0x01 : 0x00;
  30. UI_prov_data.ivindex = ms_iv_index.iv_index;
  31. UI_prov_data.flags = ((ms_iv_index.iv_update_state & 0x01) << 1) | key_refresh_state;
  32. retval = UI_set_provision_data(UI_prov_data.uaddr);
  33. /* Set the Publish address for onoff and vendor model Client */
  34. UI_prov_data.uaddr = 0xCFFF;//重点
  35. UI_set_publish_address(UI_prov_data.uaddr, UI_generic_onoff_client_model_handle,MS_FALSE);//重点
  36. UI_set_publish_address(UI_prov_data.uaddr, UI_vendor_defined_client_model_handle,MS_FALSE);

发送“generic_onoff_set”命令

  1. void UI_generic_onoff_set(UCHAR state)
  2. {
  3. API_RESULT retval;
  4. MS_GENERIC_ONOFF_SET_STRUCT param;
  5. CONSOLE_OUT
  6. ("Send Generic Onoff Set\n");
  7. param.onoff = state;
  8. param.tid = 0;
  9. param.optional_fields_present = 0x00;
  10. retval = MS_generic_onoff_set(&param);//重点
  11. CONSOLE_OUT
  12. ("Retval - 0x%04X\n", retval);
  13. }
  14. #define MS_generic_onoff_set(param) \
  15. MS_generic_onoff_client_send_reliable_pdu \
  16. (\
  17. MS_ACCESS_GENERIC_ONOFF_SET_OPCODE,\//重点
  18. param,\
  19. MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE\
  20. )

处理generic_onoff回调

  1. API_RESULT UI_generic_onoff_client_cb
  2. (
  3. /* IN */ MS_ACCESS_MODEL_HANDLE* handle,
  4. /* IN */ UINT32 opcode,
  5. /* IN */ UCHAR* data_param,
  6. /* IN */ UINT16 data_len
  7. )
  8. {
  9. API_RESULT retval;
  10. retval = API_SUCCESS;
  11. CONSOLE_OUT (
  12. "[GENERIC_ONOFF_CLIENT] Callback. Opcode 0x%04X\n", opcode);
  13. appl_dump_bytes(data_param, data_len);
  14. switch(opcode)
  15. {
  16. case MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE://重点
  17. {
  18. CONSOLE_OUT(
  19. "MS_ACCESS_GENERIC_ONOFF_STATUS_OPCODE\n");
  20. }
  21. break;
  22. }
  23. return retval;
  24. }

服务端(light节点):
初始化

  1. if (API_SUCCESS == retval)
  2. {
  3. /* Register Generic OnOff model server */
  4. retval = UI_register_generic_onoff_model_server(element_handle);
  5. }

绑定appkey

  1. API_RESULT UI_sample_binding_app_key(void)
  2. {
  3. MS_APPKEY_HANDLE handle;
  4. UINT8* key;
  5. UINT8 aid;
  6. DECL_CONST UINT8 t_key[16] = {0};
  7. API_RESULT retval;
  8. CONSOLE_OUT("Fetching App Key for Handle 0x0000\n");
  9. handle = 0x0000;
  10. retval = MS_access_cm_get_app_key
  11. (
  12. handle,
  13. &key,
  14. &aid
  15. );
  16. /* Check Retval. Print App Key */
  17. if (API_SUCCESS == retval)
  18. {
  19. CONSOLE_OUT("App Key[0x%02X]: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
  20. handle, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
  21. key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
  22. if (0 == EM_mem_cmp(key, t_key, 16))
  23. {
  24. /* NO AppKey Bound */
  25. retval = API_FAILURE;
  26. }
  27. else
  28. {
  29. /* Found a Valid App Key */
  30. /* Keeping the retval as API_SUCCESS */
  31. retval=MS_access_bind_model_app(UI_generic_onoff_server_model_handle, handle);//重点
  32. #ifdef USE_LIGHTNESS
  33. retval=MS_access_bind_model_app(UI_light_lightness_server_model_handle, handle);
  34. CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_light_lightness_server_model_handle,handle);
  35. #endif
  36. #ifdef USE_CTL
  37. retval=MS_access_bind_model_app(UI_light_ctl_server_model_handle, handle);
  38. CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_light_ctl_server_model_handle,handle);
  39. #endif
  40. #ifdef USE_HSL
  41. retval=MS_access_bind_model_app(UI_light_hsl_server_model_handle, handle);
  42. CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_light_hsl_server_model_handle,handle);
  43. #endif
  44. #ifdef USE_SCENE
  45. retval=MS_access_bind_model_app(UI_scene_server_model_handle, handle);
  46. CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_scene_server_model_handle,handle);
  47. #endif
  48. #ifdef USE_VENDORMODEL
  49. retval=MS_access_bind_model_app(UI_vendor_defined_server_model_handle, handle);
  50. CONSOLE_OUT("BINDING App Key %04x (%04x %04x)\n",retval,UI_vendor_defined_server_model_handle,handle);
  51. #endif
  52. }
  53. }
  54. #ifdef EASY_BOUNDING
  55. //Provision ok,stop provision/config timeout handler by hq
  56. CONSOLE_OUT("Stop timer\n");
  57. EM_stop_timer(&procfg_timer_handle);
  58. blebrr_prov_started = MS_FALSE;
  59. #endif
  60. return retval;
  61. }

订阅0xCFFF

  1. vm_subscriptiong_add (0xCFFF);//重点
  2. void vm_subscriptiong_add (MS_NET_ADDR addr)
  3. {
  4. CONSOLE_OUT("vm_subscriptiong_add:%x\n",addr);
  5. MS_ACCESS_ADDRESS sub_addr;
  6. sub_addr.use_label=0;
  7. sub_addr.addr=addr;
  8. MS_access_ps_store_disable(MS_TRUE);
  9. MS_access_cm_add_model_subscription(UI_generic_onoff_server_model_handle,&sub_addr);
  10. #ifdef USE_LIGHTNESS
  11. MS_access_cm_add_model_subscription(UI_light_lightness_server_model_handle,&sub_addr);
  12. #endif
  13. #ifdef USE_CTL
  14. MS_access_cm_add_model_subscription(UI_light_ctl_server_model_handle,&sub_addr);
  15. MS_access_cm_add_model_subscription(UI_light_ctl_setup_server_model_handle,&sub_addr);
  16. #endif
  17. #ifdef USE_HSL
  18. MS_access_cm_add_model_subscription(UI_light_hsl_server_model_handle,&sub_addr);
  19. MS_access_cm_add_model_subscription(UI_light_hsl_setup_server_model_handle,&sub_addr);
  20. #endif
  21. #ifdef USE_SCENE
  22. MS_access_cm_add_model_subscription(UI_scene_server_model_handle,&sub_addr);
  23. MS_access_cm_add_model_subscription(UI_scene_setup_server_model_handle,&sub_addr);
  24. #endif
  25. MS_access_ps_store_disable(MS_FALSE);
  26. MS_access_ps_store_all_record();
  27. }

回调处理

  1. static API_RESULT UI_generic_onoff_server_cb
  2. (
  3. /* IN */ MS_ACCESS_MODEL_REQ_MSG_CONTEXT* ctx,
  4. /* IN */ MS_ACCESS_MODEL_REQ_MSG_RAW* msg_raw,
  5. /* IN */ MS_ACCESS_MODEL_REQ_MSG_T* req_type,
  6. /* IN */ MS_ACCESS_MODEL_STATE_PARAMS* state_params,
  7. /* IN */ MS_ACCESS_MODEL_EXT_PARAMS* ext_params
  8. )
  9. {
  10. MS_STATE_GENERIC_ONOFF_STRUCT param;
  11. MS_ACCESS_MODEL_STATE_PARAMS current_state_params;
  12. API_RESULT retval;
  13. retval = API_SUCCESS;
  14. /* Check message type */
  15. if (MS_ACCESS_MODEL_REQ_MSG_T_GET == req_type->type)
  16. {
  17. CONSOLE_OUT("[GENERIC_ONOFF] GET Request.\n");
  18. UI_generic_onoff_model_state_get(state_params->state_type, 0, &param, 0);
  19. current_state_params.state_type = state_params->state_type;
  20. current_state_params.state = &param;
  21. /* Using same as target state and remaining time as 0 */
  22. }
  23. else if (MS_ACCESS_MODEL_REQ_MSG_T_SET == req_type->type)//重点
  24. {
  25. CONSOLE_OUT("[GENERIC_ONOFF] SET Request.\n");
  26. retval = UI_generic_onoff_model_state_set(state_params->state_type, 0, (MS_STATE_GENERIC_ONOFF_STRUCT*)state_params->state, 0);//重点
  27. current_state_params.state_type = state_params->state_type;
  28. current_state_params.state = (MS_STATE_GENERIC_ONOFF_STRUCT*)state_params->state;
  29. }
  30. /* See if to be acknowledged */
  31. if (0x01 == req_type->to_be_acked)
  32. {
  33. CONSOLE_OUT("[GENERIC_ONOFF] Sending Response.\n");
  34. /* Parameters: Request Context, Current State, Target State (NULL: to be ignored), Remaining Time (0: to be ignored), Additional Parameters (NULL: to be ignored) */
  35. retval = MS_generic_onoff_server_state_update(ctx, &current_state_params, NULL, 0, NULL);
  36. }
  37. return retval;
  38. }
  39. static API_RESULT UI_generic_onoff_model_state_set(UINT16 state_t, UINT16 state_inst, void* param, UINT8 direction)
  40. {
  41. API_RESULT retval;
  42. UCHAR proxy_state;
  43. retval = API_SUCCESS;
  44. switch (state_t)
  45. {
  46. case MS_STATE_GENERIC_ONOFF_T:
  47. {
  48. MS_STATE_GENERIC_ONOFF_STRUCT* param_p;
  49. param_p = (MS_STATE_GENERIC_ONOFF_STRUCT*)param;
  50. /* Instantaneous Change */
  51. UI_generic_onoff.onoff = param_p->onoff;
  52. *param_p = UI_generic_onoff;
  53. CONSOLE_OUT("[state] current: 0x%02X\n", UI_generic_onoff.onoff);
  54. CONSOLE_OUT("[state] target: 0x%02X\n", UI_generic_onoff.target_onoff);
  55. CONSOLE_OUT("[state] remaining_time: 0x%02X\n", UI_generic_onoff.transition_time);
  56. proxy_state = UI_proxy_state_get();
  57. if(proxy_state==MS_PROXY_CONNECTED)
  58. {
  59. EM_start_timer (&proxy_dly_thandle, (EM_TIMEOUT_MILLISEC | 100), proxy_dly_generic_onoff, NULL, 0);
  60. }
  61. else
  62. {
  63. generic_onoff_set_pl(param_p->onoff);//重点
  64. }
  65. /* Ignoring Instance and direction right now */
  66. }
  67. break;
  68. default:
  69. break;
  70. }
  71. return retval;
  72. }