/** Parse any received messages. If it's one of our OIDs then display it. */ void parseMessages() { getMessage(); if ((zmBuf[SRSP_LENGTH_FIELD] > 0) && (IS_AF_INCOMING_MESSAGE())) { setLed(0); //LED will blink to indicate a message was received #ifdef VERBOSE_MESSAGE_DISPLAY printAfIncomingMsgHeader(zmBuf); printf("\r\n"); #endif if ((AF_INCOMING_MESSAGE_CLUSTER()) == INFO_MESSAGE_CLUSTER) { processInfoMessage(); } else if ((AF_INCOMING_MESSAGE_CLUSTER()) == CONFIG_REQUEST_MESSAGE_CLUSTER) { processConfigRequestMessage(); } else { //unknown cluster printf("Rx: "); printHexBytes(zmBuf+SRSP_HEADER_SIZE+17, zmBuf[SRSP_HEADER_SIZE+16]); //print out message payload } clearLed(0); } else if (IS_ZDO_END_DEVICE_ANNCE_IND()) { displayZdoEndDeviceAnnounce(zmBuf); } else { //unknown message, just print out the whole thing printf("MSG: "); printHexBytes(zmBuf, (zmBuf[SRSP_LENGTH_FIELD] + SRSP_HEADER_SIZE)); } zmBuf[SRSP_LENGTH_FIELD] = 0; }
void displayMessages() { spiPoll(); if (znpBuf[SRSP_LENGTH_FIELD] > 0) { if (IS_AF_INCOMING_MESSAGE()) { setLed(1); //LED will blink to indicate a message was received #ifdef VERBOSE_MESSAGE_DISPLAY printAfIncomingMsgHeader(znpBuf); printf("\r\n"); #endif if (IS_INFO_MESSAGE_CLUSTER()) { struct infoMessage im = deserializeInfoMessage(znpBuf+20); #ifdef VERBOSE_MESSAGE_DISPLAY printInfoMessage(&im); #else printf("From:"); for (int j = 0; j<8; j++) { printf("%02X", im.header->mac[j]); } printf(",LQI=%02X", znpBuf[SRSP_HEADER_SIZE+9]); #endif if (im.numParameters > 0) { printf(";PanID:%04X", im.parameters[0]); if (im.numParameters == 3) //panId, vcc3v, light sensor (lux/10) { printf(",Vcc3=%umV,Light Sensor(lux)=%u,Cause=", im.parameters[1], im.parameters[2] * 10); switch (im.cause) { case CAUSE_SCHEDULED: printf("Timer"); break; case CAUSE_MOTION: printf("Motion"); break; case CAUSE_STARTUP: printf("Startup"); break; } } printf("\r\n"); } } else { printf("Rx: "); printHexBytes(znpBuf+SRSP_HEADER_SIZE+17, znpBuf[SRSP_HEADER_SIZE+16]); //print out message payload } clearLeds(); } else { //unknown message, just print out the whole thing printf("??: "); printHexBytes(znpBuf, (znpBuf[SRSP_LENGTH_FIELD] + SRSP_HEADER_SIZE)); } znpBuf[SRSP_LENGTH_FIELD] = 0; } }
/** Public method to send messages to the Module. This will send one message and then receive the Synchronous Response (SRSP) message from the Module to indicate the command was received. @pre zmBuf contains a properly formatted message @pre Module has been initialized @post buffer zmBuf contains the response (if any) from the Module. */ moduleResult_t sendMessage() { #ifdef ZM_PHY_SPI_VERBOSE printf("Tx: "); printHexBytes(zmBuf, zmBuf[0] + 3); #endif uint8_t expectedSrspCmdMsb = zmBuf[1] + SRSP_OFFSET; //store these so we can compare with what is returned uint8_t expectedSrspCmdLsb = zmBuf[2]; moduleResult_t result = sendSreq(); //send message, buffer now holds received data if (result != MODULE_SUCCESS) //ERROR - sendSreq() timeout { #ifdef ZM_PHY_SPI_VERBOSE_ERRORS printf("ERROR - sreq() timeout %02X\r\n", result); #endif return result; } /* The correct SRSP will always be 0x4000 + cmd, or simpler 0x4000 | cmd For example, if the SREQ is 0x2605 then the corresponding SRSP is 0x6605 */ if ((zmBuf[SRSP_CMD_MSB_FIELD] == expectedSrspCmdMsb) && (zmBuf[SRSP_CMD_LSB_FIELD] == expectedSrspCmdLsb)) //verify the correct SRSP was received { return MODULE_SUCCESS; } else { #ifdef ZM_PHY_SPI_VERBOSE_ERRORS printf("ERROR - Wrong SRSP - received %02X-%02X, expected %02X-%02X\r\n", zmBuf[1], zmBuf[2],expectedSrspCmdMsb,expectedSrspCmdLsb); #endif return ZM_PHY_INCORRECT_SRSP; //Wrong SRSP received } }
void testLong2bigEndian() { unsigned long val = 945985565902; unsigned char buf[8]={0}; long2bigEndian(buf,val); printHexBytes("buf:",buf, 8); }
/** Requests a device's Short Address for a given long address. @param ieeeAddress the long address to locate @param requestType must be SINGLE_DEVICE_RESPONSE or INCLUDE_ASSOCIATED_DEVICES. If SINGLE_DEVICE_RESPONSE is selected, then only information about the requested device will be returned. If INCLUDE_ASSOCIATED_DEVICES is selected, then the short addresses of the selected device's children will be returned too. @param startIndex If INCLUDE_ASSOCIATED_DEVICES was selected, then there may be too many children to fit in one ZDO_NWK_ADDR_RSP message. So, use startIndex to get the next set of children's short addresses. @note DOES NOT WORK FOR SLEEPING END DEVICES @post An ZDO_NWK_ADDR_RSP message will be received, with one or more entries. @return a pointer to the beginning of the payload, or a pointer to indeterminate data if error. @post znpResult contains the error code, or ZNP_SUCCESS if success. */ unsigned char* zdoNetworkAddressRequest(unsigned char* ieeeAddress, unsigned char requestType, unsigned char startIndex) { if ((requestType != SINGLE_DEVICE_RESPONSE) && (requestType != INCLUDE_ASSOCIATED_DEVICES)) { znpResult = -1; return 0; } #ifdef AF_ZDO_VERBOSE printf("Requesting Network Address for long address "); printHexBytes(ieeeAddress, 8); printf("requestType %s, startIndex %u\r\n", (requestType == 0) ? "Single" : "Extended", startIndex); #endif znpBuf[0] = ZDO_NWK_ADDR_REQ_PAYLOAD_LEN; znpBuf[1] = MSB(ZDO_NWK_ADDR_REQ); znpBuf[2] = LSB(ZDO_NWK_ADDR_REQ); memcpy(znpBuf+3, ieeeAddress, 8); znpBuf[11] = requestType; znpBuf[12] = startIndex; znpResult = sendMessage(); if (znpResult != 0) return 0; znpResult = waitForMessage(ZDO_NWK_ADDR_RSP, 5); if (znpResult != 0) return 0; if (znpBuf[SRSP_PAYLOAD_START] != SRSP_STATUS_SUCCESS) //verify status is succes { znpResult = -2; return 0; } return (znpBuf + SRSP_PAYLOAD_START); }
int main( void ) { halInit(); moduleInit(); printf("\r\nWriting NV Items\r\n"); result = moduleReset(); if (result == MODULE_SUCCESS) { displaySysResetInd(); // Display the contents of the received SYS_RESET_IND message } else { printf("Module Reset ERROR 0x%02X\r\n", result); } debugConsoleIsr = &handleDebugConsoleInterrupt; //call method handleDebugConsoleInterrupt() when a byte is received HAL_ENABLE_INTERRUPTS(); //Enable Interrupts while (1) { uint8_t whichNvItem = getWhichNvItemToWrite(); if (whichNvItem != NO_CHARACTER_RECEIVED) { uint8_t nvItemSize = getNvItemSize(whichNvItem); printf("\r\nWriting to NV item %u, L%u:", whichNvItem, nvItemSize); printHexBytes(dataToWrite, nvItemSize); result = sysNvWrite(whichNvItem, dataToWrite); if (result != MODULE_SUCCESS) { printf("sysNvWrite ERROR 0x%02X\r\n", result); } } } }
/** Utility method to display stored network configuration parameters. These are the configuration parameters stored in NV memory and are used to initialize the ZNP. @post znpResult contains the error code, or ZNP_SUCCESS if success. */ void getNetworkConfigurationParameters() { printf("ZNP Configuration Parameters\r\n"); unsigned char* param; param = getConfigurationParameter(ZCD_NV_PANID); if (znpResult != 0) return; printf(" ZCD_NV_PANID %04X\r\n", (CONVERT_TO_INT(param[0], param[1]))); param = getConfigurationParameter(ZCD_NV_CHANLIST); if (znpResult != 0) return; printf(" ZCD_NV_CHANLIST %02X %02X %02X %02X\r\n", param[0], param[1], param[2], param[3]); param = getConfigurationParameter(ZCD_NV_SECURITY_MODE); if (znpResult != 0) return; printf(" ZCD_NV_SECURITY_MODE %02X\r\n", param[0]); param = getConfigurationParameter(ZCD_NV_PRECFGKEYS_ENABLE); if (znpResult != 0) return; printf(" ZCD_NV_PRECFGKEYS_ENABLE %02X\r\n", param[0]); param = getConfigurationParameter(ZCD_NV_PRECFGKEY); if (znpResult != 0) return; printf(" ZCD_NV_PRECFGKEY "); printHexBytes(param, ZCD_NV_PRECFGKEY_LEN); }
int main( void ) { halInit(); moduleInit(); printf("\r\nResetting Module, then getting MAC Address\r\n"); HAL_ENABLE_INTERRUPTS(); result = moduleReset(); if (result == MODULE_SUCCESS) { /* Display the contents of the received SYS_RESET_IND message */ displaySysResetInd(); } else { printf("ERROR 0x%02X\r\n", result); } while (1) { result = zbGetDeviceInfo(DIP_MAC_ADDRESS); if (result == MODULE_SUCCESS) { uint8_t* mac = zmBuf+SRSP_DIP_VALUE_FIELD; printf("MAC (as sent, LSB first):"); printHexBytes(mac, 8); /* Note: the MAC address comes over the wire in reverse order (LSB first) So we swap the order of the bytes so we can display it correctly. */ uint8_t temp[8]; int i; for (i=0; i<8; i++) { temp[i] = mac[7-i]; } printf("MAC (correct, MSB first):"); printHexBytes(temp, 8); printf("\r\n"); } else { printf("ERROR 0x%02X\r\n", result); } toggleLed(1); delayMs(1000); } }
/** Poll the ZNP for any messages and display them to the console. @pre SRDY went LOW indicating data is ready */ void pollAndDisplay() { spiPoll(); if (znpBuf[SRSP_LENGTH_FIELD] > 0) { printf("Rx: "); printHexBytes(znpBuf, (znpBuf[SRSP_LENGTH_FIELD] + SRSP_HEADER_SIZE)); znpBuf[SRSP_LENGTH_FIELD] = 0; } }
/** Loads the specified key into the ZNP. Does not change security mode, need to use setSecurityMode() too. @note if NOT using pre-configured keys then the coordinator will distribute its key to all devices. @param key preConfiguredKey a 16B key to use @pre setSecurityMode() called @post znpResult contains the error code, or ZNP_SUCCESS if success. */ void setSecurityKey(unsigned char* key) { #ifdef ZNP_INTERFACE_VERBOSE printf("Setting Security Key: "); printHexBytes(key, ZCD_NV_PRECFGKEY_LEN); #endif znpBuf[0] = ZB_WRITE_CONFIGURATION_LEN + ZCD_NV_PRECFGKEY_LEN; znpBuf[1] = MSB(ZB_WRITE_CONFIGURATION); znpBuf[2] = LSB(ZB_WRITE_CONFIGURATION); znpBuf[3] = ZCD_NV_PRECFGKEY; znpBuf[4] = ZCD_NV_PRECFGKEY_LEN; for (int i=5; i<(ZCD_NV_PRECFGKEY_LEN+5); i++) znpBuf[i] = key[i]; znpResult = sendMessage(); }
/** Public method to send messages to the ZNP. This will send one message and then receive the Synchronous Response (SRSP) message from the ZNP to indicate the command was received. @pre znpBuf contains a properly formatted message @pre ZNP has been initialized @post buffer znpBuf contains the response (if any) from the ZNP. @return 0 if the SRSP received was the expected SRSP, -11 if it was NOT the expected SRSP, -12 if sendSreq timeout, or -13 if too many bytes received. */ signed int sendMessage() { #ifdef ZNP_INTERFACE_SPI_VERBOSE printf("Tx: "); printHexBytes(znpBuf, znpBuf[0] + 3); #endif unsigned char expectedSrspCmdMsb = znpBuf[1] + 0x40; unsigned char expectedSrspCmdLsb = znpBuf[2]; signed int result = sendSreq(); //send message, buffer now holds received data if (result != 0) //ERROR - spiSreq() timeout { #ifdef ZNP_INTERFACE_SPI_VERBOSE printf("ERROR - sreq() timeout %i\r\n", result); #endif return -12; } if (znpBuf[0] > SRSP_BUFFER_SIZE) //Error - SRSP length exceeds buffer size { #ifdef ZNP_INTERFACE_SPI_VERBOSE printf("ERROR - SRSP too long %u > %u\r\n", znpBuf[0], SRSP_BUFFER_SIZE); #endif return -13; } //The correct SRSP will always be 0x4000 + cmd, or simpler 0x4000 | cmd //For example, if the SREQ is 0x2605 then the corresponding SRSP is 0x6605 if ((znpBuf[1] == expectedSrspCmdMsb) && (znpBuf[2] == expectedSrspCmdLsb)) //verify the correct SRSP was received return 0; else { #ifdef ZNP_INTERFACE_SPI_VERBOSE printf("ERROR - Wrong SRSP - received %02X-%02X, expected %02X-%02X\r\n", znpBuf[1], znpBuf[2],expectedSrspCmdMsb,expectedSrspCmdLsb); #endif return -11; //Wrong SRSP received } }
/** Waits for SRDY to go low, indicating a message has arrived. Displays the msg to console, and find the device's MAC address using ZDO_IEEE_ADDR_REQ. Then, if FIND_NWK_ADDRESS was defined, uses the received MAC address to find the device's short address. The two should match. @pre callbacks have been enabled with enableCallbacks() - otherwise you will never receive the ZDO_IEEE_ADDR_RSP message. */ void displayReceivedMessagesAndFindDevice() { znpBuf[0] = 0; unsigned int shortAddress; while (1) { while (SRDY_IS_HIGH()); pollAndDisplay(); if (CONVERT_TO_INT(znpBuf[2], znpBuf[1]) == AF_INCOMING_MSG) { shortAddress = CONVERT_TO_INT(znpBuf[7], znpBuf[8]); zdoRequestIeeeAddress(shortAddress, SINGLE_DEVICE_RESPONSE, 0); if (znpResult == 0) { printf("MAC Address (LSB first) of sender is :"); printHexBytes(znpBuf+4, 8); } else { printf("IEEE Request Failed (%d)\r\n", znpResult); continue; } #ifdef FIND_NWK_ADDRESS /** Very simple example of zdoNetworkAddressRequest() */ unsigned char* response = zdoNetworkAddressRequest(znpBuf+4, SINGLE_DEVICE_RESPONSE, 0); //was SINGLE_DEVICE_RESPONSE if (znpResult == 0) { unsigned int sa = CONVERT_TO_INT(znpBuf[12], znpBuf[13]); printf("Short Address = %04X\r\n", sa); } else { printf("NWK Request Failed (%d)\r\n", znpResult); continue; } printZdoNetworkAddressResponse(response); #endif } } }
/** Writes the specified Non-Volatile (NV) memory item to the ZNP. The contents of the selected nvItem will be overwritten from memory starting at data. @pre ZNP was initialized. @param nvItem which nvItem to write, 1 through 6 inclusive @param data the data to write @post znpResult contains the error code, or ZNP_SUCCESS if success. */ void writeNvItem(unsigned char nvItem, unsigned char* data) { if ((nvItem < MIN_NV_ITEM) || (nvItem > MAX_NV_ITEM)) { znpResult = -1; return; } unsigned char nvItemSize = getNvItemSize(nvItem); #ifdef ZNP_INTERFACE_VERBOSE printf("Writing NV Item %u (length %u) with data: ", nvItem, nvItemSize); printHexBytes(data, nvItemSize); #endif znpBuf[0] = SYS_OSAL_NV_WRITE_PAYLOAD_LEN + nvItemSize; znpBuf[1] = MSB(SYS_OSAL_NV_WRITE); znpBuf[2] = LSB(SYS_OSAL_NV_WRITE); znpBuf[3] = nvItem; //item number, 1-6 znpBuf[4] = 0x0F; //MSB of item number, but only items 1-6 are supported znpBuf[5] = 0; //offset from beginning of the NV item, not used znpBuf[6] = nvItemSize; //length memcpy(znpBuf+7, data, nvItemSize); znpResult = sendMessage(); }
static void stateMachine() { while (1) { if (zigbeeNetworkStatus == NWK_ONLINE) { if(moduleHasMessageWaiting()) //wait until SRDY goes low indicating a message has been received. displayMessages(); } switch (state) { case STATE_IDLE: { /* process command line commands only if not doing anything else: */ if (command != NO_CHARACTER_RECEIVED) { /* parse the command entered, and go to the required state */ state = processCommand(command); command = NO_CHARACTER_RECEIVED; } /* note: other flags (for different messages or events) can be added here */ break; } case STATE_INIT: { printf("Starting State Machine\r\n"); state = STATE_GET_DEVICE_TYPE; break; } /* A button press during startup will cause the application to prompt for device type */ case STATE_GET_DEVICE_TYPE: { //printf("Current Configured DeviceType: %s\r\n", getDeviceTypeName()); set_type: /* if saving device type to flash memory: printf("Any other key to exit. Timeout in 5 seconds.\r\n"); / long wait = 0; long timeout = TICKS_IN_ONE_MS * 5000l; while ((command == NO_CHARACTER_RECEIVED) && (wait != timeout)) wait++; */ while (command == NO_CHARACTER_RECEIVED) { printf("Setting Device Type: Press C for Coordinator, R for Router, or E for End Device.\r\n"); delayMs(2000); } switch (command) { case 'C': case 'c': printf("Coordinator it is...\r\n"); zigbeeDeviceType = COORDINATOR; break; case 'R': case 'r': printf("Router it is...\r\n"); zigbeeDeviceType = ROUTER; break; case 'E': case 'e': printf("End Device it is...\r\n"); zigbeeDeviceType = END_DEVICE; break; default: command = NO_CHARACTER_RECEIVED; goto set_type; } command = NO_CHARACTER_RECEIVED; state = STATE_MODULE_STARTUP; break; } case STATE_MODULE_STARTUP: { #define MODULE_START_DELAY_IF_FAIL_MS 5000 moduleResult_t result; /* Start with the default module configuration */ struct moduleConfiguration defaultConfiguration = DEFAULT_MODULE_CONFIGURATION_COORDINATOR; /* Make any changes needed here (channel list, PAN ID, etc.) We Configure the Zigbee Device Type (Router, Coordinator, End Device) based on what user selected */ defaultConfiguration.deviceType = zigbeeDeviceType; while ((result = startModule(&defaultConfiguration, GENERIC_APPLICATION_CONFIGURATION)) != MODULE_SUCCESS) { printf("Module start unsuccessful. Error Code 0x%02X. Retrying...\r\n", result); delayMs(MODULE_START_DELAY_IF_FAIL_MS); } printf("Success\r\n"); state = STATE_DISPLAY_NETWORK_INFORMATION; zigbeeNetworkStatus = NWK_ONLINE; break; } case STATE_DISPLAY_NETWORK_INFORMATION: { printf("Module Information:\r\n"); /* On network, display info about this network */ displayNetworkConfigurationParameters(); displayDeviceInformation(); displayCommandLineInterfaceHelp(); state = STATE_IDLE; //startup is done! break; } case STATE_VALID_SHORT_ADDRESS_ENTERED: //command line processor has a valid shortAddressEntered { printf("Valid Short Address Entered\r\n"); state = pendingState; break; } case STATE_VALID_LONG_ADDRESS_ENTERED: { /* flip byte order */ int8_t temp[8]; int i; for (i=0; i<8; i++) temp[7-i] = longAddressEntered[i]; memcpy(longAddressEntered, temp, 8); //Store LSB first since that is how it will be sent: state = pendingState; break; } case STATE_SEND_MESSAGE_VIA_SHORT_ADDRESS: { printf("Send via short address to %04X\r\n", shortAddressEntered); moduleResult_t result = afSendData(DEFAULT_ENDPOINT,DEFAULT_ENDPOINT,shortAddressEntered, TEST_CLUSTER, testMessage, 5); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { printf("Could not send to that device (Error Code 0x%02X)\r\n", result); #ifdef RESTART_AFTER_ZM_FAILURE printf("\r\nRestarting\r\n"); state = STATE_MODULE_STARTUP; continue; #endif } state = STATE_IDLE; break; } case STATE_SEND_MESSAGE_VIA_LONG_ADDRESS: { printf("Send via long address to (LSB first)"); printHexBytes(longAddressEntered, 8); moduleResult_t result = afSendDataExtended(DEFAULT_ENDPOINT, DEFAULT_ENDPOINT, longAddressEntered, DESTINATION_ADDRESS_MODE_LONG, TEST_CLUSTER, testMessage, 5); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { printf("Could not send to that device (Error Code 0x%02X)\r\n", result); #ifdef RESTART_AFTER_ZM_FAILURE printf("\r\nRestarting\r\n"); state = STATE_MODULE_STARTUP; continue; #endif } state = STATE_IDLE; break; } case STATE_FIND_VIA_SHORT_ADDRESS: { printf("Looking for that device...\r\n"); moduleResult_t result = zdoRequestIeeeAddress(shortAddressEntered, SINGLE_DEVICE_RESPONSE, 0); if (result == MODULE_SUCCESS) { #ifndef ZDO_NWK_ADDR_RSP_HANDLED_BY_APPLICATION displayZdoAddressResponse(zmBuf + SRSP_PAYLOAD_START); #endif } else { printf("Could not locate that device (Error Code 0x%02X)\r\n", result); } state = STATE_IDLE; break; } case STATE_FIND_VIA_LONG_ADDRESS: { printf("Looking for that device...\r\n"); moduleResult_t result = zdoNetworkAddressRequest(longAddressEntered, SINGLE_DEVICE_RESPONSE, 0); if (result == MODULE_SUCCESS) { #ifndef ZDO_NWK_ADDR_RSP_HANDLED_BY_APPLICATION displayZdoAddressResponse(zmBuf + SRSP_PAYLOAD_START); #endif } else { printf("Could not locate that device (Error Code 0x%02X)\r\n", result); } state = STATE_IDLE; break; } default: //should never happen { printf("UNKNOWN STATE (%u)\r\n", state); state = STATE_IDLE; } break; } } }
/** Parse any received messages. If it's one of our OIDs then display the value on the RGB LED too. */ void parseMessages() { getMessage(); if ((zmBuf[SRSP_LENGTH_FIELD] > 0) && (IS_AF_INCOMING_MESSAGE())) { setLed(4); //LED will blink to indicate a message was received #ifdef VERBOSE_MESSAGE_DISPLAY printAfIncomingMsgHeader(zmBuf); printf("\r\n"); #endif if ((AF_INCOMING_MESSAGE_CLUSTER()) == INFO_MESSAGE_CLUSTER) { struct infoMessage im; deserializeInfoMessage(zmBuf+20, &im); // Convert the bytes into a Message struct int j = 0; #ifdef VERBOSE_MESSAGE_DISPLAY printInfoMessage(&im); displayZmBuf(); #else printf("From:"); // Display the sender's MAC address for (j = 7; j>(-1); j--) { printf("%02X", im.header.mac[j]); } int k; for (k = 0; k < NUM_DEVICES; k++) { int match = 1; for (j = 7; j>(-1); j--) { if (routers[k].MAC_address[j] != im.header.mac[j]) { match = 0; } } if (match == 1) { current_router_index = k; routers[current_router_index].LQI = zmBuf[AF_INCOMING_MESSAGE_LQI_FIELD]; } } printf(", LQI=%02X, ", zmBuf[AF_INCOMING_MESSAGE_LQI_FIELD]); // Display the received signal quality (Link Quality Indicator) //LQI = zmBuf[AF_INCOMING_MESSAGE_LQI_FIELD]; #endif printf("%u KVPs received:\r\n", im.numParameters); #define NO_VALUE_RECEIVED 0xFF uint8_t redIndex = NO_VALUE_RECEIVED; uint8_t blueIndex = NO_VALUE_RECEIVED; uint8_t greenIndex = NO_VALUE_RECEIVED; for (j=0; j<im.numParameters; j++) // Iterate through all the received KVPs { printf(" %s (0x%02X) = %d ", getOidName(im.kvps[j].oid), im.kvps[j].oid, im.kvps[j].value); // Display the Key & Value displayFormattedOidValue(im.kvps[j].oid, im.kvps[j].value); printf("\r\n"); // If the received OID was an IR temperature OID then we can just display it on the LED if ((rgbLedDisplayMode == RGB_LED_DISPLAY_MODE_TEMP_IR) && (im.kvps[j].oid == OID_TEMPERATURE_IR)) displayTemperatureOnRgbLed(im.kvps[j].value); // But for the color sensor we need to get all three values before displaying else if (im.kvps[j].oid == OID_COLOR_SENSOR_RED) redIndex = j; else if (im.kvps[j].oid == OID_COLOR_SENSOR_BLUE) blueIndex = j; else if (im.kvps[j].oid == OID_COLOR_SENSOR_GREEN) greenIndex = j; } // Now done iterating through all KVPs. If we received color then update RGB LED #define RED_VALUE (im.kvps[redIndex].value) #define BLUE_VALUE (im.kvps[blueIndex].value) #define GREEN_VALUE (im.kvps[greenIndex].value) if ((rgbLedDisplayMode == RGB_LED_DISPLAY_MODE_COLOR) && ((redIndex != NO_VALUE_RECEIVED) && (blueIndex != NO_VALUE_RECEIVED) && (greenIndex != NO_VALUE_RECEIVED))) { displayColorOnRgbLed(RED_VALUE, BLUE_VALUE, GREEN_VALUE); } printf("\r\n"); } else { printf("Rx: "); printHexBytes(zmBuf+SRSP_HEADER_SIZE+17, zmBuf[SRSP_HEADER_SIZE+16]); //print out message payload } clearLeds(0); } else if (IS_ZDO_END_DEVICE_ANNCE_IND()) { displayZdoEndDeviceAnnounce(zmBuf); } else { //unknown message, just print out the whole thing printf("MSG: "); printHexBytes(zmBuf, (zmBuf[SRSP_LENGTH_FIELD] + SRSP_HEADER_SIZE)); } zmBuf[SRSP_LENGTH_FIELD] = 0; }
static void stateMachine() { while (1) { if (zigbeeNetworkStatus == NWK_ONLINE) { if(moduleHasMessageWaiting()) //wait until SRDY goes low indicating a message has been received. { getMessage(); displayMessage(); } } switch (state) { case STATE_IDLE: { /* process command line commands only if not doing anything else: */ if (command != NO_CHARACTER_RECEIVED) { /* parse the command entered, and go to the required state */ state = processCommand(command); command = NO_CHARACTER_RECEIVED; } /* note: other flags (for different messages or events) can be added here */ break; } case STATE_INIT: { printf("Starting State Machine\r\n"); state = STATE_GET_DEVICE_TYPE; break; } /* A button press during startup will cause the application to prompt for device type */ case STATE_GET_DEVICE_TYPE: { set_type: while (command == NO_CHARACTER_RECEIVED) { printf("Setting Device Type: Press C for Coordinator, R for Router, or E for End Device.\r\n"); #define DEVICE_TYPE_DELAY_MS 2000 #define DEVICE_TYPE_DELAY_PER_CYCLE_MS 100 uint16_t delayCycles = DEVICE_TYPE_DELAY_MS / DEVICE_TYPE_DELAY_PER_CYCLE_MS; while ((command == NO_CHARACTER_RECEIVED) && (delayCycles--) > 0) delayMs(DEVICE_TYPE_DELAY_PER_CYCLE_MS); } switch (command) { case 'C': case 'c': printf("Coordinator it is...\r\n"); zigbeeDeviceType = COORDINATOR; break; case 'R': case 'r': printf("Router it is...\r\n"); zigbeeDeviceType = ROUTER; break; case 'E': case 'e': printf("End Device it is...\r\n"); zigbeeDeviceType = END_DEVICE; break; default: command = NO_CHARACTER_RECEIVED; goto set_type; } command = NO_CHARACTER_RECEIVED; state = STATE_MODULE_STARTUP; break; } case STATE_MODULE_STARTUP: { #define MODULE_START_DELAY_IF_FAIL_MS 5000 moduleResult_t result; /* Start with the default module configuration */ struct moduleConfiguration defaultConfiguration = DEFAULT_MODULE_CONFIGURATION_COORDINATOR; /* Make any changes needed here (channel list, PAN ID, etc.) We Configure the Zigbee Device Type (Router, Coordinator, End Device) based on what user selected */ defaultConfiguration.deviceType = zigbeeDeviceType; /* Change this below to be your operating region - MODULE_REGION_NORTH_AMERICA or MODULE_REGION_EUROPE */ #define OPERATING_REGION (MODULE_REGION_NORTH_AMERICA) // or MODULE_REGION_EUROPE while ((result = expressStartModule(&defaultConfiguration, GENERIC_APPLICATION_CONFIGURATION, OPERATING_REGION)) != MODULE_SUCCESS) { SET_NETWORK_FAILURE_LED_ON(); // Turn on the LED to show failure handleModuleError(result); printf("Retrying...\r\n"); delayMs(MODULE_START_DELAY_IF_FAIL_MS/2); SET_NETWORK_FAILURE_LED_OFF(); delayMs(MODULE_START_DELAY_IF_FAIL_MS/2); } printf("Success\r\n"); state = STATE_DISPLAY_NETWORK_INFORMATION; zigbeeNetworkStatus = NWK_ONLINE; break; } case STATE_DISPLAY_NETWORK_INFORMATION: { printf("Module Information:\r\n"); /* On network, display info about this network */ displayNetworkConfigurationParameters(); displayDeviceInformation(); displayCommandLineInterfaceHelp(); state = STATE_IDLE; //startup is done! break; } case STATE_VALID_SHORT_ADDRESS_ENTERED: //command line processor has a valid shortAddressEntered { state = pendingState; break; } case STATE_VALID_LONG_ADDRESS_ENTERED: { /* Flip byte order because we need to send it LSB first */ int8_t temp[8]; int i; for (i=0; i<8; i++) temp[7-i] = longAddressEntered[i]; memcpy(longAddressEntered, temp, 8); //Store LSB first since that is how it will be sent: state = pendingState; break; } case STATE_SEND_MESSAGE_VIA_SHORT_ADDRESS: { printf("Send to 0x%04X\r\n", shortAddressEntered); moduleResult_t result = afSendData(DEFAULT_ENDPOINT,DEFAULT_ENDPOINT,shortAddressEntered, TEST_CLUSTER, testMessage, 5); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { handleModuleError(result); #ifdef RESTART_AFTER_ZM_FAILURE printf("\r\nRestarting\r\n"); state = STATE_MODULE_STARTUP; continue; #endif } state = STATE_IDLE; break; } case STATE_SEND_MESSAGE_VIA_LONG_ADDRESS: { printf("Send to (LSB first)"); printHexBytes(longAddressEntered, 8); moduleResult_t result = afSendDataExtended(DEFAULT_ENDPOINT, DEFAULT_ENDPOINT, longAddressEntered, DESTINATION_ADDRESS_MODE_LONG, TEST_CLUSTER, testMessage, 5); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { handleModuleError(result); #ifdef RESTART_AFTER_ZM_FAILURE printf("\r\nRestarting\r\n"); state = STATE_MODULE_STARTUP; continue; #endif } state = STATE_IDLE; break; } #ifdef LEAVE_REQUEST case STATE_MANAGEMENT_LEAVE_REQUEST: { printf("Sending Leave Request for MAC (LSB first)"); printHexBytes(longAddressEntered, 8); moduleResult_t result = zdoManagementLeaveRequest(longAddressEntered, 0); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { handleModuleError(result); } state = STATE_IDLE; break; } #endif case STATE_FIND_VIA_SHORT_ADDRESS: { printf("Looking for that device...\r\n"); moduleResult_t result = zdoRequestIeeeAddress(shortAddressEntered, INCLUDE_ASSOCIATED_DEVICES, 0); if (result == MODULE_SUCCESS) { #ifndef ZDO_NWK_ADDR_RSP_HANDLED_BY_APPLICATION displayZdoAddressResponse(zmBuf + SRSP_PAYLOAD_START); #endif } else { handleModuleError(result); } state = STATE_IDLE; break; } case STATE_FIND_VIA_LONG_ADDRESS: { printf("Looking for that device...\r\n"); moduleResult_t result = zdoNetworkAddressRequest(longAddressEntered, INCLUDE_ASSOCIATED_DEVICES, 0); if (result == MODULE_SUCCESS) { #ifndef ZDO_NWK_ADDR_RSP_HANDLED_BY_APPLICATION displayZdoAddressResponse(zmBuf + SRSP_PAYLOAD_START); #endif } else { handleModuleError(result); } state = STATE_IDLE; break; } #ifdef INCLUDE_PERMIT_JOIN case STATE_SET_PERMIT_JOIN_ON: { printf("Turning joining ON...\r\n"); moduleResult_t result = zdoManagementPermitJoinRequest(shortAddressEntered, PERMIT_JOIN_ON_INDEFINITELY, 0); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { handleModuleError(result); } state = STATE_IDLE; break; } case STATE_SET_PERMIT_JOIN_OFF: { printf("Turning joining OFF...\r\n"); moduleResult_t result = zdoManagementPermitJoinRequest(shortAddressEntered, PERMIT_JOIN_OFF, 0); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { handleModuleError(result); } state = STATE_IDLE; break; } #endif #ifdef DISCOVER_NETWORKS case STATE_NETWORK_DISCOVERY_REQUEST: { printf("Scanning...\r\n"); moduleResult_t result = zdoNetworkDiscoveryRequest(ANY_CHANNEL_MASK, BEACON_ORDER_480_MSEC); if (result == MODULE_SUCCESS) { printf("Success\r\n"); } else { handleModuleError(result); } state = STATE_IDLE; break; } #endif #ifdef INCLUDE_NETWORK_TOPOLOGY case STATE_GET_NETWORK_TOPOLOGY: { printf("Displaying NWK Topology...........\r\n"); initSet(&searchedSet); // Start the recursive search for all children of the short address //removeAllFromSet(); int8_t numChildren = displayChildren(shortAddressEntered); state = STATE_IDLE; break; } #endif default: //should never happen { printf("UNKNOWN STATE (%u)\r\n", state); state = STATE_IDLE; } break; } } }
/** Displays the type of message in zmBuf. Ignores the message if length = 0. @pre moduleHasMessageWaiting() is true @pre getMessage() called to get message into zmBuf @post zmBuf Length field = 0 */ void displayMessage() { if (zmBuf[SRSP_LENGTH_FIELD] > 0) { switch ( (CONVERT_TO_INT(zmBuf[SRSP_CMD_LSB_FIELD], zmBuf[SRSP_CMD_MSB_FIELD])) ) { case AF_DATA_CONFIRM: { printf("AF_DATA_CONFIRM\r\n"); break; } case AF_INCOMING_MSG: { printf("AF_INCOMING_MSG "); printAfIncomingMsgHeader(zmBuf); printf("\r\n"); #ifdef VERBOSE_MESSAGE_DISPLAY printf("Payload: "); printHexBytes(zmBuf+SRSP_HEADER_SIZE+17, zmBuf[SRSP_HEADER_SIZE+16]); //print out message payload #endif break; } case AF_INCOMING_MSG_EXT: { printf("AF_INCOMING_MSG_EXT\r\n"); uint16_t len = AF_INCOMING_MESSAGE_EXT_LENGTH(); printf("Extended Message Received, L%u ", len); break; } case ZDO_IEEE_ADDR_RSP: { printf("ZDO_IEEE_ADDR_RSP\r\n"); displayZdoAddressResponse(zmBuf + SRSP_PAYLOAD_START); break; } case ZDO_NWK_ADDR_RSP: { printf("ZDO_NWK_ADDR_RSP\r\n"); displayZdoAddressResponse(zmBuf + SRSP_PAYLOAD_START); break; } case ZDO_END_DEVICE_ANNCE_IND: { printf("ZDO_END_DEVICE_ANNCE_IND\r\n"); displayZdoEndDeviceAnnounce(zmBuf); break; } case ZB_FIND_DEVICE_CONFIRM: { printf("ZB_FIND_DEVICE_CONFIRM\r\n"); break; } case ZDO_MGMT_NWK_DISCOVERY_RSP: { printf("ZDO_MGMT_NWK_DISCOVERY_RSP\r\n"); displayZdoNetworkDiscoveryResponse(zmBuf + SRSP_PAYLOAD_START); break; } case ZDO_MGMT_LEAVE_RSP: { printf("ZDO_MGMT_LEAVE_RSP\r\n"); displayZdoManagementLeaveResponse(zmBuf); break; } case ZDO_JOIN_CNF: { printf("ZDO_JOIN_CNF\r\n"); displayZdoJoinConfirm(zmBuf); break; } case ZDO_STATE_CHANGE_IND: { printf("ZDO_STATE_CHANGE_IND\r\n"); displayZdoStateChangeInd(zmBuf); break; } default: { printf("Message received, type 0x%04X\r\n", (CONVERT_TO_INT(zmBuf[SRSP_CMD_LSB_FIELD], zmBuf[SRSP_CMD_MSB_FIELD]))); printHexBytes(zmBuf, (zmBuf[SRSP_LENGTH_FIELD] + SRSP_HEADER_SIZE)); } } zmBuf[SRSP_LENGTH_FIELD] = 0; } //ignore messages with length == 0 }