/*************************************************************************************************** * @fn MT_SapiSendData * * @brief Process SAPI Send Data Command * * @param pBuf - pointer to received buffer * * @return none ***************************************************************************************************/ void MT_SapiSendData(uint8 *pBuf) { uint8 cmdId; uint16 destination, command; uint8 len, handle, txOption, radius; /* parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; pBuf += MT_RPC_FRAME_HDR_SZ; /* Destination */ destination = BUILD_UINT16(pBuf[0], pBuf[1]); /* Command */ command = BUILD_UINT16(pBuf[2], pBuf[3]); /* Handle */ handle = pBuf[4]; /* txOption */ txOption = pBuf[5]; /* Radius */ radius = pBuf[6]; /* Length */ len = pBuf[7]; zb_SendDataRequest(destination, command, len, &pBuf[8], handle, txOption, radius); /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SAPI), cmdId, 0, NULL); }
/****************************************************************************** * @fn sendReport * * @brief Send sensor report * * @param none * * @return none */ static void sendReport(void) { uint8 pData[SENSOR_REPORT_LENGTH]; static uint8 reportNr=0; uint8 txOptions; // Read and report temperature value pData[SENSOR_TEMP_OFFSET] = readTemp(); // Read and report voltage value pData[SENSOR_VOLTAGE_OFFSET] = readVoltage(); pData[SENSOR_PARENT_OFFSET] = HI_UINT16(parentShortAddr); pData[SENSOR_PARENT_OFFSET + 1] = LO_UINT16(parentShortAddr); // Set ACK request on each ACK_INTERVAL report // If a report failed, set ACK request on next report if ( ++reportNr<ACK_REQ_INTERVAL && reportFailureNr==0 ) { txOptions = AF_TX_OPTIONS_NONE; } else { txOptions = AF_MSG_ACK_REQUEST; reportNr = 0; } // Destination address 0xFFFE: Destination address is sent to previously // established binding for the commandId. zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, SENSOR_REPORT_LENGTH, pData, 0, txOptions, 0 ); }
/****************************************************************************** * @fn sendReport * * @brief Send sensor report * * @param none * * @return none */ static void sendReport(void) { uint8 pData[SENSOR_REPORT_LENGTH]; static uint8 reportNr = 0; uint8 txOptions; // Read and report temperature value pData[SENSOR_TEMP_OFFSET] = readTemp(); // Read and report voltage value pData[SENSOR_VOLTAGE_OFFSET] = readVoltage(); pData[SENSOR_PARENT_OFFSET] = HI_UINT16(parentShortAddr); pData[SENSOR_PARENT_OFFSET + 1] = LO_UINT16(parentShortAddr); pData[BUTTON_PARENT_OFFSET+1] = MCU_IO_GET(0,1); // HalUARTWrite(HAL_UART_PORT_0,pData,SENSOR_REPORT_LENGTH); // HalUARTWrite(HAL_UART_PORT_1,pData,SENSOR_REPORT_LENGTH); int test = MCU_IO_GET(0,1); if( MCU_IO_GET(0,1) > 0){ MCU_IO_SET_LOW(0, 0); } else { MCU_IO_SET_HIGH(0, 0); } MCU_IO_SET_LOW(0, 1); // Set ACK request on each ACK_INTERVAL report // If a report failed, set ACK request on next report if ( ++reportNr<ACK_REQ_INTERVAL && reportFailureNr == 0 ) { txOptions = AF_TX_OPTIONS_NONE; } else { txOptions = AF_MSG_ACK_REQUEST; reportNr = 0; } // Destination address 0xFFFE: Destination address is sent to previously // established binding for the commandId. //printf("%i %i",pData[SENSOR_TEMP_OFFSET],oldValue); if(timeDone >= 60000){ timeDone += 1; } if(pData[SENSOR_TEMP_OFFSET] != oldValue && timeDone >= 60000){ oldValue = pData[SENSOR_TEMP_OFFSET]; zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, SENSOR_REPORT_LENGTH, pData, 0, txOptions, 0 ); timeDone = 0; } else { timeDone += myReportPeriod; } }
/****************************************************************************** * @fn sendCommand * * @brief Sends a command message via Zigbee * * @param command - uint8 containing the command bit * * @return none */ void sendCommand ( uint8 command ) { uint8 pData[1]; static uint8 reportNr = 0; uint8 txOptions; pData[0] = command; if ( ++reportNr < ACK_REQ_INTERVAL && reportFailureNr == 0 ) { txOptions = AF_TX_OPTIONS_NONE; } else { txOptions = AF_MSG_ACK_REQUEST; reportNr = 0; } zb_SendDataRequest( 0xFFFE, ROUTER_REPORT_CMD_ID, 1, pData, 0, txOptions, 0 ); }
/* * This routine send data originated by the user layer to * the Z-Accel. */ void zaccel_xmt(struct work_struct *work) { struct bmi_zb *zb; struct zaccel_info *z_info; struct zaccel_xmt_msg *msg; zb = container_of(work, struct bmi_zb, xmt_work); z_info = &zb->z_info; while(!list_empty(&z_info->xmt_list)) { msg = list_entry(z_info->xmt_list.next, struct zaccel_xmt_msg, list); zb_SendDataRequest(zb, msg->buf, msg->len); list_del(z_info->xmt_list.next); kfree(msg); } }
/** * @brief Este callback es llamado asincrónicamente por el stack de ZigBee * para notificar a la aplicación que se recibieron datos, enviados * por otro nodo de la red. * @param source Short Address (NWK) del nodo que envío los datos. * @param command ID del comando asociado con los datos. * @param len Cantidad de bytes del parámetro pData. * @param pData Puntero al inicio de los datos envíados por el nodo. */ void zb_ReceiveDataIndication(uint16 source, uint16 command, uint16 len, uint8 *pData) { // imprime la dirección fuente en el display HalLcdWriteStringValue("RCB", source, 16, 1); // flashea el LED 2 para indicar que se recibió un mensaje HalLedSet(HAL_LED_2, HAL_LED_MODE_FLASH); // deserealiza mensaje recibido msgReport = deserializeMessage(pData); if (msgReport.msgType == MSG_TYPE_REPORT) { HalLcdWriteStringValue("#", msgReport.sequence, 10, 2); // verifica condiciones de alarmas alarmFlags = checkAlarms(&msgReport); // imprime alarma en LCD //HalLcdWriteStringValue("ALARM", alarmFlags, 16, 2); if (alarmFlags != 0) { // crea paquete de respuesta con igual MAC y nº de secuencia struct message_t msgAlarm; msgAlarm.sequence = msgReport.sequence; memcpy(&(msgAlarm.mac), &(msgReport.mac), sizeof(msgReport.mac)); msgAlarm.msgType = MSG_TYPE_ALARM; msgAlarm.lenData = MSG_LEN_DATA_ALARM; // flags en little-endian msgAlarm.data[0] = LO_UINT16(alarmFlags); msgAlarm.data[1] = HI_UINT16(alarmFlags); // serializa mensaje y lo envía serializeMessage(&(msgAlarm), msgBuf); zb_SendDataRequest(source, MESSAGE_CLUSTER, getSizeOfMessage(&(msgAlarm)), msgBuf, 0, AF_TX_OPTIONS_NONE, 0); } // crea evento para enviar el reporte por UART a la PC, añandiendo // los flags osal_start_timerEx(sapi_TaskID, SEND_UART_MSG, 0); } }
/********************************************************************* * @fn temcoApp_MessageMSGCB */ static void temcoApp_MessageMSGCB(afIncomingMSGPacket_t *pkt) { switch(pkt->clusterId) { case TEMCO_CLUSTERID: if( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER) // Prepare to insert modbus message into TSTAT's { if( (pkt->cmd.Data[1] == MODBUS_SINGLE_READ) && (pkt->cmd.DataLength == 8)) { firstAddr = BUILD_UINT16(pkt->cmd.Data[3],pkt->cmd.Data[2]); uint8 length = pkt->cmd.Data[5]; if( (firstAddr<21)&&((firstAddr+length)>21)) { modbusDataLength = firstAddr+length-21; modbusStartAddr = 21; } else if( (firstAddr>=21) && (firstAddr <100)) { modbusStartAddr = firstAddr; if(length <= (101-firstAddr)) modbusDataLength = length; else modbusDataLength = 101-firstAddr; } else { modbusStartAddr = 0; modbusDataLength = 0; } } else if( pkt->cmd.Data[1] == MODBUS_SINGLE_WRITE) { modbus_single_write(pkt->cmd.Data, pkt->cmd.DataLength); } else if( pkt->cmd.Data[1] == MODBUS_MULTI_WRITE) { modbus_multi_write(pkt->cmd.Data, pkt->cmd.DataLength); } } HalUARTWrite ( 0, pkt->cmd.Data, pkt->cmd.DataLength ); break; case ACK_CMD_CLUSTERID: // 7/16取消修改 此处改为定时发广播,收到任何节点消息,不论对方类型,都不需要重启 if(zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { uint8 ack_byte = 1; zb_SendDataRequest( pkt->srcAddr.addr.shortAddr, ACK_CMD_CLUSTERID, 1, &ack_byte, 0, AF_ACK_REQUEST, 0); } else { if(pkt->cmd.Data[0] == 1) ack_exist = TRUE; } break; case RSSI_REQ_CLUSTERID: if( pkt->cmd.Data[0] == 0) { if( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { zb_SendDataRequest( pkt->srcAddr.addr.shortAddr, RSSI_RSP_CLUSTERID, 1, &tstat_id, 0, AF_ACK_REQUEST, 0); } else { if( tstat_id != 0) zb_SendDataRequest( pkt->srcAddr.addr.shortAddr, RSSI_RSP_CLUSTERID, 1, &tstat_id, 0, AF_ACK_REQUEST, 0); } } break; case RSSI_RSP_CLUSTERID: if( pkt->cmd.Data[0] != 0) { signalStrength_t *pInSignal; pInSignal = findSignalStrength( pkt->cmd.Data[0]); if( pInSignal != NULL) { pInSignal->rssi = pkt->rssi; pInSignal->leaveTime = 0; } else { register_signalStrength( pkt->cmd.Data[0], pkt->rssi); numSignalStren++; } } break; default: break; } }
/********************************************************************* * @fn temcoApp_ProcessEvent */ uint16 temcoApp_ProcessEvent(uint8 task_id, uint16 events) { osal_event_hdr_t *pMsg; afIncomingMSGPacket_t *pMSGpkt; if( events & SYS_EVENT_MSG) { pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id ); while(pMsg) { switch( pMsg->event) { case AF_INCOMING_MSG_CMD: pMSGpkt = (afIncomingMSGPacket_t *)pMsg; temcoApp_MessageMSGCB(pMSGpkt); break; case ZDO_STATE_CHANGE: if (pMsg->status == DEV_END_DEVICE || pMsg->status == DEV_ROUTER ) //||pMsg->status == DEV_ZB_COORD ) { osal_set_event( temcoAPP_TaskID, ACK_CHECK); // HalLedSet ( HAL_LED_1, HAL_LED_MODE_FLASH ); // HalLedBlink ( HAL_LED_1, 0, 50, 500 ); } break; default: break; } // Release the memory osal_msg_deallocate( (uint8 *) pMsg ); // Next pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id ); } // Return unprocessed events return (events ^ SYS_EVENT_MSG); } if (events & ACK_CHECK) { uint8 ack_byte = 0; if( ack_count > ACK_TIMEOUT_NUM) { ack_count = 0; if( ack_exist == FALSE) { restore_factory_setting(); } } if( ack_exist == TRUE) { zb_SendDataRequest( 0, ACK_CMD_CLUSTERID, 1, &ack_byte, 0, AF_ACK_REQUEST, 0); ack_exist = FALSE; } ack_count ++; osal_start_timerEx( temcoAPP_TaskID, ACK_CHECK, ACK_CHECK_TIMEOUT); // Every minute check ack, if no receive, restart to join a new network return ( events ^ ACK_CHECK); } // Send the command to check TSTAT modbus id if( events & ASK_MODBUS_ID) { uint8 rssi_byte = 0; uint8 deleteId; if( type_assert >= TYPE_ASSERT_TIMEOUT) // Decide which type to start up { #if 0 if( (product_id == 0) || (product_id == 100)) { if( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER) { zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; restart_to_other_type(); } } else { if( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) { zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; restart_to_other_type(); } } #endif // To read register6 of TSTAT if( tstat_id != 0) { //if( zgDeviceLogicalType != ZG_DEVICETYPE_COORDINATOR) // Send a command asking other nodes' modbus id, the response message carry rssi zb_SendDataRequest( 0xffff, RSSI_REQ_CLUSTERID, 1, &rssi_byte, 0, AF_ACK_REQUEST, 0); deleteId = checkNodeAlive(); // check if there are any nodes not alive if( deleteId != 255) deleteSignalStrength(deleteId); // delete the dead id } } else { type_assert ++; HalUARTWrite ( 0, ask_modbus_id, 8 ); } // if not received, send again X seconds later osal_start_timerEx( temcoAPP_TaskID, ASK_MODBUS_ID, RSSI_REQ_TIMEOUT); return ( events ^ ASK_MODBUS_ID); } if( events & SEND_ZIGBEE_FLAG) { if( tstat_id == 0) HalUARTWrite( 0, "zigbee", strlen("zigbee")); else osal_stop_timerEx( temcoAPP_TaskID, SEND_ZIGBEE_FLAG); osal_start_timerEx( temcoAPP_TaskID, SEND_ZIGBEE_FLAG, 3000); } // Discard unknown events return 0; }