/********************************************************************* * @fn GenericApp_ProcessRtosMessage * * @brief Receive message from RTOS queue, send response back. * * @param none * * @return none */ static void GenericApp_ProcessRtosMessage( void ) { osalQueue_t inMsg; if ( osal_queue_receive( OsalQueue, &inMsg, 0 ) == pdPASS ) { uint8 cmndId = inMsg.cmnd; uint32 counter = osal_build_uint32( inMsg.cbuf, 4 ); switch ( cmndId ) { case CMD_INCR: counter += 1; /* Increment the incoming counter */ /* Intentionally fall through next case */ case CMD_ECHO: { userQueue_t outMsg; outMsg.resp = RSP_CODE | cmndId; /* Response ID */ osal_buffer_uint32( outMsg.rbuf, counter ); /* Increment counter */ osal_queue_send( UserQueue1, &outMsg, 0 ); /* Send back to UserTask */ break; } default: break; /* Ignore unknown command */ } } }
/********************************************************************* * @fn thermometerMeasIndicate * * @brief Prepare and send a thermometer measurement notification * * @return none */ static void thermometerMeasIndicate(void) { // att value notification structure uint8 *p = thermometerMeas.value; // temperature uint32 temperature; //flags uint8 flags = thermometerFlags[thermometerFlagsIdx]; // flags 1 byte long *p++ = flags; if(flags & THERMOMETER_FLAGS_FARENHEIT) { temperature = (thermometerCelcius *9/5) +320; } else { temperature = thermometerCelcius; } temperature = 0xFF000000 | temperature; //osal_buffer_uint32 osal_buffer_uint32( p, temperature ); //temperature is 4 bytes long *p++; *p++; *p++; *p++; //timestamp if (flags & THERMOMETER_FLAGS_TIMESTAMP) { UTCTimeStruct time; // Get time structure from OSAL osal_ConvertUTCTime( &time, osal_getClock() ); *p++ = (time.year & 0x00FF); *p++ = (time.year & 0xFF00)>>8; //*p++ = time.year; //*p++; *p++=time.month; *p++=time.day; *p++=time.hour; *p++=time.minutes; *p++=time.seconds; }
/*************************************************************************************************** * @fn MT_SysGetUtcTime * * @brief Get the OSAL UTC time * * @param None * * @return 32-bit and Parsed UTC time ***************************************************************************************************/ void MT_SysGetUtcTime(void) { uint8 len; uint8 *buf; len = sizeof( UTCTime ) + sizeof( UTCTimeStruct ); buf = osal_mem_alloc( len ); if ( buf ) { uint8 *pBuf; UTCTime utcSecs; UTCTimeStruct utcTime; // Get current 32-bit UTC time and parse it utcSecs = osal_getClock(); osal_ConvertUTCTime( &utcTime, utcSecs ); // Start with 32-bit UTC time pBuf = osal_buffer_uint32( buf, utcSecs ); // Concatenate parsed UTC time fields *pBuf++ = utcTime.hour; *pBuf++ = utcTime.minutes; *pBuf++ = utcTime.seconds; *pBuf++ = utcTime.month + 1; // Convert to human numbers *pBuf++ = utcTime.day + 1; *pBuf++ = LO_UINT16( utcTime.year ); *pBuf++ = HI_UINT16( utcTime.year ); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SYS), MT_SYS_GET_TIME, (uint8)(pBuf-buf), buf); osal_mem_free( buf ); } }
/********************************************************************* * @fn thermometerMeasIndicate * * @brief Prepare and send a thermometer measurement indication * * @return none */ static void thermometerMeasIndicate(void) { // Thermometer measurement value stored in this structure. attHandleValueInd_t thermometerMeas; thermometerMeas.pValue = GATT_bm_alloc(gapConnHandle, ATT_HANDLE_VALUE_IND, THERMOMETER_MEAS_LEN, NULL); if (thermometerMeas.pValue != NULL) { // att value notification structure uint8 *p = thermometerMeas.pValue; // temperature uint32 temperature; //flags uint8 flags = thermometerFlags[thermometerFlagsIdx]; // flags 1 byte long *p++ = flags; if(flags & THERMOMETER_FLAGS_FARENHEIT) { temperature = (thermometerCelcius *9/5) +320; } else { temperature = thermometerCelcius; } temperature = 0xFF000000 | temperature; //osal_buffer_uint32 p = osal_buffer_uint32( p, temperature ); //timestamp if (flags & THERMOMETER_FLAGS_TIMESTAMP) { UTCTimeStruct time; // Get time structure from OSAL osal_ConvertUTCTime( &time, osal_getClock() ); *p++ = LO_UINT16(time.year); *p++ = HI_UINT16(time.year); *p++ = time.month; *p++ = time.day; *p++ = time.hour; *p++ = time.minutes; *p++ = time.seconds; } if(flags & THERMOMETER_FLAGS_TYPE) { uint8 site; Thermometer_GetParameter( THERMOMETER_TYPE, &site ); *p++ = site; } thermometerMeas.len = (uint8) (p - thermometerMeas.pValue); thermometerMeas.handle = THERMOMETER_TEMP_VALUE_POS; // Queue indication. thermometerStoreIndications( &thermometerMeas); //advertise measurement is ready thermometer_Advertise(); } }
/********************************************************************* * @fn thermometerMeasNotify * * @brief Prepare and send a thermometer measurement notification * * @return none */ static void thermometerImeasNotify(void) { if (temperatureIMeasCharConfig == true) { attHandleValueNoti_t thermometerIMeas; thermometerIMeas.pValue = GATT_bm_alloc( gapConnHandle, ATT_HANDLE_VALUE_NOTI, THERMOMETER_IMEAS_LEN, NULL ); if ( thermometerIMeas.pValue != NULL ) { // att value notification structure uint8 *p = thermometerIMeas.pValue; // temperature uint32 temperature; //flags uint8 flags = thermometerFlags[thermometerFlagsIdx]; // flags 1 byte long *p++ = flags; if(flags & THERMOMETER_FLAGS_FARENHEIT) { temperature = (thermometerCelcius *9/5) +320; } else { temperature = thermometerCelcius; } temperature = 0xFF000000 | temperature; //osal_buffer_uint32 p = osal_buffer_uint32( p, temperature ); //timestamp if (flags & THERMOMETER_FLAGS_TIMESTAMP) { UTCTimeStruct time; // Get time structure from OSAL osal_ConvertUTCTime( &time, osal_getClock() ); *p++ = LO_UINT16(time.year); *p++ = HI_UINT16(time.year); *p++ = time.month; *p++ = time.day; *p++ = time.hour; *p++ = time.minutes; *p++ = time.seconds; } if(flags & THERMOMETER_FLAGS_TYPE) { uint8 site; Thermometer_GetParameter( THERMOMETER_TYPE, &site ); *p++ = site; } thermometerIMeas.len = (uint8) (p - thermometerIMeas.pValue); if ( Thermometer_IMeasNotify( gapConnHandle, &thermometerIMeas) != SUCCESS ) { GATT_bm_free( (gattMsg_t *)&thermometerIMeas, ATT_HANDLE_VALUE_NOTI ); } } } }
/********************************************************************* * @fn OTA_Send_ReadAttrInd * * @brief Notifies the console about attribute values for a device. * * @param none. * * @return none */ void OTA_Send_ReadAttrInd(uint16 cluster, uint16 shortAddr, zclReadRspStatus_t *pAttr) { uint8 buffer[OTA_APP_READ_ATTRIBUTE_IND_LEN]; uint8 *pBuf = buffer; uint8 len; *pBuf++ = OTA_SYSAPP_ENDPOINT; *pBuf++ = OTA_APP_READ_ATTRIBUTE_IND; *pBuf++ = LO_UINT16(_NIB.nwkPanId); *pBuf++ = HI_UINT16(_NIB.nwkPanId); *pBuf++ = LO_UINT16(cluster); *pBuf++ = HI_UINT16(cluster); *pBuf++ = LO_UINT16(shortAddr); *pBuf++ = HI_UINT16(shortAddr); *pBuf++ = LO_UINT16(pAttr->attrID); *pBuf++ = HI_UINT16(pAttr->attrID); *pBuf++ = pAttr->status; *pBuf++ = pAttr->dataType; len = zclGetDataTypeLength(pAttr->dataType); // We should not be reading attributes greater than 8 bytes in length if (len <= 8) { *pBuf++ = len; if (len) { uint8 *pStr; switch ( pAttr->dataType ) { case ZCL_DATATYPE_UINT8: *pBuf = *((uint8 *)pAttr->data); break; case ZCL_DATATYPE_UINT16: *pBuf++ = LO_UINT16( *((uint16*)pAttr->data) ); *pBuf++ = HI_UINT16( *((uint16*)pAttr->data) ); break; case ZCL_DATATYPE_UINT32: pBuf = osal_buffer_uint32( pBuf, *((uint32*)pAttr->data) ); break; case ZCL_DATATYPE_IEEE_ADDR: pStr = (uint8*)pAttr->data; osal_memcpy( pBuf, pStr, 8 ); break; default: break; } } } else *pBuf = 0; // Send the indication MT_BuildAndSendZToolResponse(MT_RPC_SYS_APP, MT_APP_MSG, OTA_APP_READ_ATTRIBUTE_IND_LEN, buffer); }
/************************************************************************************************** * @fn MT_ZnpBasicRsp * * @brief Build and send the ZNP Basic Response to the ZAP. * * input parameters * * None. * * output parameters * * None. * * @return true if message built and sent; false otherwise. */ bool MT_ZnpBasicRsp(void) { uint8 *pBuf = osal_mem_alloc(sizeof(mt_znp_basic_rsp_t)); if (pBuf == NULL) { return false; } osal_buffer_uint32( &pBuf[0], MT_PeriodicMsgRate ); osal_buffer_uint32( &pBuf[4], zgDefaultChannelList ); pBuf[8] = LO_UINT16(zgConfigPANID); pBuf[9] = HI_UINT16(zgConfigPANID); osal_nv_read(ZCD_NV_STARTUP_OPTION, 0, 1, pBuf+10); pBuf[11] = zgDeviceLogicalType; pBuf[12] = LO_UINT16(_NIB.nwkDevAddress); pBuf[13] = HI_UINT16(_NIB.nwkDevAddress); pBuf[14] = LO_UINT16(_NIB.nwkCoordAddress); pBuf[15] = HI_UINT16(_NIB.nwkCoordAddress); pBuf[16] = LO_UINT16(_NIB.nwkPanId); pBuf[17] = HI_UINT16(_NIB.nwkPanId); pBuf[18] = _NIB.nwkLogicalChannel; pBuf[19] = _NIB.nwkState; (void)osal_memcpy(pBuf+20, _NIB.nwkCoordExtAddress, Z_EXTADDR_LEN); (void)osal_memcpy(pBuf+28, aExtendedAddress, Z_EXTADDR_LEN); pBuf[36] = devState; #if defined INTER_PAN extern uint8 appEndPoint; pBuf[37] = appEndPoint; //rsp->spare1[2]; #else //rsp->spare1[3]; #endif // Initialize list with invalid EndPoints. (void)osal_memset(pBuf+40, AF_BROADCAST_ENDPOINT, (MT_ZNP_EP_ID_LIST_MAX * 3)); uint8 idx = 40; epList_t *epItem = epList; for (uint8 cnt = 0; cnt < MT_ZNP_EP_ID_LIST_MAX; cnt++) { if (epItem == NULL) { break; } if ((epItem->epDesc->simpleDesc != NULL) && (epItem->epDesc->simpleDesc->EndPoint != ZDO_EP)) { pBuf[idx++] = epItem->epDesc->simpleDesc->EndPoint; pBuf[idx++] = LO_UINT16(epItem->epDesc->simpleDesc->AppProfId); pBuf[idx++] = HI_UINT16(epItem->epDesc->simpleDesc->AppProfId); } epItem = epItem->nextDesc; } idx = 40 + (MT_ZNP_EP_ID_LIST_MAX * 3); // Initialize list with invalid Cluster Id's. (void)osal_memset(pBuf+idx, 0xFF, (MT_ZNP_ZDO_MSG_CB_LIST_MAX * 2)); typedef struct { void *next; uint8 taskID; uint16 clusterID; } ZDO_MsgCB_t; extern ZDO_MsgCB_t *zdoMsgCBs; ZDO_MsgCB_t *pItem = zdoMsgCBs; for (uint8 cnt = 0; cnt < MT_ZNP_ZDO_MSG_CB_LIST_MAX; cnt++) { if (pItem == NULL) { break; } else if (pItem->taskID == MT_TaskID) { pBuf[idx++] = LO_UINT16(pItem->clusterID); pBuf[idx++] = HI_UINT16(pItem->clusterID); } pItem = pItem->next; } idx = 40 + (MT_ZNP_EP_ID_LIST_MAX * 3) + (MT_ZNP_ZDO_MSG_CB_LIST_MAX * 2); extern pfnZdoCb zdoCBFunc[MAX_ZDO_CB_FUNC]; for (uint8 cnt = 0; cnt < MAX_ZDO_CB_FUNC; cnt++) { pBuf[idx++] = (zdoCBFunc[cnt] == NULL) ? 0 : 1; } MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ | (uint8)MT_RPC_SYS_ZNP), MT_ZNP_BASIC_RSP, 40 + (MT_ZNP_EP_ID_LIST_MAX * 3) + (MT_ZNP_ZDO_MSG_CB_LIST_MAX * 2) + MAX_ZDO_CB_FUNC, pBuf); (void)osal_mem_free(pBuf); return true; }