Hi,
I’m up to no good again… I’m not sure if this is a stackoverflow type question, but figured i’d post here first as you fine folk at core-electronics might see value in this one?? (maybe)
I am trying to send an image from one PiicoDev Transceiver to another. To reduce swivel chair operations i’m running both PiicoDev Transceivers off of a single Raspberry Pi4B, with the first transceiver having ID 0,0,0,0 and the second transceiver having ID 1,0,0,0. Transceiver 2 is plugged into transceiver 1 which is attached to the PiicoDev interface board that is sitting on my Pi.
WHY (am I trying to send an image)
Great question and you probably think i am mad, but reality is - cellular communications isn’t always there, nor wifi (for those use cases I just use UDP/Sockets), but imagine you’re out in the bush with your 4x4, there’s no network coverage and you want to send a picture to the 4x4 in front of you over RF…
The Challenge
I’ve written some sender and receiver code, however i’m not a natural python programmer and so I don’t know how to solve my challenge. The ‘sending/transmitter’ code works I think, it sends packets of data with a START and END ok. On the receiving code, it detects the START and then starts reading the data packets and appending them to received_data , again I think this works ok. However once all the packets are received I am then trying to display the image but get the message:
TypeError: a bytes-like object is required, not 'str'
I tried using an .encode() command on the string but that throws up a different type of error.
Anyhow keen to see if anyone knows what adjustments I’d have to make to achieve my mission (sending an image over a PiicoDev 915Mhz Transceiver).
SENDER Code
# The purpose of this code is to send an image file across a PiicoDev Transceiver
# Include statements for the transceiver
from PiicoDev_Transceiver import PiicoDev_Transceiver
from PiicoDev_Unified import sleep_ms
#setup the PiicoDev sensors / output devices
transmitter = PiicoDev_Transceiver(id=[0,0,0,0])
# Open and read the JPEG image
image_path = "/home/pimaster/Desktop/PiicoDev/Test-Image.jpg"
with open(image_path, 'rb') as image_file:
image_data = image_file.read()
# Define the packet size for splitting the image data
PACKET_SIZE = 1024
# Create a function to split data into packets and send them
def send_data(data):
packet_count = (len(data) + PACKET_SIZE - 1) // PACKET_SIZE
print("Packet count is " + str(packet_count))
#transmitter.send(f"START{packet_count}".encode())
transmitter.send(f"START{packet_count}")
sleep_ms(500)
#Transceiver - Send packet of image data
for i in range(0, len(data), PACKET_SIZE):
packet = data[i : i + PACKET_SIZE]
transmitter.send(packet)
print('Sending packet number ' + str(i))
sleep_ms(500)
#transmitter.send(b"END")
transmitter.send(f"END")
print('Sending END packet')
try:
send_data(image_data)
print("Image sent successfully!")
except Exception as e:
print("Error sending image:", e)
RECEIVER Code
# This is my receiver code. The intention is to receive packets of image data from a
# transceiver and then show the image once all the packets have been received.
# Include/imports statements for the transceiver
from PiicoDev_Transceiver import PiicoDev_Transceiver
from PiicoDev_Unified import sleep_ms
# Include/imports for image stuff
from PIL import Image
import io
import re
#setup the PiicoDev sensors / output devices
receiver = PiicoDev_Transceiver(id=[1,0,0,0])
# Define our global vars
received_data = ""
expected_packet_count = 0
current_packet_count = 0
# Listen for incoming connections and data
def lookforstart():
startnotfound = True
global expected_packet_count
while True:
if receiver.receive():
message = receiver.message
if ('START' in message):
numberofpackets = int(re.search(r'\d+', message).group())
expected_packet_count = numberofpackets
print("Expected packet count is " + str(expected_packet_count))
startnotfound = False
if startnotfound == False:
break
def getimagedata():
global expected_packet_count
global current_packet_count
global received_data
while True:
if receiver.receive():
data = receiver.message
print("Received packet " + str(current_packet_count) + " of " + str(expected_packet_count))
if ("START" in data):
print("** Have found start again so that might be a new image")
expected_packet_count = int(data[5:])
print(f"Expecting {expected_packet_count} packets.")
current_packet_count = 0
received_data = b""
#elif data.startswith(b"END"):
elif ("END" in data):
print("** Have come to the end of the data stream")
# received_data += data
if current_packet_count == int(expected_packet_count):
# I did try to encode the string but that generates a different type of error
#encoded_data = received_data.encode()
#image = Image.open(io.BytesIO(encoded_data))
image = Image.open(io.BytesIO(received_data))
image.show()
print("Image received successfully!")
else:
print("Received packet count doesn't match the expected count.")
expected_packet_count = 0
current_packet_count = 0
received_data = b""
break
current_packet_count += 1
received_data += data
try:
# Look for the initial START packet and get the intended packet count
lookforstart()
# Now get the data packets and display the image
getimagedata()
except KeyboardInterrupt:
print("Terminating...")
Last thing to mention is you’ll see that I slowed the sending down by introducing a sleep of 500ms, this was intentional for the moment. Once the code works then the sleeps can be removed and I guess the transceiver speed needs to be set to 300kbps (maybe) but I am not sure what that will do to the range - again this is something I was looking to test… Would be good to be able to send a message over 50-100m maybe…