int zdo_device_annce_handler( const wpan_envelope_t FAR *envelope, void FAR *context) { addr64 addr_be; char buffer[ADDR64_STRING_LENGTH]; const zdo_device_annce_t FAR *annce; // Standard wpan_aps_handler_fn callback, but we don't use the context param. XBEE_UNUSED_PARAMETER( context); if (envelope == NULL) { return -EINVAL; } annce = envelope->payload; memcpy_letobe( &addr_be, &annce->ieee_address_le, 8); printf( "Device Announce %" PRIsFAR " (0x%04x) cap 0x%02x\n", addr64_format( buffer, &addr_be), le16toh( annce->network_addr_le), annce->capability); // discover the commissioning cluster and hand off to xbee_found? return 0; }
void transparent_dump( const addr64 FAR *ieee, const void FAR *payload, uint16_t length) { xbee_node_id_t *node_id; char buffer[ADDR64_STRING_LENGTH]; const uint8_t FAR *message = payload; uint16_t i; printf( "%u bytes from ", length); node_id = node_by_addr( ieee); if (node_id != NULL) { printf( "'%s':\n", node_id->node_info); } else { printf( "%s:\n", addr64_format( buffer, ieee)); } for (i = 0; i < length && isprint( message[i]); ++i); if (i == length) { // all characters of message are printable printf( "\t%.*s\n", length, message); } else { hex_dump( message, length, HEX_DUMP_FLAG_TAB); } }
int set_target(const char *str, addr64 FAR *address) { uint_fast8_t i; uint8_t FAR *b; int ret; char buf[40]; i = 8; // bytes to convert if (str != NULL && address != NULL) { // skip over leading spaces while (isspace( (uint8_t) *str)) { ++str; } for (b = address->b; i; ++b, --i) { ret = hexstrtobyte( str); if (ret < 0) { break; } *b = (uint8_t)ret; str += 2; // point past the encoded byte // skip over any separator, if present if (*str && ! isxdigit( (uint8_t) *str)) { ++str; } } } if (i == 4) { for (i = 7; i >= 4; --i) { address->b[i] = address->b[i-4]; } address->b[0] = 0x00; address->b[1] = 0x13; address->b[2] = 0xA2; address->b[3] = 0x00; i = 0; } if (i != 0) { printf("Target set to local device\n"); return 0; } printf("Target now %" PRIsFAR "\n", addr64_format(buf, address)); ever_had_target = 1; return 1; }
// ideas for flags: // show portname // extended dump // super dump? (state information) _xbee_device_debug void xbee_dev_dump_settings( xbee_dev_t *xbee, uint16_t flags) { char addr[ADDR64_STRING_LENGTH]; // flags parameter included in API for future expansion; unused for now XBEE_UNUSED_PARAMETER( flags); printf( "XBee on %s: HV=0x%x VR=0x%" PRIx32 " IEEE=%" PRIsFAR " net=0x%04x\n\n", xbee_ser_portname( &xbee->serport), xbee->hardware_version, xbee->firmware_version, addr64_format( addr, &xbee->wpan_dev.address.ieee), xbee->wpan_dev.address.network); }
/*** EndHeader */ int xbee_route_dump_record_indicator( xbee_dev_t *xbee, const void FAR *frame, uint16_t length, void FAR *context) { const xbee_frame_route_record_indicator_t FAR *record = frame; char buffer[ADDR64_STRING_LENGTH]; const uint16_t FAR *addr_be; int i; if (frame == NULL) { return -EINVAL; } if (record->address_count == 0 && record->address_count > XBEE_ROUTE_MAX_ADDRESS_COUNT) { printf( "invalid address count, must be 1 to %u (not %u)\n", XBEE_ROUTE_MAX_ADDRESS_COUNT, record->address_count); } else if (length == offsetof( xbee_frame_route_record_indicator_t, route_address_be) + record->address_count * sizeof *record->route_address_be) { printf( "route record indicator from %" PRIsFAR " (0x%04X):\n", addr64_format( buffer, &record->ieee_address), be16toh( record->network_address_be)); if (record->receive_options & XBEE_RX_OPT_ACKNOWLEDGED) { printf( "acknowledged, "); } if (record->receive_options & XBEE_RX_OPT_BROADCAST) { printf( "broadcast, "); } printf( "\t%u addresses:\n\tdest -> ", record->address_count); addr_be = record->route_address_be; for (i = record->address_count; i; ++addr_be, --i) { printf( "0x%04X -> ", be16toh( *addr_be)); } puts( "source"); return 0; } puts( "malformed route record indicator:"); hex_dump( frame, length, HEX_DUMP_FLAG_TAB); return -EINVAL; }
/*** EndHeader */ int xbee_route_dump_many_to_one_req( xbee_dev_t *xbee, const void FAR *frame, uint16_t length, void FAR *context) { const xbee_frame_route_many_to_one_req_t FAR *request = frame; char buffer[ADDR64_STRING_LENGTH]; if (frame != NULL && length == sizeof *request) { printf( "many to one route request from %" PRIsFAR " (0x%04X):\n", addr64_format( buffer, &request->ieee_address), be16toh( request->network_address_be)); return 0; } puts( "malformed many-to-one route request:"); hex_dump( frame, length, HEX_DUMP_FLAG_TAB); return -EINVAL; }
/* START FUNCTION DESCRIPTION ******************************************** wpan_envelope_dump <wpan_aps.c> SYNTAX: void wpan_envelope_dump( const wpan_envelope_t FAR *envelope) DESCRIPTION: Debugging function to dump the contents of an envelope to stdout. Displays all fields from the envelope, plus the contents of the payload PARAMETER1: envelope - envelope to dump **************************************************************************/ wpan_aps_debug void wpan_envelope_dump( const wpan_envelope_t FAR *envelope) { char addr[ADDR64_STRING_LENGTH]; if (envelope == NULL) { printf( "NULL envelope\n"); } else { printf( "ep %u->%u, profile 0x%04x, clust 0x%04x\n", envelope->source_endpoint, envelope->dest_endpoint, envelope->profile_id, envelope->cluster_id); printf( "remote %" PRIsFAR " (0x%04x), options=0x%04x, " "%u-byte payload:\n", addr64_format( addr, &envelope->ieee_address), envelope->network_address, envelope->options, envelope->length); hex_dump( envelope->payload, envelope->length, HEX_DUMP_FLAG_OFFSET); } }
/* main Initiate communication with the XBee module, then accept AT commands from STDIO, pass them to the XBee module and print the result. */ int main( void) { char cmdstr[80]; int status; uint16_t t; if (xbee_dev_init( &my_xbee, &XBEE_SERPORT, xbee_awake_pin, xbee_reset_pin)) { printf( "Failed to initialize device.\n"); return 0; } //xbee_dev_reset( &my_xbee); // give the XBee 500ms to wake up after resetting it (or exit if it // receives a packet) t = XBEE_SET_TIMEOUT_MS(500); while (! XBEE_CHECK_TIMEOUT_MS(t) && xbee_dev_tick( &my_xbee) <= 0); // Initialize the AT Command layer for this XBee device and have the // driver query it for basic information (hardware version, firmware version, // serial number, IEEE address, etc.) xbee_cmd_init_device( &my_xbee); printf( "Waiting for driver to query the XBee device...\n"); do { xbee_dev_tick( &my_xbee); status = xbee_cmd_query_status( &my_xbee); } while (status == -EBUSY); if (status) { printf( "Error %d waiting for query to complete.\n", status); } // report on the settings xbee_dev_dump_settings( &my_xbee, XBEE_DEV_DUMP_FLAG_DEFAULT); printATCmds( &my_xbee); printf("Target setting for remote commands:\n"); printf(" > addr (addr is hex ieee addr, high bytes assumed 0013a200)\n"); printf(" > (reset to local device)\n"); printf(" < (reinstate previous remote target)\n"); while (1) { while (xbee_readline( cmdstr, sizeof cmdstr) == -EAGAIN) { xbee_dev_tick( &my_xbee); } if (! strncmpi( cmdstr, "menu", 4)) { printATCmds( &my_xbee); } else if (! strcmpi( cmdstr, "quit")) { return 0; } else if ( cmdstr[0] == '>') { have_target = set_target( cmdstr+1, &target_ieee); } else if ( cmdstr[0] == '<') { if (ever_had_target) { have_target = 1; printf("Reinstating %" PRIsFAR "\n", addr64_format(cmdstr, &target_ieee)); } else { printf("Nothing to reinstate\n"); } } else { have_target ? process_command_remote( &my_xbee, cmdstr, &target_ieee) : process_command( &my_xbee, cmdstr); } } }
/* main Initiate communication with the XBee module, then accept AT commands from STDIO, pass them to the XBee module and print the result. */ int main( int argc, char *argv[]) { char cmdstr[80]; char buffer[ADDR64_STRING_LENGTH]; int status; xbee_serial_t XBEE_SERPORT; addr64 return_ieee_be = *ZDO_IEEE_ADDR_PENDING; uint16_t return_net_addr = ZDO_NET_ADDR_PENDING; int err; parse_serial_arguments( argc, argv, &XBEE_SERPORT); // initialize the serial and device layer for this XBee device if (xbee_dev_init( &my_xbee, &XBEE_SERPORT, NULL, NULL)) { printf( "Failed to initialize device.\n"); return 0; } // Initialize the WPAN layer of the XBee device driver. This layer enables // endpoints and clusters, and is required for all ZigBee layers. xbee_wpan_init( &my_xbee, &sample_endpoints.zdo); // Initialize the AT Command layer for this XBee device and have the // driver query it for basic information (hardware version, firmware version, // serial number, IEEE address, etc.) xbee_cmd_init_device( &my_xbee); printf( "Waiting for driver to query the XBee device...\n"); do { xbee_dev_tick( &my_xbee); status = xbee_cmd_query_status( &my_xbee); } while (status == -EBUSY); if (status) { printf( "Error %d waiting for query to complete.\n", status); } // report on the settings xbee_dev_dump_settings( &my_xbee, XBEE_DEV_DUMP_FLAG_DEFAULT); // have XBee handle ZDO responses -- on SE device, need to have it respond // to match descriptors looking for the Key Establishment cluster. xbee_cmd_simple( &my_xbee, "AO", 1); print_help(); while (1) { while (xbee_readline( cmdstr, sizeof cmdstr) == -EAGAIN) { wpan_tick( &my_xbee.wpan_dev); if (! addr64_equal( &return_ieee_be, ZDO_IEEE_ADDR_PENDING)) { if (addr64_equal( &return_ieee_be, ZDO_IEEE_ADDR_TIMEOUT)) { puts( "IEEE_addr request timed out"); } else if (addr64_is_zero( &return_ieee_be)) { printf( "Error retrieving IEEE_addr"); } else { printf( "IEEE address is %" PRIsFAR "\n", addr64_format( buffer, &return_ieee_be)); } return_ieee_be = *ZDO_IEEE_ADDR_PENDING; } if (return_net_addr != ZDO_NET_ADDR_PENDING) { if (return_net_addr == ZDO_NET_ADDR_TIMEOUT) { puts( "NWK_addr request timed out"); } else if (return_net_addr == ZDO_NET_ADDR_ERROR) { printf( "Error retrieving NWK_addr"); } else { printf( "Network address is 0x%04X\n", return_net_addr); } return_net_addr = ZDO_NET_ADDR_PENDING; } } if (! strcmpi( cmdstr, "help") || ! strcmp( cmdstr, "?")) { print_help(); } else if (! strcmpi( cmdstr, "quit")) { return 0; } else if (! strncmpi( cmdstr, "ieee ", 5)) { addr64 ieee_be; if (addr64_parse( &ieee_be, &cmdstr[5])) { printf( "couldn't parse '%s'\n", &cmdstr[5]); } else { err = zdo_send_nwk_addr_req( &my_xbee.wpan_dev, &ieee_be, &return_net_addr); printf( "sent NWK_addr request for %" PRIsFAR " (err=%d)\n", addr64_format( buffer, &ieee_be), err); } } else if (! strncmpi( cmdstr, "net ", 4)) { uint16_t net_addr; char *tail; net_addr = strtoul( &cmdstr[4], &tail, 0); if (tail == NULL) { printf( "couldn't parse '%s'\n", &cmdstr[4]); } else { err = zdo_send_ieee_addr_req( &my_xbee.wpan_dev, net_addr, &return_ieee_be); printf( "sent IEEE_addr request for 0x%04X (err=%d)\n", net_addr, err); } } else if (! strncmpi( cmdstr, "AT", 2)) { process_command( &my_xbee, cmdstr); } } }