问题
I've two xBee Pro S2C module. I'm trying to send a image from Windows PC to Raspberry Pi with xBee modules. I configured my xBees for API mode and i can receive/send AT text messages with Python codes.
I want to send a image from my PC to Raspberry Pi Model 3 B+
I also checked this subject: http://cms.digi.com/support/forum/70518/transfer-image-between-xbee-modules-connected-raspberry-each
I made some changes and tried codes below.
PC side(sender) ###########################
ser = serial.Serial('COM6', 9600,timeout=.5)
fc= 'xbee.jpg'
File = open(fc,'r')
#while True:
line = ser.readline()
a= File.read()
print(str(a))
ser.write(str(a))
#############################
Raspberry Pi side (receiver) #############################
ser = serial.Serial('/dev/ttyUSB0', 9600,timeout=.5)
while True:
incoming = ser.readline().strip()
file = open ('images.png','wb')
print (incoming)
file.write(incoming)
file.close()
content= file.read()
#################################
Then i got a error:
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 240: character maps to <undefined>
Also an idea came to my mind. I made a script converts an image to base64 code and saves as a .txt file. I changed "images.png" as "test.txt". There is no error occured but also there is no .txt file created on my raspberry pi.
Thats really important for me. Please help.
UPDATE
I've tried this code also: https://github.com/MortadhaDhkar/zigbee-file-transfer
There is no error occured. But also file don't receive to Raspbbery Pi. Sender.py out put is:
Sending Header...
Sending File...
Done
回答1:
You can't use readline()
with binary data such as images because it is meant for text. It basically looks for linefeed characters to delimit lines of text, but when you have images they are binary and may contain the linefeed character if a pixel happens to have the brightness value of 10 (over-simplified example).
Instead, we need to establish a way for the receiver to know how many bytes of data to expect and it can then just read that many bytes. There are many ways to do that, but I just show below how to send a 4-byte integer, in network order so that the receiver can simply read a fixed number of 4 bytes to get the length of the image, and then read the exact number of bytes that make up the image. I do it in network byte order in case one machine is big-endian and the other little-endian. This allows transmission of up to 2GB images which is enormous when compared to typical JPEG/PNG image sizes.
So, here is the sender:
#!/usr/bin/env python3
import serial
import struct
# Open image and slurp entire contents
with open('image.jpg', 'rb') as f:
image = f.read()
nbytes = len(image)
print(f'DEBUG: Image length={nbytes}')
# Open serial connection
with serial.Serial('/dev/ttyS0', 9600) as s:
# Send 4-byte network order long with image size
s.write(struct.pack('!L', nbytes))
# Send image itself
s.write(image)
And here is the receiver:
#!/usr/bin/env python3
import serial
import struct
# Open serial connection
with serial.Serial('/dev/ttyS0', 9600) as s:
# Read 4-byte network order long with image size
print(f'DEBUG: Waiting for 4-byte header')
nbytes = struct.unpack('!L', s.read(4))[0]
print(f'DEBUG: Image length={nbytes}')
# Read image itself
image = s.read(nbytes)
# Open image and write
with open('image.jpg', 'wb') as f:
f.write(image)
Keywords: Raspberry Pi, serial, pyserial, send image, receive image, framing protocol.
来源:https://stackoverflow.com/questions/63531175/file-transfer-pc-to-raspberry-pi-with-xbee