/** * \file phy_model_client.c * * \brief This file defines the Mesh Configuration Model Application Interface * - includes Data Structures and Methods for both Server and Client. */ /* * Copyright (C) 2020. phyplus Ltd. * All rights reserved. */ /* --------------------------------------------- Header File Inclusion */ #include "phymodel_client.h" /* --------------------------------------------- Data Types/ Structures */ /* --------------------------------------------- Global Definitions */ /* --------------------------------------------- Static Global Variables */ static DECL_CONST UINT32 phy_model_client_opcode_list[] = { MS_ACCESS_PHY_MODEL_STATUS_OPCODE, MS_ACCESS_PHY_MODEL_INDICATION_OPCODE, MS_ACCESS_PHY_MODEL_WRITECMD_OPCODE, MS_ACCESS_PHY_MODEL_NOTIFY_OPCODE }; static MS_ACCESS_MODEL_HANDLE phy_model_client_model_handle; static MS_PHY_MODEL_CLIENT_CB phy_model_client_UI_cb; /* --------------------------------------------- External Global Variables */ /* --------------------------------------------- Function */ /** * \brief Access Layer Application Asynchronous Notification Callback. * * \par Description * Access Layer calls the registered callback to indicate events occurred to the application. * * \param [in] handle Model Handle. * \param [in] saddr 16 bit Source Address. * \param [in] daddr 16 bit Destination Address. * \param [in] appkey_handle AppKey Handle. * \param [in] subnet_handle Subnet Handle. * \param [in] opcode Opcode. * \param [in] data_param Data associated with the event if any or NULL. * \param [in] data_len Size of the event data. 0 if event data is NULL. */ API_RESULT phy_model_client_cb ( /* IN */ MS_ACCESS_MODEL_HANDLE * handle, /* IN */ MS_NET_ADDR saddr, /* IN */ MS_NET_ADDR daddr, /* IN */ MS_SUBNET_HANDLE subnet_handle, /* IN */ MS_APPKEY_HANDLE appkey_handle, /* IN */ UINT32 opcode, /* IN */ UCHAR * data_param, /* IN */ UINT16 data_len ) { MS_ACCESS_MODEL_REQ_MSG_CONTEXT req_context; MS_ACCESS_MODEL_REQ_MSG_RAW req_raw; MS_ACCESS_MODEL_REQ_MSG_T req_type; MS_ACCESS_MODEL_EXT_PARAMS * ext_params_p; MS_ACCESS_PHY_MODEL_STATE_PARAMS state_params; UINT16 marker = 0; API_RESULT retval; retval = API_SUCCESS; ext_params_p = NULL; /* Request Context */ req_context.handle = *handle; req_context.saddr = saddr; req_context.daddr = daddr; req_context.subnet_handle = subnet_handle; req_context.appkey_handle = appkey_handle; /* Request Raw */ req_raw.opcode = opcode; req_raw.data_param = data_param; req_raw.data_len = data_len; // printf( // "[PHY_MODEL_CLIENT] Callback. Opcode 0x%04X\n", opcode); // appl_dump_bytes(data_param, data_len); switch(opcode) { case MS_ACCESS_PHY_MODEL_STATUS_OPCODE: { // printf( // "MS_ACCESS_PHY_MODEL_STATUS_MSG\n"); MODEL_OPCODE_HANDLER_CALL(vendor_example_transparent_msg_handler); /* Set Request Type */ req_type.type = MS_ACCESS_MODEL_REQ_MSG_T_OTHERS; req_type.to_be_acked = 0x00; } break; case MS_ACCESS_PHY_MODEL_INDICATION_OPCODE: { // printf( // "MS_ACCESS_PHY_MODEL_INDICATION_OPCODE_MSG\n"); marker = 1; MS_UNPACK_LE_2_BYTE(&state_params.phy_mode_type, data_param+marker); marker += 2; state_params.phy_mode_param = &data_param[marker]; /* Set Request Type */ req_type.type = MS_ACCESS_MODEL_REQ_MSG_T_OTHERS; req_type.to_be_acked = 0x01; } break; case MS_ACCESS_PHY_MODEL_WRITECMD_OPCODE: { // printf( // "MS_ACCESS_PHY_MODEL_WRITECMD_OPCODE\n"); // UCHAR *_data_pram; marker = 1; MS_UNPACK_LE_2_BYTE(&state_params.phy_mode_type, data_param+marker); marker += 2; // if(data_len>3) // { // _data_pram = EM_alloc_mem(data_len - 3); // EM_mem_copy(_data_pram, data_param+marker, data_len-3); // } // EM_mem_copy((UCHAR *)state_params.state,data_param+marker,data_len-3); state_params.phy_mode_param = &data_param[marker]; // EM_free_mem(_data_pram); /* Set Request Type */ req_type.type = MS_ACCESS_MODEL_REQ_MSG_T_OTHERS; req_type.to_be_acked = 0x00; } break; case MS_ACCESS_PHY_MODEL_NOTIFY_OPCODE: { // UCHAR *_data_pram; state_params.phy_mode_type = MS_STATE_PHYMODEL_NOTIFY_T; marker = 1; // if(data_len > 1) // { // _data_pram = EM_alloc_mem(data_len - 1); // EM_mem_copy(_data_pram, data_param+marker, data_len-1); // } state_params.phy_mode_param = &data_param[marker]; // EM_free_mem(_data_pram); /* Set Request Type */ req_type.type = MS_ACCESS_MODEL_REQ_MSG_T_OTHERS; req_type.to_be_acked = 0x00; } break; default: // printf( // "MS_ACCESS_PHY_MODEL_NONE_OPCODE\n"); break; } /* Application callback */ if (NULL != phy_model_client_UI_cb) { phy_model_client_UI_cb(&req_context, &req_raw, &req_type, &state_params, ext_params_p); } return retval; } /* ----------------------------------------- Functions */ /** * \brief API to send reply or to update state change * * \par Description * This is to send reply for a request or to inform change in state. * * \param [in] ctx Context of the message. * \param [in] current_state_params Model specific current state parameters. * \param [in] target_state_params Model specific target state parameters (NULL: to be ignored). * \param [in] remaining_time Time from current state to target state (0: to be ignored). * \param [in] ext_params Additional parameters (NULL: to be ignored). * * \return API_SUCCESS or an error code indicating reason for failure */ API_RESULT MS_phy_model_client_state_update ( /* IN */ MS_ACCESS_MODEL_REQ_MSG_CONTEXT * ctx, /* IN */ MS_ACCESS_PHY_MODEL_STATE_PARAMS * current_state_params, /* IN */ MS_ACCESS_MODEL_STATE_PARAMS * target_state_params, /* IN */ UINT16 remaining_time, /* IN */ MS_ACCESS_MODEL_EXT_PARAMS * ext_params, /* IN */ UINT16 data_length ) { API_RESULT retval; /* TODO: Check what should be maximum length */ UCHAR buffer[256]; UCHAR * pdu_ptr; UINT16 marker; UINT32 opcode; retval = API_FAILURE; marker = 0; // printf( // "current_state_params->state_type 0x%04X.\n",current_state_params->phy_mode_type); switch (current_state_params->phy_mode_type) { case MS_STATE_PHY_MODEL_ONOFF_T: { buffer[marker] = ++vendor_tid; marker++; MS_PACK_LE_2_BYTE_VAL(&buffer[marker], current_state_params->phy_mode_type); marker += 2; EM_mem_copy(&buffer[marker], current_state_params->phy_mode_param, 1); marker++; /* Set Opcode */ opcode = MS_ACCESS_PHY_MODEL_CONFIRMATION_OPCODE; } break; default: break; } /* Publish - reliable */ if (0 == marker) { pdu_ptr = NULL; } else { pdu_ptr = buffer; } retval = MS_access_reply ( &ctx->handle, ctx->daddr, ctx->saddr, ctx->subnet_handle, ctx->appkey_handle, ACCESS_INVALID_DEFAULT_TTL, opcode, pdu_ptr, marker ); return retval; } /** * \brief API to send acknowledged commands * * \par Description * This is to initialize sending acknowledged commands. * * \param [in] req_opcode Request Opcode. * \param [in] param Parameter associated with Request Opcode. * \param [in] rsp_opcode Response Opcode. * * \return API_SUCCESS or an error code indicating reason for failure */ API_RESULT MS_phymodel_client_send_reliable_pdu ( /* IN */ UINT32 req_opcode, /* IN */ void * param, /* IN */ MS_NET_ADDR dst_addr ) { API_RESULT retval; /* TODO: Check what should be maximum length */ UCHAR buffer[256]; UCHAR * pdu_ptr; UINT16 marker; MS_APPKEY_HANDLE key_handle; retval = API_FAILURE; marker = 0; // printf( // "[VENDOR_MODEL_CLIENT] Send Reliable PDU. Req Opcode 0x%08X\n", // req_opcode); switch(req_opcode) { case MS_ACCESS_PHY_MODEL_GET_OPCODE: { MS_ACCESS_PHY_MODEL_STATE_PARAMS * param_p; buffer[marker] = ++vendor_tid; marker++; param_p = (MS_ACCESS_PHY_MODEL_STATE_PARAMS *) param; MS_PACK_LE_2_BYTE_VAL(&buffer[marker], param_p->phy_mode_type); marker += 2; } break; case MS_ACCESS_PHY_MODEL_SET_OPCODE: case MS_ACCESS_PHY_MODEL_SET_UNACKNOWLEDGED_OPCODE: { MS_ACCESS_PHY_MODEL_STATE_PARAMS * param_p; buffer[marker] = ++vendor_tid; marker++; param_p = (MS_ACCESS_PHY_MODEL_STATE_PARAMS *) param; MS_PACK_LE_2_BYTE_VAL(&buffer[marker], param_p->phy_mode_type); marker += 2; switch(param_p->phy_mode_type) { case MS_STATE_PHY_MODEL_ONOFF_T: { EM_mem_copy(&buffer[marker], param_p->phy_mode_param, 1); marker += 1; } break; case MS_STATE_PHY_MODEL_HSL_T: { EM_mem_copy(&buffer[marker], param_p->phy_mode_param, 6); marker += 6; } break; default : break; } } break; case MS_ACCESS_PHY_MODEL_NOTIFY_OPCODE: { UINT16 len; MS_ACCESS_PHY_MODEL_STATE_PARAMS * param_p; param_p = (MS_ACCESS_PHY_MODEL_STATE_PARAMS *) param; MS_IGNORE_UNUSED_PARAM(param_p->phy_mode_type); MS_UNPACK_LE_2_BYTE(&len, param_p->phy_mode_param); buffer[marker] = ++vendor_tid; marker ++; if(len) { EM_mem_copy(&buffer[marker], ¶m_p->phy_mode_param[2], len); marker += len; } } break; default: break; } /* Publish - reliable */ if (0 == marker) { pdu_ptr = NULL; } else { pdu_ptr = buffer; } MS_access_get_appkey_handle ( &phy_model_client_model_handle, &key_handle ); retval = MS_access_raw_data ( &phy_model_client_model_handle, req_opcode, dst_addr, key_handle, pdu_ptr, marker, MS_FALSE ); return retval; } /** * \brief API to initialize Vendor_Example_1 Server model * * \par Description * This is to initialize Vendor_Example_1 Server model and to register with Acess layer. * * \param [in] element_handle * Element identifier to be associated with the model instance. * * \param [in, out] model_handle * Model identifier associated with the model instance on successful initialization. * After power cycle of an already provisioned node, the model handle will have * valid value and the same will be reused for registration. * * \param [in] UI_cb Application Callback to be used by the Vendor_Example_1 Server. * * \return API_SUCCESS or an error code indicating reason for failure */ API_RESULT MS_phy_model_client_init ( /* IN */ MS_ACCESS_ELEMENT_HANDLE element_handle, /* INOUT */ MS_ACCESS_MODEL_HANDLE * model_handle, /* IN */ MS_PHY_MODEL_CLIENT_CB UI_cb ) { API_RESULT retval; MS_ACCESS_NODE_ID node_id; MS_ACCESS_MODEL model; /* TBD: Initialize MUTEX and other data structures */ /* Using default node ID */ node_id = MS_ACCESS_DEFAULT_NODE_ID; // printf( // "[PHY_MODEL] Registered Element Handle 0x%02X\n", element_handle); /* Configure Model */ model.model_id.id = MS_MODEL_ID_PHY_MODEL_CLIENT; model.model_id.type = MS_ACCESS_MODEL_TYPE_VENDOR; model.elem_handle = element_handle; /* Register Callback */ model.cb = phy_model_client_cb; /* List of Opcodes */ model.opcodes = phy_model_client_opcode_list; model.num_opcodes = sizeof(phy_model_client_opcode_list) / sizeof(UINT32); retval = MS_access_register_model ( node_id, &model, model_handle ); /* Save Application Callback */ phy_model_client_UI_cb = UI_cb; phy_model_client_model_handle = *model_handle; return retval; }