/********************************************************************* * @fn zclApplianceStatistics_LogQueueRsp_NativeToOta * * @brief Converts from native to OTA format. * * @param disableDefaultRsp - whether to disable the Default Response command * @param pZclPayloadLen - returns zcl payload len * * @return pointer to zcl payload */ uint8 *zclApplianceStatistics_LogQueueRsp_NativeToOta( zclCmdApplianceStatisticsLogQueueRspPayload_t *pPayload , uint16 * pZclPayloadLen ) { uint8 *pZclPayload; // OTA ZCL payload uint16 zclPayloadLen; // OTA ZCL payload length uint16 i; uint16 offset; // allocate some memory for the ZCL payload zclPayloadLen = 1 + (pPayload->logQueueSize * sizeof(uint32)); // # of LogQueue IDs pZclPayload = zcl_mem_alloc( zclPayloadLen ); if( !pZclPayload ) { return NULL; // no memory } // fill in payload pZclPayload[0] = pPayload->logQueueSize; offset = 1; for( i = 0; i < pPayload->logQueueSize; ++i ) { pZclPayload[offset] = BREAK_UINT32(pPayload->pLogID[i], 0); pZclPayload[offset+1] = BREAK_UINT32(pPayload->pLogID[i], 1); pZclPayload[offset+2] = BREAK_UINT32(pPayload->pLogID[i], 2); pZclPayload[offset+3] = BREAK_UINT32(pPayload->pLogID[i], 3); offset += sizeof( uint32 ); } // return OTA payload and length *pZclPayloadLen = zclPayloadLen; return pZclPayload; }
/** * SNP_getRev * */ void SNP_getRev(snpGetRevisionRsp_t *pRsp) { ICall_BuildRevision buildRev = {0}; pRsp->snpVer = BUILD_UINT16(HI_UINT16(SNP_VERSION), LO_UINT16(SNP_VERSION)); pRsp->status = Util_buildRevision(&buildRev); // Stack revision // Byte 0: Major // Byte 1: Minor // Byte 2: Patch pRsp->stackBuildVer[0] = BREAK_UINT32(buildRev.stackVersion, 0); pRsp->stackBuildVer[1] = BREAK_UINT32(buildRev.stackVersion, 1); pRsp->stackBuildVer[2] = BREAK_UINT32(buildRev.stackVersion, 2); // Build revision pRsp->stackBuildVer[3] = LO_UINT16(buildRev.buildVersion); pRsp->stackBuildVer[4] = HI_UINT16(buildRev.buildVersion); // Stack info (Byte 5) pRsp->stackBuildVer[5] = buildRev.stackInfo; // Controller info - part 1 (Byte 6) pRsp->stackBuildVer[6] = LO_UINT16(buildRev.ctrlInfo); // Controller info - part 2 (Byte 7) pRsp->stackBuildVer[7] = 0; // reserved // Host info - part 1 (Byte 8) pRsp->stackBuildVer[8] = LO_UINT16(buildRev.hostInfo); // Host info - part 2 (Byte 9) pRsp->stackBuildVer[9] = 0; // reserved }
/*************************************************************************************************** * @fn packDev_t * * @brief Pack an associated_devices_t structure into a byte buffer (pack INVALID_NODE_ADDR if * the pDev parameter is NULL). * * @param pBuf - pointer to the buffer into which to pack the structure. * @param pDev - pointer to the structure. * * @return void ***************************************************************************************************/ static void packDev_t(uint8 *pBuf, associated_devices_t *pDev) { if (NULL == pDev) { uint16 rtrn = INVALID_NODE_ADDR; *pBuf++ = LO_UINT16(rtrn); *pBuf++ = HI_UINT16(rtrn); } else { *pBuf++ = LO_UINT16(pDev->shortAddr); *pBuf++ = HI_UINT16(pDev->shortAddr); *pBuf++ = LO_UINT16(pDev->addrIdx); *pBuf++ = HI_UINT16(pDev->addrIdx); *pBuf++ = pDev->nodeRelation; *pBuf++ = pDev->devStatus; *pBuf++ = pDev->assocCnt; *pBuf++ = pDev->age; *pBuf++ = pDev->linkInfo.txCounter; *pBuf++ = pDev->linkInfo.txCost; *pBuf++ = pDev->linkInfo.rxLqi; *pBuf++ = pDev->linkInfo.inKeySeqNum; *pBuf++ = BREAK_UINT32(pDev->linkInfo.inFrmCntr, 0); *pBuf++ = BREAK_UINT32(pDev->linkInfo.inFrmCntr, 1); *pBuf++ = BREAK_UINT32(pDev->linkInfo.inFrmCntr, 2); *pBuf++ = BREAK_UINT32(pDev->linkInfo.inFrmCntr, 3); *pBuf++ = LO_UINT16(pDev->linkInfo.txFailure); *pBuf++ = HI_UINT16(pDev->linkInfo.txFailure); } }
/********************************************************************* * @fn zclElectricalMeasurement_Send_GetMeasurementProfileRsp * * @brief Call to send out Electrical Measurement Get Measurement Profile Response. This will * tell the client the appropriate parameters of the measurement profile. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param pPayload: * startTime - represents the end time of the most chronologically recent interval being requested * status - table status enumeration lists the valid values returned in status field * profileIntervalPeriod - time frame used to capture parameter for profiling purposes * numberOfIntervalsDelivered - number of intervals the device is returning * attributeID - attribute that has been profiled by the application * intervals - array of intervals that depend on numberOfIntervalsDelivered, type based on attributeID * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclElectricalMeasurement_Send_GetMeasurementProfileRsp( uint8 srcEP, afAddrType_t *dstAddr, zclElectricalMeasurementGetMeasurementProfileRsp_t *pPayload, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 i; uint8 offset; uint8 *pBuf; // variable length payload uint8 attrRtn; uint8 calculatedAttrLen; uint16 calculatedIntervalSize; uint16 calculatedBufLen; ZStatus_t status; zclAttrRec_t attrRec; // determine if attribute ID is found per EP and cluster ID attrRtn = zclFindAttrRec( dstAddr->endPoint, ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT, pPayload->attributeID, &attrRec ); if ( attrRtn == TRUE ) { // if found, determine length of attribute based on given type calculatedAttrLen = zclGetDataTypeLength( attrRec.attr.dataType ); } calculatedIntervalSize = calculatedAttrLen * pPayload->numberOfIntervalsDelivered; // get a buffer large enough to hold the whole packet, including size of variable array calculatedBufLen = ( 9 + calculatedIntervalSize ); pBuf = zcl_mem_alloc( calculatedBufLen ); if ( !pBuf ) { return ( ZMemError ); // no memory, return failure } pBuf[0] = BREAK_UINT32(pPayload->startTime, 0); pBuf[1] = BREAK_UINT32(pPayload->startTime, 1); pBuf[2] = BREAK_UINT32(pPayload->startTime, 2); pBuf[3] = BREAK_UINT32(pPayload->startTime, 3); pBuf[4] = pPayload->status; pBuf[5] = pPayload->profileIntervalPeriod; pBuf[6] = pPayload->numberOfIntervalsDelivered; pBuf[7] = LO_UINT16(pPayload->attributeID); pBuf[8] = HI_UINT16(pPayload->attributeID); offset = 9; for ( i = 0; i < calculatedIntervalSize; i++ ) { pBuf[offset++] = pPayload->pIntervals[i]; } status = zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT, COMMAND_ELECTRICAL_MEASUREMENT_GET_MEASUREMENT_PROFILE_RSP, TRUE, ZCL_FRAME_SERVER_CLIENT_DIR, disableDefaultRsp, 0, seqNum, calculatedBufLen, pBuf ); zcl_mem_free( pBuf ); return ( status ); }
/********************************************************************* * @fn Thermometer_measIndicate * * @brief Prepare and send a thermometer measurement notification. * * @param none * * @return none */ static void Thermometer_measIndicate(void) { // Thermometer measurement value stored in this structure. attHandleValueInd_t thermometerMeas; thermometerMeas.pValue = GATT_bm_alloc(thermometer_connHandle, ATT_HANDLE_VALUE_IND, THERMOMETER_MEAS_LEN, NULL); if (thermometerMeas.pValue != NULL) { // ATT value notification structure. uint8_t *p = thermometerMeas.pValue; // Temperature. uint32_t temperature; // Flags. uint8_t 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; // Temperature is 4 bytes long. *p++ = BREAK_UINT32(temperature, 0); *p++ = BREAK_UINT32(temperature, 1); *p++ = BREAK_UINT32(temperature, 2); *p++ = BREAK_UINT32(temperature, 3); // Timestamp. if (flags & THERMOMETER_FLAGS_TIMESTAMP) { UTCTimeStruct time; // Get time structure from UTC. UTC_convertUTCTime(&time, UTC_getClock()); *p++ = (time.year & 0x00FF); *p++ = (time.year & 0xFF00)>>8; *p++=time.month; *p++=time.day; *p++=time.hour; *p++=time.minutes; *p++=time.seconds; }
/************************************************************************************************** * @fn afRetrieve * * @brief This function retrieves the data of a huge incoming message. On an failure during * the retrieval, the incoming message is freed. Otherwise, the incoming message is * forwarded to the corresponding task. * * input parameters * * @param pMsg - Pointer to the incoming AF message. * @param taskId - The task ID corresponding to the destination endpoint of the message. * * output parameters * * @param pMsg->cmd.Data - The incoming message data buffer member is filled. * * @return None. ************************************************************************************************** */ static void afRetrieve(uint8 taskId, afIncomingMSGPacket_t *pMsg) { #define ZAP_AF_RTV_MSG_HDR 7 // Retrieve message header length. #define ZAP_AF_RTV_RPY_HDR 2 // Retrieve-reply message header length. #define ZAP_AF_RTV_DAT_MAX (MT_RPC_DATA_MAX - ZAP_AF_RTV_RPY_HDR) uint16 idx = 0, len = pMsg->cmd.DataLength; uint8 *pBuf, rtrn, tmpLen = 0; do { /* This trick to pre-decrement (with zero on the first pass) allows the while() test to * succeed and loop to send a zero data length message which will trigger the ZNP to * de-allocate the huge incoming message being held. */ len -= tmpLen; idx += tmpLen; if (len > ZAP_AF_RTV_DAT_MAX) { tmpLen = ZAP_AF_RTV_DAT_MAX; } else { tmpLen = len; } if ((pBuf = zap_msg_allocate(ZAP_AF_RTV_MSG_HDR, ((uint8)MT_RPC_SYS_AF | MT_RPC_CMD_SREQ), MT_AF_DATA_RETRIEVE)) == NULL) { rtrn = afStatus_MEM_FAIL; break; } pBuf[0] = BREAK_UINT32(pMsg->timestamp, 0); pBuf[1] = BREAK_UINT32(pMsg->timestamp, 1); pBuf[2] = BREAK_UINT32(pMsg->timestamp, 2); pBuf[3] = BREAK_UINT32(pMsg->timestamp, 3); pBuf[4] = LO_UINT16(idx); pBuf[5] = HI_UINT16(idx); pBuf[6] = tmpLen; zapPhySend(zapAppPort, pBuf); rtrn = (afStatus_t)ZAP_SRSP_STATUS(pBuf); (void)osal_memcpy(pMsg->cmd.Data+idx, pBuf+ZAP_AF_RTV_RPY_HDR, tmpLen); zap_msg_deallocate(&pBuf); } while ((rtrn == afStatus_SUCCESS) && len); if (rtrn == afStatus_SUCCESS) { (void)osal_msg_send(taskId, (uint8 *)pMsg); } else { (void)osal_msg_deallocate((uint8 *)pMsg); } }
/********************************************************************* * @fn sensorMeasNotify * * @brief Prepare and send a CSC measurement notification * * @return none */ static void sensorMeasNotify( void ) { uint8 *p = sensorMeas.value; uint8 flags = sensorFlags[sensorFlagsIdx]; // Build CSC measurement structure from simulated values // Flags simulate the isPresent bits. *p++ = flags; // If present, add Speed data into measurement if (flags & CSC_FLAGS_SPEED) { *p++ = BREAK_UINT32(cummWheelRevs, 0); *p++ = BREAK_UINT32(cummWheelRevs, 1); *p++ = BREAK_UINT32(cummWheelRevs, 2); *p++ = BREAK_UINT32(cummWheelRevs, 3); *p++ = LO_UINT16(lastWheelEvtTime); *p++ = HI_UINT16(lastWheelEvtTime); // Update simulated values (simulate in the reverse direction) /* if (cummWheelRevs < WHEEL_REV_INCREMENT) //don't allow revolutions to roll over { cummWheelRevs = 0; } else { cummWheelRevs -= WHEEL_REV_INCREMENT; } lastWheelEvtTime += WHEEL_EVT_INCREMENT; */ } // If present, add Cadence data into measurement if (flags & CSC_FLAGS_CADENCE) { *p++ = LO_UINT16(cummCrankRevs); *p++ = HI_UINT16(cummCrankRevs); *p++ = LO_UINT16(lastCrankEvtTime); *p++ = HI_UINT16(lastCrankEvtTime); // Update Simualted Values /* cummCrankRevs += CRANK_REV_INCREMENT; lastCrankEvtTime += CRANK_EVT_INCREMENT; */ } // Get length sensorMeas.len = (uint8) (p - sensorMeas.value); // Send to service to send the notification Cycling_MeasNotify( gapConnHandle, &sensorMeas ); }
/*************************************************************************************************** * @fn MT_UtilAPSME_LinkKeyDataGet * * @brief Proxy the APSME_LinkKeyDataGet() function. * * @param pBuf - pointer to the received buffer * * @return void ***************************************************************************************************/ static void MT_UtilAPSME_LinkKeyDataGet(uint8 *pBuf) { // Status + LinkKeyDataLen + Tx+Rx Frame counter. #define MT_APSME_LINKKEY_GET_RSP_LEN (1 + SEC_KEY_LEN + 4 + 4) uint8 rsp[MT_APSME_LINKKEY_GET_RSP_LEN]; APSME_LinkKeyData_t *pData; uint8 cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; *rsp = APSME_LinkKeyDataGet(pBuf, &pData); if (SUCCESS == *rsp) { uint8 *ptr = rsp+1; (void)osal_memcpy(ptr, pData->key, SEC_KEY_LEN); ptr += SEC_KEY_LEN; *ptr++ = BREAK_UINT32(pData->txFrmCntr, 0); *ptr++ = BREAK_UINT32(pData->txFrmCntr, 1); *ptr++ = BREAK_UINT32(pData->txFrmCntr, 2); *ptr++ = BREAK_UINT32(pData->txFrmCntr, 3); *ptr++ = BREAK_UINT32(pData->rxFrmCntr, 0); *ptr++ = BREAK_UINT32(pData->rxFrmCntr, 1); *ptr++ = BREAK_UINT32(pData->rxFrmCntr, 2); *ptr++ = BREAK_UINT32(pData->rxFrmCntr, 3); } MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_NWK), cmdId, MT_APSME_LINKKEY_GET_RSP_LEN, rsp); }
/*************************************************************************************************** * @fn MT_UtilAPSME_LinkKeyDataGet * * @brief Retrieves APS Link Key data from NV. * * @param pBuf - pointer to the received buffer * * @return void ***************************************************************************************************/ static void MT_UtilAPSME_LinkKeyDataGet(uint8 *pBuf) { uint8 rsp[MT_APSME_LINKKEY_GET_RSP_LEN]; APSME_LinkKeyData_t *pData = NULL; uint8 cmdId = pBuf[MT_RPC_POS_CMD1]; uint16 apsLinkKeyNvId; uint32 *apsRxFrmCntr; uint32 *apsTxFrmCntr; pBuf += MT_RPC_FRAME_HDR_SZ; *rsp = APSME_LinkKeyNVIdGet(pBuf, &apsLinkKeyNvId); if (SUCCESS == *rsp) { pData = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t)); if (pData != NULL) { // retrieve key from NV if ( osal_nv_read( apsLinkKeyNvId, 0, sizeof(APSME_LinkKeyData_t), pData) == SUCCESS) { apsRxFrmCntr = &ApsLinkKeyFrmCntr[apsLinkKeyNvId - ZCD_NV_APS_LINK_KEY_DATA_START].rxFrmCntr; apsTxFrmCntr = &ApsLinkKeyFrmCntr[apsLinkKeyNvId - ZCD_NV_APS_LINK_KEY_DATA_START].txFrmCntr; uint8 *ptr = rsp+1; (void)osal_memcpy(ptr, pData->key, SEC_KEY_LEN); ptr += SEC_KEY_LEN; *ptr++ = BREAK_UINT32(*apsTxFrmCntr, 0); *ptr++ = BREAK_UINT32(*apsTxFrmCntr, 1); *ptr++ = BREAK_UINT32(*apsTxFrmCntr, 2); *ptr++ = BREAK_UINT32(*apsTxFrmCntr, 3); *ptr++ = BREAK_UINT32(*apsRxFrmCntr, 0); *ptr++ = BREAK_UINT32(*apsRxFrmCntr, 1); *ptr++ = BREAK_UINT32(*apsRxFrmCntr, 2); *ptr++ = BREAK_UINT32(*apsRxFrmCntr, 3); } // clear copy of key in RAM osal_memset( pData, 0x00, sizeof(APSME_LinkKeyData_t) ); osal_mem_free(pData); } } else { // set data key and counters 0xFF osal_memset(&rsp[1], 0xFF, SEC_KEY_LEN + (MT_UTIL_FRM_CTR_LEN * 2)); } MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_UTIL), cmdId, MT_APSME_LINKKEY_GET_RSP_LEN, rsp); // clear key data osal_memset(rsp, 0x00, MT_APSME_LINKKEY_GET_RSP_LEN); }
/********************************************************************* * @fn zclApplianceStatistics_Send_LogReq * * @brief Request sent to server for Log Request. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param logID - identifies uniquely the log information contained in log payload * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclApplianceStatistics_Send_LogReq( uint8 srcEP, afAddrType_t *dstAddr, uint32 logID, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buf[4]; // 4 byte payload buf[0] = BREAK_UINT32(logID, 0); buf[1] = BREAK_UINT32(logID, 1); buf[2] = BREAK_UINT32(logID, 2); buf[3] = BREAK_UINT32(logID, 3); return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS, COMMAND_APPLIANCE_STATISTICS_LOG_REQ, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, sizeof( buf ), buf ); }
/*************************************************************************************************** * @fn MT_UtilTimeAlive * * @brief Process Time Alive * * @param None. * * @return None ***************************************************************************************************/ void MT_UtilTimeAlive(void) { uint8 timeAlive[4]; uint32 tmp32; /* Time since last reset (seconds) */ tmp32 = osal_GetSystemClock() / 1000; /* Convert to high byte first into temp buffer */ timeAlive[0] = BREAK_UINT32(tmp32, 0); timeAlive[1] = BREAK_UINT32(tmp32, 1); timeAlive[2] = BREAK_UINT32(tmp32, 2); timeAlive[3] = BREAK_UINT32(tmp32, 3); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_UTIL), MT_UTIL_TIME_ALIVE, sizeof(timeAlive), timeAlive); }
/*************************************************************************************************** * @fn MT_OtaFileReadReq * * @brief Requests a block of a file be read from the remote. * * @param pAddr - The addres of the device requsting the data * @param pFileId - Teh id of the image to read from * @param len - Amount of data to read (must be smaller than the max MT message payload len) * @param offset - The offset into the image to start reading from * * @return status ***************************************************************************************************/ uint8 MT_OtaFileReadReq(afAddrType_t *pAddr, zclOTA_FileID_t *pFileId, uint8 len, uint32 offset) { uint8 msgLen; uint8 *pBuf; uint8 *p; // Check if the requested length is longer than the RX receive buffer if (len + MT_OTA_FILE_READ_RSP_LEN + SPI_0DATA_MSG_LEN > MT_UART_RX_BUFF_MAX) return 0; // Get length msgLen = MT_OTA_FILE_READ_REQ_LEN; // Allocate a buffer if ((p = pBuf = MT_TransportAlloc(0, msgLen)) != NULL) { /* build header */ *p++ = msgLen; *p++ = (uint8) MT_RPC_CMD_AREQ | (uint8) MT_RPC_SYS_OTA; *p++ = MT_OTA_FILE_READ_REQ; // Add the file ID p = OTA_FileIdToStream(pFileId, p); // Add the device address p = OTA_AfAddrToStream(pAddr, p); // File ofset to read from *p++ = BREAK_UINT32(offset, 0); *p++ = BREAK_UINT32(offset, 1); *p++ = BREAK_UINT32(offset, 2); *p++ = BREAK_UINT32(offset, 3); *p = len; // Send command to server MT_TransportSend(pBuf); return ZSuccess; } return ZMemError; }
/********************************************************************* * @fn zclElectricalMeasurement_Send_GetMeasurementProfile * * @brief Call to send out Electrical Measurement Get Measurement Profile. This will * ask the server for the appropriate parameters of the measurement profile. * * @param srcEP - Sending application's endpoint * @param dstAddr - where you want the message to go * @param attributeID - the electricity measurement attribute being profiled * @param startTime - selects the interval block from available interval blocks * @param numberOfIntervals - represents the number of intervals being requested * @param disableDefaultRsp - whether to disable the Default Response command * @param seqNum - sequence number * * @return ZStatus_t */ ZStatus_t zclElectricalMeasurement_Send_GetMeasurementProfile( uint8 srcEP, afAddrType_t *dstAddr, uint16 attributeID, uint32 startTime, uint8 numberOfIntervals, uint8 disableDefaultRsp, uint8 seqNum ) { uint8 buf[7]; // 7 byte payload buf[0] = LO_UINT16(attributeID); buf[1] = HI_UINT16(attributeID); buf[2] = BREAK_UINT32(startTime, 0); buf[3] = BREAK_UINT32(startTime, 1); buf[4] = BREAK_UINT32(startTime, 2); buf[5] = BREAK_UINT32(startTime, 3); buf[6] = numberOfIntervals; return zcl_SendCommand( srcEP, dstAddr, ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT, COMMAND_ELECTRICAL_MEASUREMENT_GET_MEASUREMENT_PROFILE, TRUE, ZCL_FRAME_CLIENT_SERVER_DIR, disableDefaultRsp, 0, seqNum, sizeof(buf), buf ); }
/****************************************************************************** * @fn OTA_FileIdToStream * * @brief Writes a file ID to a stream * * @param pFileId - File ID * pStream - Stream * * @return new stream pointer */ uint8 *OTA_FileIdToStream(zclOTA_FileID_t *pFileId, uint8 *pStream) { if (pStream) { *pStream++ = LO_UINT16(pFileId->manufacturer); *pStream++ = HI_UINT16(pFileId->manufacturer); *pStream++ = LO_UINT16(pFileId->type); *pStream++ = HI_UINT16(pFileId->type); // osal_buffer_uint32 not available under windows //pStream = osal_buffer_uint32(pStream, pFileId->version); *pStream++ = BREAK_UINT32(pFileId->version, 0); *pStream++ = BREAK_UINT32(pFileId->version, 1); *pStream++ = BREAK_UINT32(pFileId->version, 2); *pStream++ = BREAK_UINT32(pFileId->version, 3); } return pStream; }
/********************************************************************* * @fn sensorMeasNotify * * @brief Prepare and send a CSC measurement notification * * @return none */ static void sensorMeasNotify( void ) { attHandleValueNoti_t sensorMeas; sensorMeas.pValue = GATT_bm_alloc( gapConnHandle, ATT_HANDLE_VALUE_NOTI, CSC_MEAS_LEN, NULL ); if ( sensorMeas.pValue != NULL ) { uint8 *p = sensorMeas.pValue; uint8 flags = sensorFlags[sensorFlagsIdx]; // Build CSC measurement structure from simulated values // Flags simulate the isPresent bits. *p++ = flags; // If present, add Speed data into measurement if (flags & CSC_FLAGS_SPEED) { *p++ = BREAK_UINT32(cummWheelRevs, 0); *p++ = BREAK_UINT32(cummWheelRevs, 1); *p++ = BREAK_UINT32(cummWheelRevs, 2); *p++ = BREAK_UINT32(cummWheelRevs, 3); *p++ = LO_UINT16(lastWheelEvtTime); *p++ = HI_UINT16(lastWheelEvtTime); // Update simulated values (simulate in the reverse direction) if (cummWheelRevs < WHEEL_REV_INCREMENT) //don't allow revolutions to roll over { cummWheelRevs = 0; } else { cummWheelRevs -= WHEEL_REV_INCREMENT; } lastWheelEvtTime += WHEEL_EVT_INCREMENT; } // If present, add Cadence data into measurement if (flags & CSC_FLAGS_CADENCE) { *p++ = LO_UINT16(cummCrankRevs); *p++ = HI_UINT16(cummCrankRevs); *p++ = LO_UINT16(lastCrankEvtTime); *p++ = HI_UINT16(lastCrankEvtTime); // Update Simualted Values cummCrankRevs += CRANK_REV_INCREMENT; lastCrankEvtTime += CRANK_EVT_INCREMENT; } // Get length sensorMeas.len = (uint8) (p - sensorMeas.pValue); // Send to service to send the notification if ( Cycling_MeasNotify( gapConnHandle, &sensorMeas ) != SUCCESS ) { GATT_bm_free( (gattMsg_t *)&sensorMeas, ATT_HANDLE_VALUE_NOTI ); } } }
/****************************************************************************** * @fn modbus_insert_msg */ void modbus_insert_msg( uint8 *pBuf, uint8 len) { uint8 index = 0; afAddrType_t destAddr; destAddr.addrMode = afAddr16Bit; destAddr.addr.shortAddr = 0; destAddr.endPoint = 10; signalStrength_t* pSigStren; initCRC16(); // uint8 *pInsertBuf = osal_mem_alloc( modbusDataLength*2); if( firstAddr < 21) index = 45 - 2*firstAddr; else //index = (modbusStartAddr-20)*2 + 1; index = 3; for (uint8 i=0; i<modbusDataLength; i++) { if( i+modbusStartAddr == MODBUS_PANID) { pBuf[index++] = HI_UINT16( _NIB.nwkPanId); pBuf[index++] = LO_UINT16( _NIB.nwkPanId); } else if( i + modbusStartAddr == MODBUS_DEVICE_TYPE) { pBuf[index++] = ZERO; pBuf[index++] = zgDeviceLogicalType; } else if( i + modbusStartAddr == MODBUS_CHANNEL_LIST_HI) { pBuf[index++] = BREAK_UINT32(zgDefaultChannelList, 3); pBuf[index++] = BREAK_UINT32(zgDefaultChannelList, 2); } else if( i + modbusStartAddr == MODBUS_CHANNEL_LIST_LO) { pBuf[index++] = BREAK_UINT32(zgDefaultChannelList, 1); pBuf[index++] = BREAK_UINT32(zgDefaultChannelList, 0); } else if( i + modbusStartAddr == MODBUS_SOFTWARE_REV) { pBuf[index++] = ZERO; pBuf[index++] = ZIG_SOFTWARE_VER; } else if( (i + modbusStartAddr >= MODBUS_EXTENDED_ADDR_HI) && (i + modbusStartAddr <= MODBUS_EXTENDED_ADDR_LO)) { pBuf[index++] = ZERO; pBuf[index++] = aExtendedAddress[ i+modbusStartAddr-MODBUS_EXTENDED_ADDR_HI]; } else if( (i + modbusStartAddr >= MODBUS_SECURITY_KEY_START) && (i + modbusStartAddr <= MODBUS_SECURITY_KEY_END)) { pBuf[index++] = ZERO; pBuf[index++] = defaultKey[ i+modbusStartAddr-MODBUS_SECURITY_KEY_START]; } else if( i + modbusStartAddr == MODBUS_TSTAT_NUM) { pBuf[index++] = ZERO; pBuf[index++] = numSignalStren; } else if( (i + modbusStartAddr >= MODBUS_FIRST_TSTAT_ID) && ( i+ modbusStartAddr <= MODBUS_LAST_TSTAT_ID)) { if( i + modbusStartAddr == MODBUS_FIRST_TSTAT_ID) { pSigStren = pSignalStren; } else { pSigStren = pSignalStren; for( uint8 j=0; j<((i+modbusStartAddr)-MODBUS_FIRST_TSTAT_ID); j++) { if(pSigStren) pSigStren = pSigStren->next; } } pBuf[index++] = ZERO; if(pSigStren != NULL) { pBuf[index++] = pSigStren->modbus_id; } else pBuf[index++] = ZERO; } else if( (i + modbusStartAddr >= MODBUS_FIRST_SIG_STREN) && ( i+ modbusStartAddr <= MODBUS_LAST_SIG_STREN)) { if( i + modbusStartAddr == MODBUS_FIRST_SIG_STREN) { pSigStren = pSignalStren; } else { pSigStren = pSignalStren; for( uint8 j=0; j<((i+modbusStartAddr)-MODBUS_FIRST_SIG_STREN); j++) { if(pSigStren) pSigStren = pSigStren->next; } } pBuf[index++] = ZERO; if(pSigStren != NULL) { pBuf[index++] = pSigStren->rssi; } else pBuf[index++] = ZERO; } else { pBuf[index++] = ZERO; pBuf[index++] = ZERO; } } for( uint8 i=0; i<len-2; i++) CRC16_byte(pBuf[i]); pBuf[len-2] = CRChi; pBuf[len-1] = CRClo; AF_DataRequest( &destAddr, &temco_epDesc, TEMCO_CLUSTERID, len, pBuf, &temcoApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ); modbusStartAddr = 0; modbusDataLength = 0; }
/****************************************************************************** * @fn OTA_WriteHeader * * @brief Writes the OTA header to the output buffer. * * @param pHdr - pointer to the header information * @param pHdr - pointer to the output buffer * * @return none */ uint8 *OTA_WriteHeader(OTA_ImageHeader_t *pHdr, uint8 *pBuf) { uint8 i; // Output the Magic Number // osal_buffer_uint32 not available under windows //pBuf = osal_buffer_uint32(pBuf, pHdr->magicNumber); *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 0); *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 1); *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 2); *pBuf++ = BREAK_UINT32(pHdr->magicNumber, 3); // Output the Header Version *pBuf++ = LO_UINT16(pHdr->headerVersion); *pBuf++ = HI_UINT16(pHdr->headerVersion); // Output the Header Length *pBuf++ = LO_UINT16(pHdr->headerLength); *pBuf++ = HI_UINT16(pHdr->headerLength); // Output the Field Control *pBuf++ = LO_UINT16(pHdr->fieldControl); *pBuf++ = HI_UINT16(pHdr->fieldControl); // Output the Manufacturer ID *pBuf++ = LO_UINT16(pHdr->fileId.manufacturer); *pBuf++ = HI_UINT16(pHdr->fileId.manufacturer); // Output the Image Type *pBuf++ = LO_UINT16(pHdr->fileId.type); *pBuf++ = HI_UINT16(pHdr->fileId.type); // Output the File Version // osal_buffer_uint32 not available under windows //pBuf = osal_buffer_uint32(pBuf, pHdr->fileId.version); *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 0); *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 1); *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 2); *pBuf++ = BREAK_UINT32(pHdr->fileId.version, 3); // Output the Stack Version *pBuf++ = LO_UINT16(pHdr->stackVersion); *pBuf++ = HI_UINT16(pHdr->stackVersion); // Output the Header string for (i=0; i<OTA_HEADER_STR_LEN; i++) { *pBuf++ = pHdr->headerString[i]; } // Output the Image Size // osal_buffer_uint32 not available under windows //pBuf = osal_buffer_uint32(pBuf, pHdr->imageSize); *pBuf++ = BREAK_UINT32(pHdr->imageSize, 0); *pBuf++ = BREAK_UINT32(pHdr->imageSize, 1); *pBuf++ = BREAK_UINT32(pHdr->imageSize, 2); *pBuf++ = BREAK_UINT32(pHdr->imageSize, 3); // Output the Security Credential Version if (pHdr->fieldControl & OTA_FC_SCV_PRESENT) { *pBuf++ = pHdr->secCredentialVer; } // Output the Upgrade File Destination if (pHdr->fieldControl & OTA_FC_DSF_PRESENT) { for (i=0; i<Z_EXTADDR_LEN; i++) { *pBuf++ = pHdr->destIEEE[i]; } } // Output the Min and Max Hardware Versions if (pHdr->fieldControl & OTA_FC_HWV_PRESENT) { *pBuf++ = LO_UINT16(pHdr->minHwVer); *pBuf++ = HI_UINT16(pHdr->minHwVer); *pBuf++ = LO_UINT16(pHdr->maxHwVer); *pBuf++ = HI_UINT16(pHdr->maxHwVer); } return pBuf; }
/****************************************************************************** * @fn modbus_process_msg * * @brief Process modbus message * * @param uint8 - the pointer the buffer * uint8 - length * * @return none */ static void modbus_process_msg( uint8 *data_buffer, uint8 len) { uint8 num, tempByte; uint8 zero = 0; uint16 i; uint16 address; boatMonitor_t *pTempMonitor; UTCTime utcSecs; UTCTimeStruct utcTime; utcSecs = osal_getClock(); osal_ConvertUTCTime( &utcTime, utcSecs ); address = BUILD_UINT16( data_buffer[3], data_buffer[2]); if(( data_buffer[0] == modbus_id) || ( data_buffer[0] == 255)) { if(data_buffer[1] == MODBUS_SINGLE_WRITE) { HalUARTWrite( 0, data_buffer, len); if( address == MODBUS_ADDRESS) { modbus_id = data_buffer[5]; osal_nv_write( ZCD_NV_MODBUS_ID, 0, sizeof(modbus_id), &modbus_id); } if( address == MODBUS_BAUDRATE) { if((data_buffer[5] >=0) &&(data_buffer[5] <= 4)) { modbus_set_baudrate = data_buffer[5]; osal_nv_write( ZCD_NV_BAUDRATE, 0, sizeof(modbus_set_baudrate), &modbus_set_baudrate); restore_factory_setting(); } } } else if( data_buffer[1] == MODBUS_MULTI_WRITE) { if( address == MODBUS_SERIALNUMBER_LOWORD) { if(data_buffer[6] == 8) { for( uint8 k=0;k<4;k++) { ttt[k] = data_buffer[2*k+8]; osal_nv_write( ZCD_NV_SERIAL_NUM, 0, sizeof(ttt), ttt); } } } // write system UTC if( address == MODBUS_SYS_HOUR) { if( data_buffer[6] >= 12) modbus_setUtcTime( &data_buffer[7]); } } else if( data_buffer[1] == MODBUS_SINGLE_READ) { num = data_buffer[5]; uint8 *pBuf; uint8 index=0; pBuf = osal_mem_alloc(num*2+5); if( pBuf != NULL) { pBuf[index++] = data_buffer[0]; pBuf[index++] = data_buffer[1]; pBuf[index++] = num*2; //modbus_send_byte( data_buffer[0], CRC_NO); //modbus_send_byte( data_buffer[1], CRC_NO); //modbus_send_byte( num*2, CRC_NO); for( i = 0; i < num; i++) { if ( i + address <= MODBUS_SERIALNUMBER_LOWORD + 3) { //modbus_send_byte( zero, CRC_NO); pBuf[index++] = zero; pBuf[index++] = ttt[ i + address - MODBUS_SERIALNUMBER_LOWORD]; } else if( i + address == MODBUS_FIRMWARE_VERSION_NUMBER_LO) { pBuf[index++] = zero; pBuf[index++] = ttt[4]; } else if( i + address == MODBUS_FIRMWARE_VERSION_NUMBER_HI) { pBuf[index++] = zero; pBuf[index++] = ttt[5]; } else if( i + address == MODBUS_ADDRESS) { pBuf[index++] = zero; pBuf[index++] = modbus_id; } else if( i + address == MODBUS_PRODUCT_ID) { pBuf[index++] = zero; pBuf[index++] = 210; } // System UTC Time else if( i + address == MODBUS_SYS_HOUR) { pBuf[index++] = zero; pBuf[index++] = utcTime.hour; } else if( i + address == MODBUS_SYS_MINUTES) { pBuf[index++] = zero; pBuf[index++] = utcTime.minutes; } else if( i + address == MODBUS_SYS_SECONDS) { pBuf[index++] = zero; pBuf[index++] = utcTime.seconds; } else if( i + address == MODBUS_SYS_MONTH) { tempByte = utcTime.month + 1; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_SYS_DAY) { tempByte = utcTime.day + 1; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_SYS_YEAR) { tempByte = HI_UINT16( utcTime.year); pBuf[index++] = tempByte; tempByte = LO_UINT16( utcTime.year); pBuf[index++] = tempByte; } /*else if( i + address == MODBUS_WATER_SWITCH) { if(leaveTimeCounter){ tempByte = water_switch; //leaveTimeCounter=0; } else tempByte = zero; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_DETECT_POWER) { uint16 power_temp; if(leaveTimeCounter){ power_temp = (ad_power-196)*10/10.57+90;//(ad_power-186)*100/74+90;//((ad_power-644)*64)/100+70; //leaveTimeCounter = 0; }else power_temp = 0; tempByte = HI_UINT16( power_temp); pBuf[index++] = tempByte; tempByte = LO_UINT16( power_temp); pBuf[index++] = tempByte; } else if( i + address == MODBUS_WATER_ID) { if(leaveTimeCounter){ tempByte = water_id; //leaveTimeCounter=0; } else tempByte = zero; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_WATER_RSSI) { if(leaveTimeCounter){ tempByte = (uint8)water_rssi; } else tempByte = zero; pBuf[index++] = 255; pBuf[index++] = tempByte; } else if( i + address == MODBUS_WATER_SWITCH1) { if(leaveTimeCounter1){ tempByte = water_switch1; //leaveTimeCounter=0; } else tempByte = zero; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_DETECT_POWER1) { uint16 power_temp; if(leaveTimeCounter1){ power_temp = (ad_power1-196)*10/10.57+90;//(ad_power-186)*100/74+90;//((ad_power-644)*64)/100+70; //leaveTimeCounter = 0; }else power_temp = 0; tempByte = HI_UINT16( power_temp); pBuf[index++] = tempByte; tempByte = LO_UINT16( power_temp); pBuf[index++] = tempByte; } else if( i + address == MODBUS_WATER_ID1) { if(leaveTimeCounter1){ tempByte = water_id1; //leaveTimeCounter=0; } else tempByte = zero; pBuf[index++] = zero; pBuf[index++] = tempByte; }*/ else if( i + address == MODBUS_BAUDRATE) { tempByte = modbus_set_baudrate; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_PANID) { tempByte = HI_UINT16( _NIB.nwkPanId); pBuf[index++] = tempByte; tempByte = LO_UINT16( _NIB.nwkPanId); pBuf[index++] = tempByte; } else if( i + address == MODBUS_DEVICE_TYPE) { tempByte = zgDeviceLogicalType; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( i + address == MODBUS_CHANNEL_LIST_HI) { tempByte = BREAK_UINT32(zgDefaultChannelList, 3); pBuf[index++] = tempByte; tempByte = BREAK_UINT32(zgDefaultChannelList, 2); pBuf[index++] = tempByte; } else if( i + address == MODBUS_CHANNEL_LIST_LO) { tempByte = BREAK_UINT32(zgDefaultChannelList, 1); pBuf[index++] = tempByte; tempByte = BREAK_UINT32(zgDefaultChannelList, 0); pBuf[index++] = tempByte; } else if( (i + address >= MODBUS_EXTENDED_ADDR_HI) && (i + address <= MODBUS_EXTENDED_ADDR_LO)) { tempByte = aExtendedAddress[ i+address-MODBUS_EXTENDED_ADDR_HI]; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( (i + address >= MODBUS_SECURITY_KEY_START) && (i + address <= MODBUS_SECURITY_KEY_END)) { tempByte = defaultKey[ i+address-MODBUS_SECURITY_KEY_START]; pBuf[index++] = zero; pBuf[index++] = tempByte; } /*else if( i + address == MODBUS_DETECT_PIN1) { uint16 power_temp; if(leaveTimeCounter){ power_temp = detectPin1; }else power_temp = 0; tempByte = HI_UINT16( power_temp); pBuf[index++] = tempByte; tempByte = LO_UINT16( power_temp); pBuf[index++] = tempByte; } else if( i + address == MODBUS_DETECT_PIN2) { uint16 power_temp; if(leaveTimeCounter){ power_temp = detectPin2; //leaveTimeCounter=0; }else power_temp = 0; tempByte = HI_UINT16( power_temp); pBuf[index++] = tempByte; tempByte = LO_UINT16( power_temp); pBuf[index++] = tempByte; }*/ else if( i + address == MODBUS_MONITOR_NUM) { tempByte = numMonitor; pBuf[index++] = zero; pBuf[index++] = tempByte; } else if( (i + address >= MODBUS_FIRST_MONITOR_ID) && ( i+ address <= MODBUS_LAST_MONITOR_ID)) { if( i + address == MODBUS_FIRST_MONITOR_ID) { pTempMonitor = pBoatMonitor; } else { pTempMonitor = pBoatMonitor; for( uint8 j=0; j<((i+address)-MODBUS_FIRST_MONITOR_ID); j++) { if(pTempMonitor) pTempMonitor = pTempMonitor->next; } } pBuf[index++]= zero; if(pTempMonitor != NULL) { pBuf[index++]= pTempMonitor->modbus_id; } else pBuf[index++]= zero; } else if( (i + address >= MODBUS_FIRST_DETECT_POWER) && ( i+ address <= MODBUS_LAST_DETECT_POWER)) { if( i + address == MODBUS_FIRST_DETECT_POWER) { pTempMonitor = pBoatMonitor; } else { pTempMonitor = pBoatMonitor; for( uint8 j=0; j<((i+address)-MODBUS_FIRST_DETECT_POWER); j++) { if(pTempMonitor) pTempMonitor = pTempMonitor->next; } } if(pTempMonitor != NULL) { uint16 power_temp; power_temp = (pTempMonitor->ad_power-196)*10/10.57+90; tempByte = HI_UINT16( power_temp); pBuf[index++] = tempByte; tempByte = LO_UINT16( power_temp); pBuf[index++] = tempByte; } else { pBuf[index++]= zero; pBuf[index++]= zero; } } else if( (i + address >= MODBUS_FIRST_WATER_SWITCH) && ( i+ address <= MODBUS_LAST_WATER_SWITCH)) { if( i + address == MODBUS_FIRST_WATER_SWITCH) { pTempMonitor = pBoatMonitor; } else { pTempMonitor = pBoatMonitor; for( uint8 j=0; j<((i+address)-MODBUS_FIRST_WATER_SWITCH); j++) { if(pTempMonitor) pTempMonitor = pTempMonitor->next; } } pBuf[index++]= zero; if(pTempMonitor != NULL) { pBuf[index++]= pTempMonitor->water_switch; } else pBuf[index++]= zero; } else if((i + address >= MODBUS_FIRST_DETECT_PIN1) && ( i+ address <= MODBUS_LAST_DETECT_PIN1)) { if( i + address == MODBUS_FIRST_DETECT_PIN1) { pTempMonitor = pBoatMonitor; } else { pTempMonitor = pBoatMonitor; for( uint8 j=0; j<((i+address)-MODBUS_FIRST_DETECT_PIN1); j++) { if(pTempMonitor) pTempMonitor = pTempMonitor->next; } } if(pTempMonitor != NULL) { tempByte = HI_UINT16( pTempMonitor->detectPin1); pBuf[index++] = tempByte; tempByte = LO_UINT16( pTempMonitor->detectPin1); pBuf[index++] = tempByte; } else { pBuf[index++]= zero; pBuf[index++]= zero; } } else if((i + address >= MODBUS_FIRST_DETECT_PIN2) && ( i+ address <= MODBUS_LAST_DETECT_PIN2)) { if( i + address == MODBUS_FIRST_DETECT_PIN2) { pTempMonitor = pBoatMonitor; } else { pTempMonitor = pBoatMonitor; for( uint8 j=0; j<((i+address)-MODBUS_FIRST_DETECT_PIN2); j++) { if(pTempMonitor) pTempMonitor = pTempMonitor->next; } } if(pTempMonitor != NULL) { tempByte = HI_UINT16( pTempMonitor->detectPin2); pBuf[index++] = tempByte; tempByte = LO_UINT16( pTempMonitor->detectPin2); pBuf[index++] = tempByte; } else { pBuf[index++]= zero; pBuf[index++]= zero; } } else if( (i + address >= MODBUS_FIRST_RSSI) && ( i+ address <= MODBUS_LAST_RSSI)) { if( i + address == MODBUS_FIRST_RSSI) { pTempMonitor = pBoatMonitor; } else { pTempMonitor = pBoatMonitor; for( uint8 j=0; j<((i+address)-MODBUS_FIRST_RSSI); j++) { if(pTempMonitor) pTempMonitor = pTempMonitor->next; } } if(pTempMonitor->rssi>=0) pBuf[index++] = 0; else pBuf[index++]= 0xff; if(pTempMonitor != NULL) { pBuf[index++]= pTempMonitor->rssi; } else pBuf[index++]= zero; } else { pBuf[index++] = zero; pBuf[index++] = zero; } } for( i=0; i<num*2+3; i++) CRC16_byte(pBuf[i]); pBuf[num*2+3] = CRChi; pBuf[num*2+4] = CRClo; P1_0 = 1; send_str_Uart( pBuf, num*2+5, 0); P1_0 = 0; osal_mem_free(pBuf); } else{ send_str_Uart( pBuf, num*2+5, 0); } } } }
/********************************************************************* * @fn zclDiagnostic_ReadWriteAttrCB * * @brief Handle Diagnostics attributes. * * @param clusterId - cluster that attribute belongs to * @param attrId - attribute to be read or written * @param oper - ZCL_OPER_LEN, ZCL_OPER_READ, or ZCL_OPER_WRITE * @param pValue - pointer to attribute value, OTA endian * @param pLen - length of attribute value read, native endian * * @return status */ ZStatus_t zclDiagnostic_ReadWriteAttrCB( uint16 clusterId, uint16 attrId, uint8 oper, uint8 *pValue, uint16 *pLen ) { ZStatus_t status = ZSuccess; uint16 tempAttr; uint32 attrValue; afIncomingMSGPacket_t *origPkt; origPkt = zcl_getRawAFMsg(); switch ( oper ) { case ZCL_OPER_LEN: if ( ( attrId == ATTRID_DIAGNOSTIC_LAST_MESSAGE_LQI ) || ( attrId == ATTRID_DIAGNOSTIC_LAST_MESSAGE_RSSI ) ) { *pLen = 1; } else if ( attrId == ATTRID_DIAGNOSTIC_AVERAGE_MAC_RETRY_PER_APS_MESSAGE_SENT ) { *pLen = 2; } // The next function call only returns the length for attributes that are defined // in lower layers else if ( zclDiagnostic_GetAttribData( attrId, &tempAttr, pLen ) != ZSuccess ) { *pLen = 0; status = ZFailure; // invalid length } break; case ZCL_OPER_READ: // Identify if incoming msg is LQI or RSSI attribute // and return the LQI and RSSI of the incoming values if ( attrId == ATTRID_DIAGNOSTIC_LAST_MESSAGE_LQI ) { *pLen = 1; attrValue = origPkt->LinkQuality; } else if ( attrId == ATTRID_DIAGNOSTIC_LAST_MESSAGE_RSSI ) { //origPkt = zcl_getRawAFMsg(); *pLen = 1; attrValue = origPkt->rssi; } else if ( zclDiagnostic_GetStatsAttr( attrId, &attrValue, pLen ) == ZSuccess ) { if ( ( attrId == ATTRID_DIAGNOSTIC_MAC_TX_UCAST_RETRY ) || ( attrId == ATTRID_DIAGNOSTIC_MAC_TX_UCAST_FAIL ) ) { // The lower layer counter is a 32 bit counter, report the higher 16 bit value // util the lower layer counter wraps-up if ( attrValue > 0x0000FFFF ) { attrValue = 0x0000FFFF; } } } else { *pLen = 0; status = ZFailure; // invalid attribute } if ( *pLen == 1 ) { pValue[0] = BREAK_UINT32( attrValue, 0 ); } else if ( *pLen == 2 ) { pValue[0] = LO_UINT16( attrValue ); pValue[1] = HI_UINT16( attrValue ); } else if ( *pLen == 4 ) { pValue[0] = BREAK_UINT32( attrValue, 0 ); pValue[1] = BREAK_UINT32( attrValue, 1 ); pValue[2] = BREAK_UINT32( attrValue, 2 ); pValue[3] = BREAK_UINT32( attrValue, 3 ); } break; case ZCL_OPER_WRITE: status = ZFailure; // All attributes in Diagnostics cluster are READ ONLY break; } return ( status ); }
/*************************************************************************************************** * @fn MT_DebugMacDataDump * * @brief Process the debug MAC Data Dump request. * * @param pBuf - pointer to received buffer * * @return void ***************************************************************************************************/ static void MT_DebugMacDataDump(void) { uint8 buf[sizeof(mtDebugMacDataDump_t)]; uint8 *pBuf = buf; #ifdef FEATURE_PACKET_FILTER_STATS *pBuf++ = BREAK_UINT32(nwkInvalidPackets, 0); *pBuf++ = BREAK_UINT32(nwkInvalidPackets, 1); *pBuf++ = BREAK_UINT32(nwkInvalidPackets, 2); *pBuf++ = BREAK_UINT32(nwkInvalidPackets, 3); *pBuf++ = BREAK_UINT32(rxCrcFailure, 0); *pBuf++ = BREAK_UINT32(rxCrcFailure, 1); *pBuf++ = BREAK_UINT32(rxCrcFailure, 2); *pBuf++ = BREAK_UINT32(rxCrcFailure, 3); *pBuf++ = BREAK_UINT32(rxCrcSuccess, 0); *pBuf++ = BREAK_UINT32(rxCrcSuccess, 1); *pBuf++ = BREAK_UINT32(rxCrcSuccess, 2); *pBuf++ = BREAK_UINT32(rxCrcSuccess, 3); #endif #if defined MAC_RADIO_CC2520 *pBuf++ = macSpiReadReg(FSMSTAT0); *pBuf++ = macSpiReadReg(FSMSTAT1); #else *pBuf++ = FSMSTAT0; *pBuf++ = FSMSTAT1; #endif *pBuf++ = macData.rxCount; *pBuf++ = macData.directCount; *pBuf++ = macMain.state; *pBuf++ = macRxActive; *pBuf = macTxActive; MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_DBG), MT_DEBUG_MAC_DATA_DUMP, sizeof(buf), buf); }
/********************************************************************* * @fn zclApplianceStatistics_LogNotification_NativeToOta * * @brief Converts from native to OTA format. * * @param disableDefaultRsp - whether to disable the Default Response command * @param pZclPayloadLen - returns zcl payload len * * @return pointer to zcl payload */ uint8 *zclApplianceStatistics_LogNotification_NativeToOta( zclCmdApplianceStatisticsLogNotificationPayload_t *pPayload , uint16 * pZclPayloadLen ) { uint8 *pZclPayload; // OTA ZCL payload uint16 zclPayloadLen; // OTA ZCL payload length uint16 i; // get a buffer large enough to hold the whole packet zclPayloadLen = 12 + (uint16)( pPayload->logLength ); // 12=sizeof(TimeStamp) + sizeof(LogID) + sizeof(LogLength) pZclPayload = zcl_mem_alloc( zclPayloadLen ); if( !pZclPayload ) return NULL; // no memory // convert from Native to OTA format pZclPayload[0] = BREAK_UINT32(pPayload->timeStamp, 0); pZclPayload[1] = BREAK_UINT32(pPayload->timeStamp, 1); pZclPayload[2] = BREAK_UINT32(pPayload->timeStamp, 2); pZclPayload[3] = BREAK_UINT32(pPayload->timeStamp, 3); pZclPayload[4] = BREAK_UINT32(pPayload->logID, 0); pZclPayload[5] = BREAK_UINT32(pPayload->logID, 1); pZclPayload[6] = BREAK_UINT32(pPayload->logID, 2); pZclPayload[7] = BREAK_UINT32(pPayload->logID, 3); pZclPayload[8] = BREAK_UINT32(pPayload->logLength, 0); pZclPayload[9] = BREAK_UINT32(pPayload->logLength, 1); pZclPayload[10] = BREAK_UINT32(pPayload->logLength, 2); pZclPayload[11] = BREAK_UINT32(pPayload->logLength, 3); for( i = 0; i < pPayload->logLength; ++i ) pZclPayload[12 + i] = pPayload->pLogPayload[i]; // return payload and length *pZclPayloadLen = zclPayloadLen; return pZclPayload; }
/*************************************************************************************************** * @fn MT_AfIncomingMsg * * @brief Process the callback subscription for AF Incoming data. * * @param pkt - Incoming AF data. * * @return none ***************************************************************************************************/ void MT_AfIncomingMsg(afIncomingMSGPacket_t *pMsg) { uint8 dataLen = pMsg->cmd.DataLength; /* Length of the data section in the response packet */ uint8 respLen = 17 + dataLen; /* Length of the whole response packet */ uint8 cmd = MT_AF_INCOMING_MSG; uint8 *pRsp, *tempPtr; #if defined INTER_PAN if (StubAPS_InterPan(pMsg->srcAddr.panId, pMsg->srcAddr.endPoint)) { cmd = MT_AF_INCOMING_MSG_EXT; } else #endif if (pMsg->srcAddr.addrMode == afAddr64Bit) { cmd = MT_AF_INCOMING_MSG_EXT; } if (cmd == MT_AF_INCOMING_MSG_EXT) { respLen += 9; } // Attempt to allocate memory for the response packet. if ((pRsp = osal_mem_alloc(respLen)) == NULL) { return; } tempPtr = pRsp; /* Fill in the data */ /* Group ID */ *tempPtr++ = LO_UINT16(pMsg->groupId); *tempPtr++ = HI_UINT16(pMsg->groupId); /* Cluster ID */ *tempPtr++ = LO_UINT16(pMsg->clusterId); *tempPtr++ = HI_UINT16(pMsg->clusterId); if (cmd == MT_AF_INCOMING_MSG_EXT) { *tempPtr++ = pMsg->srcAddr.addrMode; if (pMsg->srcAddr.addrMode == afAddr64Bit) { (void)osal_memcpy(tempPtr, pMsg->srcAddr.addr.extAddr, Z_EXTADDR_LEN); } else { tempPtr[0] = LO_UINT16(pMsg->srcAddr.addr.shortAddr); tempPtr[1] = HI_UINT16(pMsg->srcAddr.addr.shortAddr); } tempPtr += Z_EXTADDR_LEN; *tempPtr++ = pMsg->srcAddr.endPoint; #if defined INTER_PAN *tempPtr++ = LO_UINT16(pMsg->srcAddr.panId); *tempPtr++ = HI_UINT16(pMsg->srcAddr.panId); #else *tempPtr++ = 0; *tempPtr++ = 0; #endif } else { /* Source Address */ *tempPtr++ = LO_UINT16(pMsg->srcAddr.addr.shortAddr); *tempPtr++ = HI_UINT16(pMsg->srcAddr.addr.shortAddr); /* Source EP */ *tempPtr++ = pMsg->srcAddr.endPoint; } /* Destination EP */ *tempPtr++ = pMsg->endPoint; /* WasBroadCast */ *tempPtr++ = pMsg->wasBroadcast; /* LinkQuality */ *tempPtr++ = pMsg->LinkQuality; /* SecurityUse */ *tempPtr++ = pMsg->SecurityUse; /* Timestamp */ *tempPtr++ = BREAK_UINT32(pMsg->timestamp, 0); *tempPtr++ = BREAK_UINT32(pMsg->timestamp, 1); *tempPtr++ = BREAK_UINT32(pMsg->timestamp, 2); *tempPtr++ = BREAK_UINT32(pMsg->timestamp, 3); /* Transmit Sequence Number */ *tempPtr++ = pMsg->cmd.TransSeqNumber; /* Data Length */ *tempPtr++ = dataLen; /* Data */ if (dataLen) { osal_memcpy(tempPtr, pMsg->cmd.Data, dataLen); } /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ|(uint8)MT_RPC_SYS_AF), cmd, respLen, pRsp); /* Free memory */ osal_mem_free(pRsp); }
/*************************************************************************************************** * @fn MT_UtilGetNvInfo * * @brief The Get NV Info serial message. * * @param None. * * @return void ***************************************************************************************************/ void MT_UtilGetNvInfo(void) { uint8 len; uint8 stat; uint8 *buf; uint8 *pBuf; uint16 tmp16; uint32 tmp32; /* Get required length of buffer Status + ExtAddr + ChanList + PanID + SecLevel + PreCfgKey */ len = 1 + Z_EXTADDR_LEN + 4 + 2 + 1 + SEC_KEY_LEN; buf = osal_mem_alloc( len ); if ( buf ) { /* Assume NV not available */ osal_memset( buf, 0xFF, len ); /* Skip over status */ pBuf = buf + 1; /* Start with 64-bit extended address */ stat = osal_nv_read( ZCD_NV_EXTADDR, 0, Z_EXTADDR_LEN, pBuf ); if ( stat ) stat = 0x01; pBuf += Z_EXTADDR_LEN; /* Scan channel list (bit mask) */ if ( osal_nv_read( ZCD_NV_CHANLIST, 0, sizeof( tmp32 ), &tmp32 ) ) stat |= 0x02; else { pBuf[0] = BREAK_UINT32( tmp32, 3 ); pBuf[1] = BREAK_UINT32( tmp32, 2 ); pBuf[2] = BREAK_UINT32( tmp32, 1 ); pBuf[3] = BREAK_UINT32( tmp32, 0 ); } pBuf += sizeof( tmp32 ); /* ZigBee PanID */ if ( osal_nv_read( ZCD_NV_PANID, 0, sizeof( tmp16 ), &tmp16 ) ) stat |= 0x04; else { pBuf[0] = LO_UINT16( tmp16 ); pBuf[1] = HI_UINT16( tmp16 ); } pBuf += sizeof( tmp16 ); /* Security level */ if ( osal_nv_read( ZCD_NV_SECURITY_LEVEL, 0, sizeof( uint8 ), pBuf++ ) ) stat |= 0x08; /* Pre-configured security key */ if ( osal_nv_read( ZCD_NV_PRECFGKEY, 0, SEC_KEY_LEN, pBuf ) ) stat |= 0x10; /* Status bit mask - bit=1 indicates failure */ *buf = stat; MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_UTIL), MT_UTIL_GET_NV_INFO, len, buf ); osal_mem_free( buf ); } }
/********************************************************************* * @fn sensorMeasNotify * * @brief Prepare and send a RSC measurement notification * * @return none */ static void sensorMeasNotify(void) { static uint16 centimeters = 0; uint8 *p = sensorMeas.value; uint8 flags = sensorFlags[sensorFlagsIdx]; switch( motion ) { case STANDING_STILL: instSpeed = instCadence = instStrideLength = STANDING_STILL; // 0 for walking bit flags = flags & 0xFB; //0b1111 1011 break; case WALKING_MOTION: instStrideLength = STRIDE_LENGTH_WALKING; instCadence = WALKING_CADENCE; instSpeed = WALKING_SPEED; // 0 for walking bit flags = flags & 0xFB; break; case RUNNING_MOTION: instStrideLength = STRIDE_LENGTH_RUNNING; instCadence = RUNNING_CADENCE; instSpeed = RUNNING_SPEED; // set in 1 for walking bit. flags = flags | 0x04; break; default: // Do nothing break; } // Add distance centimeters += (uint16)DISTANCE_TRAVELED( instSpeed ); // If traveled at least a meter if ( centimeters >= 100 ) { // add distance, truncated to meters totalDistance += (centimeters / 100); // and continue to store the remaining centimeters centimeters %= 100; } // Build RSC measurement structure from simulated values // Flags simulate the isPresent bits. *p++ = flags; //Included regardless of flags. *p++ = LO_UINT16( instSpeed ); *p++ = HI_UINT16( instSpeed ); *p++ = instCadence; if (flags & RSC_FLAGS_STRIDE) { *p++ = LO_UINT16( instStrideLength ); *p++ = HI_UINT16( instStrideLength ); } if (flags & RSC_FLAGS_DIST) { *p++ = BREAK_UINT32(totalDistance, 0); *p++ = BREAK_UINT32(totalDistance, 1); *p++ = BREAK_UINT32(totalDistance, 2); *p++ = BREAK_UINT32(totalDistance, 3); } // Get length sensorMeas.len = (uint8) (p - sensorMeas.value); // Send to service to send the notification Running_MeasNotify( gapConnHandle, &sensorMeas ); }
/*************************************************************************************************** * @fn MT_AfIncomingMsg * * @brief Process the callback subscription for AF Incoming data. * * @param pkt - Incoming AF data. * * @return none ***************************************************************************************************/ void MT_AfIncomingMsg(afIncomingMSGPacket_t *pMsg) { #define MT_AF_INC_MSG_LEN 17 #define MT_AF_INC_MSG_EXT 10 uint16 dataLen = pMsg->cmd.DataLength; // Length of the data section in the response packet. uint16 respLen = MT_AF_INC_MSG_LEN + dataLen; uint8 cmd = MT_AF_INCOMING_MSG; uint8 *pRsp, *pTmp; mtAfInMsgList_t *pItem = NULL; #if defined INTER_PAN if (StubAPS_InterPan(pMsg->srcAddr.panId, pMsg->srcAddr.endPoint)) { cmd = MT_AF_INCOMING_MSG_EXT; } else #endif if ((pMsg->srcAddr.addrMode == afAddr64Bit) || (respLen > (uint16)(MT_RPC_DATA_MAX - MT_AF_INC_MSG_EXT))) { cmd = MT_AF_INCOMING_MSG_EXT; } if (cmd == MT_AF_INCOMING_MSG_EXT) { respLen += MT_AF_INC_MSG_EXT; } if (respLen > (uint16)MT_RPC_DATA_MAX) { if ((pItem = (mtAfInMsgList_t *)osal_mem_alloc(sizeof(mtAfInMsgList_t) + dataLen)) == NULL) { return; // If cannot hold a huge message, cannot give indication at all. } pItem->data = (uint8 *)(pItem+1); respLen -= dataLen; // Zero data bytes are sent with an over-sized incoming indication. } // Attempt to allocate memory for the response packet. if ((pRsp = osal_mem_alloc(respLen)) == NULL) { if (pItem != NULL) { (void)osal_mem_free(pItem); } return; } pTmp = pRsp; /* Group ID */ *pTmp++ = LO_UINT16(pMsg->groupId); *pTmp++ = HI_UINT16(pMsg->groupId); /* Cluster ID */ *pTmp++ = LO_UINT16(pMsg->clusterId); *pTmp++ = HI_UINT16(pMsg->clusterId); if (cmd == MT_AF_INCOMING_MSG_EXT) { *pTmp++ = pMsg->srcAddr.addrMode; if (pMsg->srcAddr.addrMode == afAddr64Bit) { (void)osal_memcpy(pTmp, pMsg->srcAddr.addr.extAddr, Z_EXTADDR_LEN); } else { pTmp[0] = LO_UINT16(pMsg->srcAddr.addr.shortAddr); pTmp[1] = HI_UINT16(pMsg->srcAddr.addr.shortAddr); } pTmp += Z_EXTADDR_LEN; *pTmp++ = pMsg->srcAddr.endPoint; #if defined INTER_PAN *pTmp++ = LO_UINT16(pMsg->srcAddr.panId); *pTmp++ = HI_UINT16(pMsg->srcAddr.panId); #else *pTmp++ = 0; *pTmp++ = 0; #endif } else { /* Source Address */ *pTmp++ = LO_UINT16(pMsg->srcAddr.addr.shortAddr); *pTmp++ = HI_UINT16(pMsg->srcAddr.addr.shortAddr); /* Source EP */ *pTmp++ = pMsg->srcAddr.endPoint; } /* Destination EP */ *pTmp++ = pMsg->endPoint; /* WasBroadCast */ *pTmp++ = pMsg->wasBroadcast; /* LinkQuality */ *pTmp++ = pMsg->LinkQuality; /* SecurityUse */ *pTmp++ = pMsg->SecurityUse; /* Timestamp */ *pTmp++ = BREAK_UINT32(pMsg->timestamp, 0); *pTmp++ = BREAK_UINT32(pMsg->timestamp, 1); *pTmp++ = BREAK_UINT32(pMsg->timestamp, 2); *pTmp++ = BREAK_UINT32(pMsg->timestamp, 3); /* Data Length */ if (cmd == MT_AF_INCOMING_MSG_EXT) { /* Z-Tool apparently takes the last Byte before the data buffer as the dynamic length and * ignores the bigger UInt16 length of an EXT incoming message. But no data bytes will be sent * with a huge message, so it's necessary to work-around and fake-out Z-Tool with a zero here. */ *pTmp++ = 0; // TODO - workaround Z-Tool shortcoming; should be: = pMsg->cmd.TransSeqNumber; *pTmp++ = LO_UINT16(dataLen); *pTmp++ = HI_UINT16(dataLen); } else { *pTmp++ = pMsg->cmd.TransSeqNumber; *pTmp++ = dataLen; } /* Data */ if (pItem != NULL) { // Enqueue the new huge incoming item. pItem->next = pMtAfInMsgList; pMtAfInMsgList = pItem; // Setup to time-out the huge incoming item if host does not MT_AF_DATA_RETRIEVE it. pItem->tick = MT_AF_EXEC_CNT; if (ZSuccess != osal_start_timerEx(MT_TaskID, MT_AF_EXEC_EVT, MT_AF_EXEC_DLY)) { (void)osal_set_event(MT_TaskID, MT_AF_EXEC_EVT); } pItem->timestamp = pMsg->timestamp; (void)osal_memcpy(pItem->data, pMsg->cmd.Data, dataLen); } else { (void)osal_memcpy(pTmp, pMsg->cmd.Data, dataLen); } /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ|(uint8)MT_RPC_SYS_AF), cmd, respLen, pRsp); (void)osal_mem_free(pRsp); }
/********************************************************************* * @fn RunningSensor_measNotify * * @brief Prepare and send a RSC measurement notification. * * @param none * * @return none */ static void RunningSensor_measNotify(void) { static uint16_t centimeters = 0; attHandleValueNoti_t sensorMeas; sensorMeas.pValue = GATT_bm_alloc(gapConnHandle, ATT_HANDLE_VALUE_NOTI, RSC_MEAS_LEN, NULL); if (sensorMeas.pValue != NULL) { uint8_t *p = sensorMeas.pValue; uint8_t flags = sensorFlags[sensorFlagsIdx]; switch(motion) { case STANDING_STILL: instSpeed = instCadence = instStrideLength = STANDING_STILL; // 0 for walking bit. flags = flags & 0xFB; // 0b1111 1011 break; case WALKING_MOTION: instStrideLength = STRIDE_LENGTH_WALKING; instCadence = WALKING_CADENCE; instSpeed = WALKING_SPEED; // 0 for walking bit. flags = flags & 0xFB; break; case RUNNING_MOTION: instStrideLength = STRIDE_LENGTH_RUNNING; instCadence = RUNNING_CADENCE; instSpeed = RUNNING_SPEED; // set in 1 for walking bit. flags = flags | 0x04; break; default: // Do nothing. break; } // Add distance. centimeters += (uint16_t)DISTANCE_TRAVELED(instSpeed); // If travelled at least a meter if (centimeters >= 100) { // Add distance, truncated to meters. totalDistance += (centimeters / 100); // And continue to store the remaining centimeters. centimeters %= 100; } // Build RSC measurement structure from simulated values // Flags simulate the isPresent bits. *p++ = flags; // Included regardless of flags. *p++ = LO_UINT16(instSpeed); *p++ = HI_UINT16(instSpeed); *p++ = instCadence; if (flags & RSC_FLAGS_STRIDE) { *p++ = LO_UINT16(instStrideLength); *p++ = HI_UINT16(instStrideLength); } if (flags & RSC_FLAGS_DIST) { *p++ = BREAK_UINT32(totalDistance, 0); *p++ = BREAK_UINT32(totalDistance, 1); *p++ = BREAK_UINT32(totalDistance, 2); *p++ = BREAK_UINT32(totalDistance, 3); } // Get length. sensorMeas.len = (uint8_t)(p - sensorMeas.pValue); // Send to service to send the notification. if (RunningService_measNotify(gapConnHandle, &sensorMeas) != SUCCESS) { GATT_bm_free((gattMsg_t *)&sensorMeas, ATT_HANDLE_VALUE_NOTI); } } }