// see xbee/device.h for documentation xbee_wpan_debug int _xbee_handle_transmit_status( xbee_dev_t *xbee, const void FAR *payload, uint16_t length, void FAR *context) { #ifdef XBEE_DEVICE_VERBOSE const xbee_frame_transmit_status_t FAR *frame = payload; #else XBEE_UNUSED_PARAMETER( payload); #endif // standard XBee frame handler; stub isn't using any parameters yet XBEE_UNUSED_PARAMETER( xbee); XBEE_UNUSED_PARAMETER( length); XBEE_UNUSED_PARAMETER( context); // it may be necessary to push information up to user code so they know when // a packet has been received or if it didn't make it out #ifdef XBEE_DEVICE_VERBOSE xSerialxPrintf_P( &xSerial1Port, PSTR( "%s: id 0x%02x to 0x%04x retries=%d del=0x%02x disc=0x%02x\n"), __FUNCTION__, frame->frame_id, be16toh( frame->network_address_be), frame->retries, frame->delivery, frame->discovery); #endif return 0; }
/** @internal Dump the contents of the frame dispatch table for XBee device \a xbee. Must have XBEE_DEVICE_VERBOSE defined. @param[in] xbee XBee device of table to dump. */ _xbee_device_debug void _xbee_dispatch_table_dump( const xbee_dev_t *xbee) { #ifndef XBEE_DEVICE_VERBOSE // empty/ignored function unless VERBOSE output enabled XBEE_UNUSED_PARAMETER( xbee); #else uint_fast8_t i; const xbee_dispatch_table_entry_t *entry; if (! xbee) { return; } puts( "Index\tType\tID\tHandler\tContext"); entry = xbee_frame_handlers; for (i = 0; entry->frame_type != 0xFF; ++i, ++entry) { if (entry->frame_type) { printf( "%3d:\t0x%02x\t0x%02x\t0x%p\t%" PRIpFAR "\n", i, entry->frame_type, entry->frame_id, entry->handler, entry->context); } else { printf( "%3d:\t[empty]\n", i); } } #endif }
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; }
/** @internal @brief Special code for setting bitfield of TimeStatus attribute. See ZCL Spec section 3.12.2.2.2 for rules on setting values in this field. Only used if device has a Time Server. */ _zcl_time_debug int _zcl_time_timestatus_set( const zcl_attribute_full_t FAR *attribute, zcl_attribute_write_rec_t *rec) { uint8_t time_status; // zcl_attribute_write_fn API, but 'attribute' parameter's value is always // a pointer to 'time_status' variable. XBEE_UNUSED_PARAMETER( attribute); if (rec->flags & ZCL_ATTR_WRITE_FLAG_ASSIGN) { // Master and MasterZoneDst bits are not settable. // If Master is set to 1, Synchronized bit is always set to 0. time_status = *rec->buffer; // can only set the Synchronized bit if Master bit is not set if (!(zcl_time_timestatus & ZCL_TIME_STATUS_MASTER)) { if (time_status & ZCL_TIME_STATUS_SYNCHRONIZED) { // set Synchronized bit zcl_time_timestatus |= ZCL_TIME_STATUS_SYNCHRONIZED; } else { // clear Synchronized bit zcl_time_timestatus &= ~ZCL_TIME_STATUS_SYNCHRONIZED; } } } return 1; }
/** @internal @brief Function registered to #ZCL_TIME_ATTR_TIME attribute of Time Cluster and called to refresh the Time attribute (global zcl_time_time). See zcl_attribute_update_fn() for calling convention. */ _zcl_time_debug uint_fast8_t _zcl_time_time_get( const zcl_attribute_full_t FAR *attribute) { // zcl_attribute_update_fn API, but 'attribute' parameter's value is always // a pointer to 'zcl_time_time' variable. XBEE_UNUSED_PARAMETER( attribute); #if ZCL_TIME_EPOCH_DELTA > 0 if (! zcl_time_skew && xbee_seconds_timer() < ZCL_TIME_EPOCH_DELTA) { // we don't really know what time it is... zcl_time_time = ZCL_UTCTIME_INVALID; } else #endif { zcl_time_time = zcl_time_skew + (xbee_seconds_timer() - ZCL_TIME_EPOCH_DELTA); } #ifdef ZCL_TIME_VERBOSE printf( "%s: read clock & updated zcl_time_time to 0x%" PRIx32 "\n", __FUNCTION__, zcl_time_time); #endif return ZCL_STATUS_SUCCESS; }
// hook for GetOpenFileName to move window to foreground UINT APIENTRY OFNHookProc(HWND h, UINT msg, WPARAM wParam, LPARAM lParam) { HWND hwndDlg, hwndOwner; RECT rc, rcDlg, rcOwner; // This function follows the standard API for an OPENFILENAME lpfnHook, // but we aren't using all of its parameters. Since we set the OFN_EXPLORER // flag, this is an OFNHookProc. XBEE_UNUSED_PARAMETER( wParam); XBEE_UNUSED_PARAMETER( lParam); // Code to center window over console based on code from // http://msdn.microsoft.com/en-us/library/ms644996(v=VS.85).aspx#init_box if (msg == WM_INITDIALOG) { hwndDlg = GetParent(h); hwndOwner = GetConsoleWindow(); GetWindowRect(hwndOwner, &rcOwner); GetWindowRect(hwndDlg, &rcDlg); CopyRect(&rc, &rcOwner); // Offset the owner and dialog box rectangles so that right and bottom // values represent the width and height, and then offset the owner again // to discard space taken up by the dialog box. OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); OffsetRect(&rc, -rc.left, -rc.top); OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); // The new position is the sum of half the remaining space and the owner's // original position. SetWindowPos(hwndDlg, HWND_TOPMOST, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, // Ignores size arguments. SWP_NOSIZE | SWP_SHOWWINDOW); return TRUE; } return FALSE; }
int xbee_ota_error( const wpan_envelope_t FAR *envelope, void FAR *context) { // This cluster callback has a NULL context in the cluster table, so // there's no need to reference it here. XBEE_UNUSED_PARAMETER( context); // display any error messages sent to the OTA update client puts( "Error from target:"); printf( "%.*s\n", envelope->length, (char *) envelope->payload); return 0; }
// 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); }
/** Process XBee "Receive Explicit" frames (type 0x91) and hand off to wpan_envelope_dispatch() for further processing. Please view the function help for xbee_frame_handler_fn() for details on this function's parameters and possible return values. */ xbee_wpan_debug int _xbee_handle_receive_explicit( xbee_dev_t *xbee, const void FAR *raw, uint16_t length, void FAR *context) { const xbee_frame_receive_explicit_t FAR *frame = raw; wpan_envelope_t env; // this XBee frame handler (standard API) doesn't use the context parameter XBEE_UNUSED_PARAMETER( context); if (frame == NULL) { return -EINVAL; } if (length < offsetof( xbee_frame_receive_explicit_t, payload)) { // invalid frame -- should always be at least as long as payload field return -EBADMSG; } env.dev = &(xbee->wpan_dev); env.ieee_address = frame->ieee_address; env.network_address = be16toh( frame->network_address_be); env.source_endpoint = frame->source_endpoint; env.dest_endpoint = frame->dest_endpoint; env.cluster_id = be16toh( frame->cluster_id_be); env.profile_id = be16toh( frame->profile_id_be); env.options = 0; if (frame->options & XBEE_RX_OPT_BROADCAST) { env.options |= WPAN_ENVELOPE_BROADCAST_ADDR; } if (frame->options & XBEE_RX_OPT_APS_ENCRYPT) { env.options |= WPAN_ENVELOPE_RX_APS_ENCRYPT; } env.payload = frame->payload; env.length = length - offsetof( xbee_frame_receive_explicit_t, payload); return wpan_envelope_dispatch( &env); }
// This should be the ZDO Match Descriptor response to our search for // an XBee with the OTA update cluster. int xbee_found( wpan_conversation_t FAR *conversation, const wpan_envelope_t FAR *envelope) { int i; const uint16_t attributes[] = { ZCL_BASIC_ATTR_APP_VERSION, ZCL_BASIC_ATTR_STACK_VERSION, ZCL_BASIC_ATTR_MODEL_IDENTIFIER, ZCL_BASIC_ATTR_DATE_CODE, ZCL_ATTRIBUTE_END_OF_LIST }; const zcl_client_read_t client_read = { &sample_endpoints.zcl, ZCL_MFG_NONE, ZCL_CLUST_BASIC, attributes }; wpan_envelope_t reply_envelope; // We don't need to reference the 'converstation' parameter in this // wpan_response_fn callback. XBEE_UNUSED_PARAMETER( conversation); if (! envelope) // conversation timed out { if (target_index == 0) { printf( "%s: no targets found\n", __FUNCTION__); } return 0; } if (envelope->cluster_id != ZDO_MATCH_DESC_RSP) { printf( "%s: cluster is not a ZDO response?\n", __FUNCTION__); return -EINVAL; } i = find_target( &envelope->ieee_address); if (i < 0 && target_index < TARGET_COUNT) { i = target_index; // new target found -- add to list target_list[target_index].ieee = envelope->ieee_address; ++target_index; } if (i >= 0) { // send Read Attributes to Basic Cluster wpan_envelope_reply( &reply_envelope, envelope); reply_envelope.source_endpoint = client_read.ep->endpoint; reply_envelope.profile_id = client_read.ep->profile_id; reply_envelope.cluster_id = client_read.cluster_id; // use broadcast endpoint reply_envelope.dest_endpoint = 0xFF; reply_envelope.options = current_profile->flags; zcl_client_read_attributes( &reply_envelope, &client_read); } // just need to find one return WPAN_CONVERSATION_CONTINUE; }