Frank Hayward
Frank Hayward

Reputation: 1137

The data provided for 'dest_addr_long' was not 8 bytes long

My script is monitoring changes to the state of my remote xbee. To do this I need to send the destination long address to the router which I get from the coordinator. It all works well if I explicitly type in the destination long address like this:

addr = '\x00\x13\xA2\x00@\n!\x1C'    
xbee.remote_at(dest_addr_long=addr, command=mycommand, frame_id='\x01')

and it gives me the desired data output which is

{'status': '\x00', 'source_addr': '\x7fD', 'source_addr_long': '\x00\x13\xa2\x00@\n!\x1c', 'frame_id': '\x01', 'command': 'D0', 'parameter': '\x05', 'id': 'remote_at_response'}

from which I can read the parameter to determine the state of the xbee.

The problem I am having is that I don't know the addr up front. I get it when I run this command

mysourceaddrlong = repr(data['source_addr_long'])[1:-1] 
addr = "\\".join([(i[0]+i[1:].upper()) for i in mysourceaddrlong.split('\\') if i])
addr = addr[1:] #remove the x in front
addr = r"\x"+addr #add \x to the front and save it as a raw string
print "Formatted addr: %s" % addr

Which outputs:

Formatted addr: \x00\x13\xA2\x00@\n!\x1C This formatted addr appears to me to be exactly the same, but it does not work when I run my at command like this:

xbee.remote_at(dest_addr_long=addr, command=mycommand, frame_id='\x01')

I get an error saying

ValueError: The data provided for 'dest_addr_long' was not 8 bytes long

I've included the entire script below:

#! /usr/bin/python
import serial
import time
from xbee import XBee

ser = serial.Serial('/dev/ttyUSB0', 9600)
xbee = XBee(ser)

def print_data(data):
    print data
    mycommand = data['command']
    mysourceaddrlong = repr(data['source_addr_long'])[1:-1] 
    addr = "\\".join([(i[0]+i[1:].upper()) for i in mysourceaddrlong.split('\\') if i])
    print "incorrectly formatted addr: %s" % addr 
    addr = addr[1:] #remove the x in front
    addr = r"\x"+addr #add \x to the front and save it as a raw string
    print "formatted addr: %s" % addr
    try:
        xbee.remote_at(dest_addr_long=addr, command=mycommand, frame_id='\x01')
        response = xbee.wait_read_frame()
        myhexparameter = response['parameter'] 
        myparameter =  ord (myhexparameter)
        if myparameter == 4:
            print "Which means pin %s is OFF" % mycommand
        if myparameter == 5:
            print "Which means pin %s is ON" % mycommand
    except KeyboardInterrupt:
        pass

xbee = XBee(ser, callback=print_data)

while True:
    try:
        time.sleep(0.001)
    except KeyboardInterrupt:
        break

xbee.halt()
ser.close()

Upvotes: 0

Views: 345

Answers (1)

Alex Martelli
Alex Martelli

Reputation: 881745

formatted_addr (my name for the addr you compute in your second snippet) only appears to be the same as addr (as you set it in the first snippet) because you're passing both through the wringer of __str__ (indirectly via print) which strives for aesthetically nice output at the cost of possible ambiguity. Try instead:

print(repr(addr))

vs

print(repr(formatted_addr))

and you'll see the differences -- all those backslash characters are actually in the formatted_addr string (and get doubled in repr) while they aren't in addr (they're only displayed as part of escape sequences).

I can't repro the issue myself as I don't have access to your setup, but I suspect

actual_addr = data['source_addr_long']

is actually what you want, without all the string processing gyrations around it. Try

print(repr(actual_addr))

and unless the problem is fixed tell us what exactly you see from these three print(repr(...)) and I bet it will be easy to fix any discrepancy that might remain.

Upvotes: 2

Related Questions