0

I am trying to convert values from 0 to 255 to a single char. I am using chr. But this is somehow converting a number like 255 to a two char string. I add up those values to a string which is then converted with bytes(string , 'UTF-8') into a bytestream and written over serial to UART.


#!/usr/bin/python
import os
import sys
import serial
def asbyte(v):
 return chr(v & 0xFF)
def printStdErr(*objs):
# print("", *objs, file=stderr)
 print("")
class LightYModem:
 soh = 1 # 128 byte blocks
 stx = 2 # 1K blocks
 eot = 4
 ack = 6
 nak = 0x15
 ca = 0x18 # 24
 crc16 = 0x43 # 67
 abort1 = 0x41 # 65
 abort2 = 0x61 # 97
 packet_len = 1024
 expected_packet_len = packet_len+5
 packet_mark = stx
 def __init__(self):
 self.seq = None
 self.ymodem = None
 def blocking_read(self):
 ch = ''
 while not ch:
 ch = self.ymodem.read(1)
 printStdErr("read %d " % ord(ch))
 return ch
 def write(self, packet):
 #print(packet)
 b = bytes(packet, 'UTF-8')
 print(b)
 self.ymodem.write(b)
 return len(packet);
 def flush(self):
 pass
 #self.ymodem.flush()
 def _read_response(self):
 ch1 = self.blocking_read()
 ch1 = ord(ch1)
 printStdErr("response %d" % (ch1))
 if ch1==LightYModem.ack and self.seq==0: # may send also a crc16
 ch2 = self.blocking_read()
 elif ch1==LightYModem.ca: # cancel, always sent in pairs
 ch2 = self.blocking_read()
 return ch1
 def transfer(self, file, ymodem, output):
 self.ymodem = ymodem
 """
 file: the file to transfer via ymodem
 ymodem: the ymodem endpoint (a file-like object supporting write)
 output: a stream for output messages
 """
 file.seek(0, os.SEEK_END)
 size = file.tell()
 file.seek(0, os.SEEK_SET)
 response = self.send_filename_header("binary", size)
 while response==LightYModem.ack:
 response = self.send_packet(file, output)
 file.close()
 if response==LightYModem.eot:
 self._send_close()
 return response
 def _send_ymodem_packet(self, data):
 # pad string to 1024 chars
 data = data.ljust(LightYModem.packet_len)
 seqchr = asbyte(self.seq & 0xFF)
 print("seqchr : "+str(len(seqchr)))
 seqchr_neg = asbyte((255-self.seq) & 0xFF)
 print("seqchr_neg : "+str(len(seqchr_neg)))
 crc16 = '\x00\x00'
 print("bytes "+ str(bytes([255])))
 packet = asbyte(LightYModem.packet_mark) + seqchr + seqchr_neg + data + crc16
 if len(packet)!=LightYModem.expected_packet_len:
 raise Exception("packet length is wrong!")
 self.packet = packet
 written = self.write(packet)
 printStdErr("sent packet data, flush..."+str(written))
 self.flush()
 printStdErr("wait response..")
 response = self._read_response()
 if response==LightYModem.ack:
 ("sent packet nr %d " % (self.seq))
 self.seq += 1
 return response
 def send_packet(self, file, output):
 response = LightYModem.eot
 data = file.read(LightYModem.packet_len)
 if len(data):
 response = self._send_ymodem_packet(data)
 return response
 
 def send_filename_header(self, name, size):
 self.seq = 0
 packet = name 
 packet += asbyte(0) 
 packet += str(size) 
 packet += ' '
 return self._send_ymodem_packet(packet)
 def transfer(self, file, ymodem, output):
 self.ymodem = ymodem
 """
 file: the file to transfer via ymodem
 ymodem: the ymodem endpoint (a file-like object supporting write)
 output: a stream for output messages
 """
 file.seek(0, os.SEEK_END)
 size = file.tell()
 file.seek(0, os.SEEK_SET)
 response = self.send_filename_header("binary", size)
 while response==LightYModem.ack:
 response = self.send_packet(file, output)
 file.close()
 if response==LightYModem.eot:
 self._send_close()
 return response
def ymodem(args):
 ser = serial.Serial('COM24', 115200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE)
 os.chdir(r'D:\projects\testprojects\code\Test1\config')
 file = open(os.getcwd()+'\testfile.bin', 'rb')
 result = LightYModem().transfer(file, ser, sys.stderr)
 file.close()
 print("result: " + str(result))
 try:
 while (True):
 print(ser.read())
 except:
 pass
 print("Done")
if __name__ == '__main__':
 ymodem(sys.argv)

Tryed to build the bytes - Array for the different elements and added the 0-255 as uint8. Then I cannot see anything on the STM32 I use as a recepient over UART.

UPDATE: When I use bytes with LATIN-1 I get the 0 to 255 in a single byte transferred. If i try to send a single element from a LATIN-1 encoded bytearray, it doesnt work.Why is that so?

 seqchr ='\x00'
 seqchr_neg = '\xFF'
 packet = seqchr + seqchr_neg 
...
 def write(self, packet):
 bh = bytearray(packet, 'LATIN-1')
 ch = bytes(packet[0], 'LATIN-1')
 print(ch)
 print(bh[0])
 self.ymodem.write(bh )#receive only zero on my STM
 self.ymodem.write(ch)# receive the 0x02 on my STM
1
  • chr returns a str value. That value can be encoded to a one- or two-byte bytes value depending on what encoding is used. Commented Oct 16, 2024 at 12:50

1 Answer 1

1

You don't want to use chr to get a string that might have a two-byte UTF-8 encoding; you just want the literal bytes value for a single 8-bit integer.

>>> bytes([230])
b'\xe6'

or

>>> import struct
>>> struct.pack('B', 230)
b'\xe6'
answered Oct 16, 2024 at 12:53
Sign up to request clarification or add additional context in comments.

3 Comments

bytes endoded in LATIN-1 works for me, when sending it and receiving it via uart with my stm32. bytearray encoded in LATIN-1 does not. Why is that so?
I'd have to see exactly what you are doing. For the most part, the only difference between bytes and bytearray is mutability. Both represent integer values between 0 and 255, inclusive.
I updated my question with the code excerpt

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.