BitString with python - python

I am trying to use bitstring for python to interpret an incoming data packet and break it up into readable sections. the packet will consist of a header( Source (8bits), Destination (8bits), NS(3bits), NR(3bits), RSV(1bit), LST(1bit), OPcode(8bits), LEN(8bits) ),
the Payload which is somewhere between 0 and 128 bytes (determined by the LEN in the header) and a CRC of 16bits.
The data will be arriving in a large packet over the com port. The data is originated from a micro controller that is packetizing the data and sending it to the user, which is where the python comes in to play.
Since i am unsure of how to store it before parsing I do not have any code for this.
I am new to python and need a little help getting this off the ground.
Thanks,
Erik
EDIT
I currently have a section of code up and running, but it is not producing exactly what i need.... Here is the section of code that i have up and running....
def packet_make(ser):
src = 10
p = 0
lst = 0
payload_make = 0
crc = '0x0031'
ns = 0
nr = 0
rsv = 0
packet_timeout = 0
top = 256
topm = 255
#os.system(['clear','cls'][os.name == 'nt'])
print("\tBatts: 1 \t| Berry: 2 \t| Bessler: 3")
print("\tCordell: 4 \t| Dave: 5 \t| Gold: 6")
print("\tYen: 7 \t| Erik: 8 \t| Tommy: 9")
print("\tParsons: 10 \t| JP: 11 \t| Sucess: 12")
dst = raw_input("Please select a destination Adderss: ")
message = raw_input("Please type a message: ")
#################### Start Making packet#################
p_msg = message
message = message.encode("hex")
ln = (len(message)/2)
#print (ln)
ln_hex = (ln * 2)
message = list(message)
num_of_packets = ((ln/128) + 1)
#print (num_of_packets)
message = "".join(message)
src = hex(src)
dst = hex(int(dst))
#print (message)
print("\n########Number of packets = "+str(num_of_packets) + " ############\n\n")
for p in range (num_of_packets):
Ack_rx = 0
if( (p + 1) == (num_of_packets)):
lst = 1
else:
lst = 0
header_info = 0b00000000
if ((p % 2) > 0):
ns = 1
else:
ns = 0
header_info = (header_info | (ns << 5))
header_info = (header_info | (nr << 2))
header_info = (header_info | (rsv << 1))
header_info = (header_info | (lst))
header_info = hex(header_info)
#print (header_info)
op_code = '0x44'
if (lst == 1):
ln_packet = ((ln_hex - (p * 256)) % 256)
if (p > 0):
ln_packet = (ln_packet + 2)
else:
ln_packet = ln_packet
ln_packet = (ln_packet / 2)
# print (ln_packet)
# print()
else:
ln_packet = 128
# print(ln_packet)
# print()
#ll = (p * 128)
#print(ll)
#ul = ((ln - ll) % 128)
#print(ul)
#print (message[ll:ul])
if ((p == 0)&(ln_hex > 256)):
ll = (p * 255)
# print(ll)
payload_make = (message[ll:256])
# print (payload_make)
elif ((p > 0) & ((ln_hex - (p*256)) > 256)):
ll = (p * 256)
# print(ll)
ll = (ll - 2)
ul = (ll + 256)
# print (ul)
payload_make = (message[ll:ul])
# print(payload_make)
elif ((p > 0) & ((ln_hex - (p*256)) < 257)):
ll = (p * 256)
# print(ll)
ll = (ll - 2)
ul = ((ln_hex - ll) % 256)
ul = (ll + (ul))
ul = ul + 2
print()
print(ul)
print(ln_hex)
print(ln_packet)
print()
# print(ul)
payload_make = (message[ll:ul])
# print(payload)
elif ((p == 0) & (ln_hex < 257)):
ll = (p * 255)
ul = ln_hex
payload_make = (message[ll:ul])
print(payload_make)
packet_m = BitStream()
########################HEADER#########################
packet_m.append('0x0')
packet_m.append(src) #src
packet_m.append('0x0')
packet_m.append(dst) #dst
if(int(header_info,16) < 16):
packet_m.append('0x0')
packet_m.append(header_info) # Ns, Nr, RSV, Lst
packet_m.append(op_code) #op Code
#if(ln_packet < 16):
#packet_m.append('0x0')
packet_m.append((hex(ln_packet))) #Length
###################END OF HEADER#######################
packet_m.append(("0x"+payload_make)) #Payload
#packet_m.append(BitArray(p_msg)) #Payload
packet_m.append(crc) #CRC
#print()
#print(packet)
temp_ack = '0x00'
print(packet_m)
print(ln_packet)
while((Ack_rx == 0) & (packet_timeout <= 5)):
try:
###### Send the packet
#ser.write(chr(0x31))
str_pack = list(str(packet_m)[2:])
"".join(str_pack)
ser.write(chr(0x02))
#ser.write((str(packet_m)[2:]))
for i in range (len(str_pack)):
t = ord(str_pack[i])
ser.write(chr(t))
print(chr(t))
ser.write(chr(0x04))
ser.write(chr(0x10))
ack_packet = BitStream(ser.read())
if((len(ack_packet) > 3)):
temp_ack = ACK_parse(ack_packet)
else:
packet_timeout = (packet_timeout + 1)
print "why so serious\n\n"
if(temp_ack == '0x41'):
Ack_rx = 1
elif (temp_ack == '0x4E'):
Ack_rx = 0
else:
Acl_rx = 0
except serial.SerialTimeoutException: #if timeout occurs increment counter and resend last packet
Ack_rx = 0
packet_timeout = (packet_timeout + 1)
except serial.SerialException:
print "Error ... is not Active!!!", port
The output that is printed to the terminal is as follows when source and payload are both 1:
#######Number of packets = 1 #######
31
0x0a0101441310031
1
0
.... etc..
The micro on the other end of the serial reads : 0a0101441310031
when it should read a 1 1 44 1 31 0031
Python is sending each value as a separate character rather than putting it as one char. when it was appended into the packet rather than storing into the proper length and data type it seems to have separated the hex into 2 8 bit locations rather than 1 8 bit location....
The section of python code where i am reading from the Micro works flawlessly when reading an acknowledgement packet. I have not tried it with data, but i don't think that will be an issue. The C side can not read the ACK from the python side since it is separating the hex values into 2 char rather than transmitting just the 8 bit value....
Any ideas??? Thanks

Your exact problem is a bit vague, but I should be able to help with the bitstring portion of it.
You've probably got your payload to analyse as a str (or possibly bytes if you're using Python 3 but don't worry - it works the same way). If you haven't got that far then you're going to have to ask a more basic question. I'm going to make up some data to analyse (all this is being done with an interactive Python session):
>>> from bitstring import BitStream
>>> packet_data = '(2\x06D\x03\x124V\x03\xe8'
>>> b = BitStream(bytes=packet_data)
Now you can unpack or use reads on your BitStream to extract the things you need. For example:
>>> b.read('uint:8')
40
>>> b.read('uint:8')
50
>>> b.readlist('uint:3, uint:3')
[0, 1]
>>> b.readlist('2*bool')
[True, False]
>>> b.readlist('2*uint:8')
[68, 3]
>>> b.read('bytes:3')
'\x124V'
This is just parsing the bytes and interpreting chunks as unsigned integers, bools or bytes. Take a look at the manual for more details.
If you just want the payload, then you can just extract the length then grab it by slicing:
>>> length = b[32:40].uint
>>> b[40:40 + length*8]
BitStream('0x123456')
and if you want it back as a Python str, then use the bytes interpretation:
>>> b[40:40 + 3*8].bytes
'\x124V'
There are more advance things you can do too, but a good way to get going in Python is often to open an interactive session and try some things out.

Related

Looking for a compressing algorithm that match this code

I am trying to write a tool to modify a game save. To do so, I need to decompress and compress the save. I found this decompressing algorithm for the save (that works), but I don't understand the code, so I don't know how to compress the data.
Does anyone find this familiar to any compression/decompression algorithms?
Thanks!
def get_bit(buffer, ref_pointer, ref_filter, length):
result = 0
current = buffer[ref_pointer.value]
print(current)
for i in range(length):
result <<= 1
if current & ref_filter.value:
result |= 0x1
ref_filter.value >>= 1
if ref_filter.value == 0:
ref_pointer.value += 1
current = buffer[ref_pointer.value]
ref_filter.value = 0x80
return result
def decompress(buffer, decode, length):
ref_pointer = Ref(0)
ref_filter = Ref(0x80)
dest = 0
dic = [0] * 0x2010
while ref_pointer.value < length:
print(ref_pointer.value, ref_filter.value, dest)
bits = get_bit(buffer, ref_pointer, ref_filter, 1)
if ref_pointer.value >= length:
return dest
if bits:
bits = get_bit(buffer, ref_pointer, ref_filter, 8)
if ref_pointer.value >= length:
print(dic)
return dest
decode[dest] = bits
dic[dest & 0x1fff] = bits
dest += 1
else:
bits = get_bit(buffer, ref_pointer, ref_filter, 13)
if ref_pointer.value >= length:
print(dic)
return dest
index = bits - 1
bits = get_bit(buffer, ref_pointer, ref_filter, 4)
if ref_pointer.value >= length:
print(dic)
return dest
bits += 3
for i in range(bits):
dic[dest & 0x1fff] = dic[index + i]
decode[dest] = dic[index + i]
dest += 1
print(dic)
return dest

"Test Failed: unsupported operand type(s) for +: 'int' and 'tuple'"

i keep having a problem in my code coming back as Test Failed: unsupported operand type(s) for +: 'int' and 'tuple'.
i am a super beginner who is not very good at coding, so i cannot figure out what the issue is.
here is the full code.
i am making a simple icmp pinger program.
thanks everyone for your help!!!
(this is my first question here so please let me know if i need to edit anything)
from socket import *
import os
import sys
import struct
import time
import select
import statistics
import binascii
# Should use stdev
ICMP_ECHO_REQUEST = 8
def checksum(string):
csum = 0
countTo = (len(string) // 2) * 2
count = 0
while count < countTo:
thisVal = (string[count + 1]) * 256 + (string[count])
csum += thisVal
csum &= 0xffffffff
count += 2
if countTo < len(string):
csum += (string[len(string) - 1])
csum &= 0xffffffff
csum = (csum >> 16) + (csum & 0xffff)
csum = csum + (csum >> 16)
answer = ~csum
answer = answer & 0xffff
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer
def receiveOnePing(mySocket, ID, timeout, destAddr):
timeLeft = timeout
while 1:
startedSelect = time.time()
whatReady = select.select([mySocket], [], [], timeLeft)
howLongInSelect = (time.time() - startedSelect)
if whatReady[0] == []: # Timeout
return "Request timed out."
timeReceived = time.time()
recPacket, addr = mySocket.recvfrom(1024)
# Fetch the ICMP header from the IP packet
header = recPacket[20:28]
type, code, checksum, packID, seqNo = struct.unpack("bbHHh", header)
if type == 0 and packID == ID:
bytesInDouble = struct.calcsize("d")
timeSent = struct.unpack("d", recPacket[28:28 + bytesInDouble])[0]
ttls = struct.unpack("c", recPacket[8:9])[0]
rtt = timeReceived - timeSent
return (rtt, ttls)
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
return "Request timed out."
def sendOnePing(mySocket, destAddr, ID):
# Header is type (8), code (8), checksum (16), id (16), sequence (16)
myChecksum = 0
# Make a dummy header with a 0 checksum
# struct -- Interpret strings as packed binary data
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
data = struct.pack("d", time.time())
# Calculate the checksum on the data and the dummy header.
myChecksum = checksum(header + data)
# Get the right checksum, and put in the header
if sys.platform == 'darwin':
# Convert 16-bit integers from host to network byte order
myChecksum = htons(myChecksum) & 0xffff
else:
myChecksum = htons(myChecksum)
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
packet = header + data
mySocket.sendto(packet, (destAddr, 1)) # AF_INET address must be tuple, not str
# Both LISTS and TUPLES consist of a number of objects
# which can be referenced by their position number within the object.
def doOnePing(destAddr, timeout):
icmp = getprotobyname("icmp")
# SOCK_RAW is a powerful socket type. For more details: http://sockraw.org/papers/sock_raw
mySocket = socket(AF_INET, SOCK_RAW, icmp)
myID = os.getpid() & 0xFFFF # Return the current process i
sendOnePing(mySocket, destAddr, myID)
delay = receiveOnePing(mySocket, myID, timeout, destAddr)
mySocket.close()
return delay
def ping(host, timeout=1):
# timeout=1 means: If one second goes by without a reply from the server, # the client assumes that either the client's ping or the server's pong is lost
dest = gethostbyname(host)
# print("Pinging " + dest + " using Python:")
# print("")
# Calculate vars values and return them
count = 0
val = []
# Send ping requests to a server separated by approximately one second
for i in range(0,4):
delay = doOnePing(dest, timeout)
val.append(delay)
# print(delay)
time.sleep(1) # one second
if len(val) > 0:
packet_min = min(val) * 1000
packet_avg = sum(val) / len(val) * 1000
packet_max = max(val) * 1000
stdev_var = list(val) * 1000
vars = [str(round(packet_min, 2)), str(round(packet_avg, 2)), str(round(packet_max, 2)),str(round(stdev(stdev_var), 2))]
else:
vars = ['0', '0.0', '0', '0.0']
return vars
if __name__ == '__main__':
ping("google.co.il")
You have return (rtt, ttls) in function receiveOnePing and then you return the same tuple from function doOnePing. After that, you append this tuple to list and are trying to sum this list of tuples. This leads to the error you mentioned.
You need val.append(delay[0]) in ping function (line 122).
You also use undefined function stdev. Should be statistics.stdev.
Please note that your script will crash in case of timeout because you return a string in this.
Also the code is runnable only by root.
UPD
Below is fixed code.
rom socket import *
import os
import sys
import struct
import time
import select
import statistics
import binascii
# Should use stdev
ICMP_ECHO_REQUEST = 8
def checksum(string):
csum = 0
countTo = (len(string) // 2) * 2
count = 0
while count < countTo:
thisVal = (string[count + 1]) * 256 + (string[count])
csum += thisVal
csum &= 0xffffffff
count += 2
if countTo < len(string):
csum += (string[len(string) - 1])
csum &= 0xffffffff
csum = (csum >> 16) + (csum & 0xffff)
csum = csum + (csum >> 16)
answer = ~csum
answer = answer & 0xffff
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer
def receiveOnePing(mySocket, ID, timeout, destAddr):
timeLeft = timeout
while 1:
startedSelect = time.time()
whatReady = select.select([mySocket], [], [], timeLeft)
howLongInSelect = (time.time() - startedSelect)
if whatReady[0] == []: # Timeout
return "Request timed out."
timeReceived = time.time()
recPacket, addr = mySocket.recvfrom(1024)
# Fetch the ICMP header from the IP packet
header = recPacket[20:28]
type, code, checksum, packID, seqNo = struct.unpack("bbHHh", header)
if type == 0 and packID == ID:
bytesInDouble = struct.calcsize("d")
timeSent = struct.unpack("d", recPacket[28:28 + bytesInDouble])[0]
ttls = struct.unpack("c", recPacket[8:9])[0]
rtt = timeReceived - timeSent
return (rtt, ttls)
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
return "Request timed out."
def sendOnePing(mySocket, destAddr, ID):
# Header is type (8), code (8), checksum (16), id (16), sequence (16)
myChecksum = 0
# Make a dummy header with a 0 checksum
# struct -- Interpret strings as packed binary data
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
data = struct.pack("d", time.time())
# Calculate the checksum on the data and the dummy header.
myChecksum = checksum(header + data)
# Get the right checksum, and put in the header
if sys.platform == 'darwin':
# Convert 16-bit integers from host to network byte order
myChecksum = htons(myChecksum) & 0xffff
else:
myChecksum = htons(myChecksum)
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
packet = header + data
mySocket.sendto(packet, (destAddr, 1)) # AF_INET address must be tuple, not str
# Both LISTS and TUPLES consist of a number of objects
# which can be referenced by their position number within the object.
def doOnePing(destAddr, timeout):
icmp = getprotobyname("icmp")
# SOCK_RAW is a powerful socket type. For more details: http://sockraw.org/papers/sock_raw
mySocket = socket(AF_INET, SOCK_RAW, icmp)
myID = os.getpid() & 0xFFFF # Return the current process i
sendOnePing(mySocket, destAddr, myID)
delay = receiveOnePing(mySocket, myID, timeout, destAddr)
mySocket.close()
return delay
def ping(host, timeout=1):
# timeout=1 means: If one second goes by without a reply from the server, # the client assumes that either the client's ping or the server's pong is lost
dest = gethostbyname(host)
# print("Pinging " + dest + " using Python:")
# print("")
# Calculate vars values and return them
count = 0
val = []
# Send ping requests to a server separated by approximately one second
for i in range(0,4):
delay = doOnePing(dest, timeout)
val.append(delay[0])
# print(delay)
time.sleep(1) # one second
print(val)
if len(val) > 0:
packet_min = min(val) * 1000
packet_avg = sum(val) / len(val) * 1000
packet_max = max(val) * 1000
stdev_var = list(val) * 1000
vars = [str(round(packet_min, 2)), str(round(packet_avg, 2)), str(round(packet_max, 2)),str(round(statistics.stdev(stdev_var), 2))]
else:
vars = ['0', '0.0', '0', '0.0']
return vars
if __name__ == '__main__':
ping("google.co.il")
>sudo python3 ping.py
[0.0778355598449707, 0.07866811752319336, 0.07798004150390625, 0.07628297805786133]
The error occurs in this line:
packet_avg = sum(val) / len(val) * 1000
Therefore val is suspect. Follow the logic back through doOnePing to receiveOnePing and you will find that function does not return suitable types.
You have a few issues. What I can see:
you are trying to checksum but in python, using an index returns a string, not a character, so this generates a string, not a number:
thisVal = (string[count + 1]) * 256 + (string[count])
What you probably want in this case is:
thisVal = ord(string[count + 1]) * 256 + ord(string[count])
and also on this line:
csum += (string[len(string) - 1])
to
csum += ord(string[len(string) - 1])
Then, you are putting tuples and possibly strings into your val array.
You need to decide how you want to handle the errors/time out of the ping.
You could just ignore them for now:
for i in range(0,4):
delay = doOnePing(dest, timeout)
if isinstance(delay, tuple):
val.append(delay[0])
time.sleep(1) # one second
That will only add if you received a tuple, and only add the first member of the tuple, which appears to be the delay you want.

How to test unicode code points for valid LTR use in Python?

This question is relative to this one. But as my tried solution does not work, I open a new question to deal with my specific problems.
Context:
In the application I develop, I need to build python regex that includes unicodes, possibly in the whole range(0, 0x110000). When I build my regex, for example with the following:
regex += mycodepoint_as_char + ".{0," + str(max_repeat) + "}"
I observes that for some code points, the order is reversed as if I had written:
regex += "{0," + str(max_repeat) + "}." + mycodepoint_as_char
regex = ή.{0,2}{0,3}.䝆⚭.{0,3}俩.{0,4}ⷭ
In other cases, I have an exception.
So I studied the norm for biderectional unicode and some Q/A that explain surrogate pairs, Left-To-Right and Right-To-Left special code points, and some prohibited ones reserved for UTF-16.
My problem:
Then I have decided to test all of them, and to build a list of RTL ones and prohibited ones, assuming the first would change the order in the string, and that the last would raise an exception.
Here is my test code:
#!/usr/bin/python3
import sys
import os
import unicodedata #https://docs.python.org/fr/3/library/unicodedata.html, https://fr.wikipedia.org/wiki/Normalisation_Unicode
def group_consecutive(l):
res = []
i1 = 0
i2 = 0
while i1 < len(l):
while i2 + 1 < len(l) and l[i2+1] == l[i2] + 1:
i2 += 1
res.append((i1, i2+1)) # range(i1, i2+1) has consecutive values
i1 = i2+1
i2 = i1
return res
def id_rtl_code_points():
oldstdout = sys.stdout # https://stackoverflow.com/questions/8777152/unable-to-restore-stdout-to-original-only-to-terminal
nullstdout = open(os.devnull, 'w') # https://stackoverflow.com/questions/26837247/how-to-disable-print-statements-conveniently-so-that-pythonw-can-run?noredirect=1&lq=1
forbiddenCP = []
sep = 'a' # choose a letter that can receive modifiers
s = ""
for i in range(0, 0x110000):
if i%0x10000 == 0:
print(hex(i) + "-------------") # show progress
try:
if len(s) % 2 == 1: #keep synchronised, sep on modulo = 0, chr(i) on modulo = 1
s += sep
#sys.stdout = nullstdout
print(hex(i), " : " + sep + chr(i)) # without print, no error
except:
forbiddenCP.append(i)
else:
s += sep + chr(i)
finally:
pass
#sys.stdout = oldstdout
s += sep
rtlCP = []
for i in range(0, 0x110000,2):
if s[i] != sep: #not sure at all this algorythm is right
rtlCP.append(ord(s[i]))
sys.stdout = oldstdout
#print("id_rtl_code_points - s = ", s)
print("rtlCP = ", group_consecutive(rtlCP))
print("rtlCP% = ", round(float(len(rtlCP))/0x110000*100, 2), "%")
print("forbiddenCP = ", group_consecutive(forbiddenCP))
print("forbiddenCP% = ", round(float(len(forbiddenCP))/0x110000*100, 2), "%")
def main():
id_rtl_code_points()
if __name__ == '__main__':
main()
Run as it is, I get (I skip parts with dots):
$ ./test.py
0x0-------------
0x0 : a
0x1 : a
0x2 : a
....................
0x21 : a!
0x22 : a"
0x23 : a#
0x24 : a$
....................
0x60 : a`
0x61 : aa
0x62 : ab
0x63 : ac
0x64 : ad
....................
0x98 : a
0x9a : a
0x9b : a
9c : a
0x9d : a$ 1;1;120;120;1;0x
Not so good, I don't understand why it stops displaying.
If I forward stdout to /dev/null for the exception test (uncomment lines 33 and 41), I get:
$ ./test.py
0x0-------------
0x10000-------------
0x20000-------------
0x30000-------------
0x40000-------------
0x50000-------------
0x60000-------------
0x70000-------------
0x80000-------------
0x90000-------------
0xa0000-------------
0xb0000-------------
0xc0000-------------
0xd0000-------------
0xe0000-------------
0xf0000-------------
0x100000-------------
rtlCP = []
rtlCP% = 0.0 %
forbiddenCP = [(0, 2048)]
forbiddenCP% = 0.18 %
The first 2048 code points would raise exception ? This is a silly result, of course not. I would have expected problems in the range U+D800 and U+DFFF.
Is my approach correct, then what do I miss, or is it non sense, then why?

Non responsive 2D scatter plot in Python 3.0.9

I'm trying to run a python code for an awr1642BOOST board to make a short range radar. since i dont have an dca1000 evm data capture board I'm trying to obtain the detected data points using the detObj dictionary of the provided python code. On running the the code the 2D scatter window appears blank and remains unresponsive. Please can someone point out what i might be doing wrong. I have also attached a screen shot of the error window and the python shell.[enter image description here][1]
import time
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
# Change the configuration file name
configFileName = '1642config.cfg'
CLIport = {}
Dataport = {}
byteBuffer = np.zeros(2**15,dtype = 'uint8')
byteBufferLength = 0;
# ------------------------------------------------------------------
# Function to configure the serial ports and send the data from
# the configuration file to the radar
def serialConfig(configFileName):
global CLIport
global Dataport
# Open the serial ports for the configuration and the data ports
# Raspberry pi
#CLIport = serial.Serial('/dev/ttyACM0', 115200)
#Dataport = serial.Serial('/dev/ttyACM1', 921600)
# Windows
CLIport = serial.Serial('COM4', 115200)
Dataport = serial.Serial('COM5', 921600)
# Read the configuration file and send it to the board
config = [line.rstrip('\r\n') for line in open(configFileName)]
for i in config:
CLIport.write((i+'\n').encode())
print(i)
time.sleep(0.01)
return CLIport, Dataport
# ------------------------------------------------------------------
# Function to parse the data inside the configuration file
def parseConfigFile(configFileName):
configParameters = {} # Initialize an empty dictionary to store the configuration parameters
# Read the configuration file and send it to the board
config = [line.rstrip('\r\n') for line in open(configFileName)]
for i in config:
# Split the line
splitWords = i.split(" ")
# Hard code the number of antennas, change if other configuration is used
numRxAnt = 4
numTxAnt = 2
# Get the information about the profile configuration
if "profileCfg" in splitWords[0]:
startFreq = int(float(splitWords[2]))
idleTime = int(splitWords[3])
rampEndTime = float(splitWords[5])
freqSlopeConst = float(splitWords[8])
numAdcSamples = int(splitWords[10])
numAdcSamplesRoundTo2 = 1;
while numAdcSamples > numAdcSamplesRoundTo2:
numAdcSamplesRoundTo2 = numAdcSamplesRoundTo2 * 2;
digOutSampleRate = int(splitWords[11]);
# Get the information about the frame configuration
elif "frameCfg" in splitWords[0]:
chirpStartIdx = int(splitWords[1]);
chirpEndIdx = int(splitWords[2]);
numLoops = int(splitWords[3]);
numFrames = int(splitWords[4]);
framePeriodicity = int(splitWords[5]);
# Combine the read data to obtain the configuration parameters
numChirpsPerFrame = (chirpEndIdx - chirpStartIdx + 1) * numLoops
configParameters["numDopplerBins"] = numChirpsPerFrame / numTxAnt
configParameters["numRangeBins"] = numAdcSamplesRoundTo2
configParameters["rangeResolutionMeters"] = (3e8 * digOutSampleRate * 1e3) / (2 * freqSlopeConst * 1e12 * numAdcSamples)
configParameters["rangeIdxToMeters"] = (3e8 * digOutSampleRate * 1e3) / (2 * freqSlopeConst * 1e12 * configParameters["numRangeBins"])
configParameters["dopplerResolutionMps"] = 3e8 / (2 * startFreq * 1e9 * (idleTime + rampEndTime) * 1e-6 * configParameters["numDopplerBins"] * numTxAnt)
configParameters["maxRange"] = (300 * 0.9 * digOutSampleRate)/(2 * freqSlopeConst * 1e3)
configParameters["maxVelocity"] = 3e8 / (4 * startFreq * 1e9 * (idleTime + rampEndTime) * 1e-6 * numTxAnt)
return configParameters
# ------------------------------------------------------------------
# Funtion to read and parse the incoming data
def readAndParseData16xx(Dataport, configParameters):
global byteBuffer, byteBufferLength
# Constants
OBJ_STRUCT_SIZE_BYTES = 12;
BYTE_VEC_ACC_MAX_SIZE = 2**15;
MMWDEMO_UART_MSG_DETECTED_POINTS = 1;
MMWDEMO_UART_MSG_RANGE_PROFILE = 2;
maxBufferSize = 2**15;
magicWord = [2, 1, 4, 3, 6, 5, 8, 7]
# Initialize variables
magicOK = 0 # Checks if magic number has been read
dataOK = 0 # Checks if the data has been read correctly
frameNumber = 0
detObj = {}
tlv_type = 0
readBuffer = Dataport.read(Dataport.in_waiting)
byteVec = np.frombuffer(readBuffer, dtype = 'uint8')
byteCount = len(byteVec)
# Check that the buffer is not full, and then add the data to the buffer
if (byteBufferLength + byteCount) < maxBufferSize:
byteBuffer[byteBufferLength:byteBufferLength + byteCount] = byteVec[:byteCount]
byteBufferLength = byteBufferLength + byteCount
# Check that the buffer has some data
if byteBufferLength > 16:
# Check for all possible locations of the magic word
possibleLocs = np.where(byteBuffer == magicWord[0])[0]
# Confirm that is the beginning of the magic word and store the index in startIdx
startIdx = []
for loc in possibleLocs:
check = byteBuffer[loc:loc+8]
if np.all(check == magicWord):
startIdx.append(loc)
# Check that startIdx is not empty
if startIdx:
# Remove the data before the first start index
if startIdx[0] > 0 and startIdx[0] < byteBufferLength:
byteBuffer[:byteBufferLength-startIdx[0]] = byteBuffer[startIdx[0]:byteBufferLength]
byteBuffer[byteBufferLength-startIdx[0]:] = np.zeros(len(byteBuffer[byteBufferLength-startIdx[0]:]),dtype = 'uint8')
byteBufferLength = byteBufferLength - startIdx[0]
# Check that there have no errors with the byte buffer length
if byteBufferLength < 0:
byteBufferLength = 0
# word array to convert 4 bytes to a 32 bit number
word = [1, 2**8, 2**16, 2**24]
# Read the total packet length
totalPacketLen = np.matmul(byteBuffer[12:12+4],word)
# Check that all the packet has been read
if (byteBufferLength >= totalPacketLen) and (byteBufferLength != 0):
magicOK = 1
# If magicOK is equal to 1 then process the message
if magicOK:
# word array to convert 4 bytes to a 32 bit number
word = [1, 2**8, 2**16, 2**24]
# Initialize the pointer index
idX = 0
# Read the header
magicNumber = byteBuffer[idX:idX+8]
idX += 8
version = format(np.matmul(byteBuffer[idX:idX+4],word),'x')
idX += 4
totalPacketLen = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
platform = format(np.matmul(byteBuffer[idX:idX+4],word),'x')
idX += 4
frameNumber = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
timeCpuCycles = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
numDetectedObj = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
numTLVs = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
subFrameNumber = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
# Read the TLV messages
for tlvIdx in range(numTLVs):
# word array to convert 4 bytes to a 32 bit number
word = [1, 2**8, 2**16, 2**24]
# Check the header of the TLV message
try:
tlv_type = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
tlv_length = np.matmul(byteBuffer[idX:idX+4],word)
idX += 4
except:
pass
# Read the data depending on the TLV message
if tlv_type == MMWDEMO_UART_MSG_DETECTED_POINTS:
# word array to convert 4 bytes to a 16 bit number
word = [1, 2**8]
tlv_numObj = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
tlv_xyzQFormat = 2**np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
# Initialize the arrays
rangeIdx = np.zeros(tlv_numObj,dtype = 'int16')
dopplerIdx = np.zeros(tlv_numObj,dtype = 'int16')
peakVal = np.zeros(tlv_numObj,dtype = 'int16')
x = np.zeros(tlv_numObj,dtype = 'int16')
y = np.zeros(tlv_numObj,dtype = 'int16')
z = np.zeros(tlv_numObj,dtype = 'int16')
for objectNum in range(tlv_numObj):
# Read the data for each object
rangeIdx[objectNum] = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
dopplerIdx[objectNum] = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
peakVal[objectNum] = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
x[objectNum] = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
y[objectNum] = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
z[objectNum] = np.matmul(byteBuffer[idX:idX+2],word)
idX += 2
# Make the necessary corrections and calculate the rest of the data
rangeVal = rangeIdx * configParameters["rangeIdxToMeters"]
dopplerIdx[dopplerIdx > (configParameters["numDopplerBins"]/2 - 1)] = dopplerIdx[dopplerIdx > (configParameters["numDopplerBins"]/2 - 1)] - 65535
dopplerVal = dopplerIdx * configParameters["dopplerResolutionMps"]
#x[x > 32767] = x[x > 32767] - 65536
#y[y > 32767] = y[y > 32767] - 65536
#z[z > 32767] = z[z > 32767] - 65536
x = x / tlv_xyzQFormat
y = y / tlv_xyzQFormat
z = z / tlv_xyzQFormat
# Store the data in the detObj dictionary
detObj = {"numObj": tlv_numObj, "rangeIdx": rangeIdx, "range": rangeVal, "dopplerIdx": dopplerIdx, \
"doppler": dopplerVal, "peakVal": peakVal, "x": x, "y": y, "z": z}
dataOK = 1
# Remove already processed data
if idX > 0 and byteBufferLength > idX:
shiftSize = totalPacketLen
byteBuffer[:byteBufferLength - shiftSize] = byteBuffer[shiftSize:byteBufferLength]
byteBuffer[byteBufferLength - shiftSize:] = np.zeros(len(byteBuffer[byteBufferLength - shiftSize:]),dtype = 'uint8')
byteBufferLength = byteBufferLength - shiftSize
# Check that there are no errors with the buffer length
if byteBufferLength < 0:
byteBufferLength = 0
return dataOK, frameNumber, detObj
# ------------------------------------------------------------------
# Funtion to update the data and display in the plot
def update():
dataOk = 0
global detObj
x = []
y = []
# Read and parse the received data
dataOk, frameNumber, detObj = readAndParseData16xx(Dataport, configParameters)
if dataOk and len(detObj["x"])>0:
#print(detObj)
x = -detObj["x"]
y = detObj["y"]
s.setData(x,y)
QtGui.QApplication.processEvents()
return dataOk
# ------------------------- MAIN -----------------------------------------
# Configurate the serial port
CLIport, Dataport = serialConfig(configFileName)
# Get the configuration parameters from the configuration file
configParameters = parseConfigFile(configFileName)
# START QtAPPfor the plot
app = QtGui.QApplication([])
# Set the plot
pg.setConfigOption('background','w')
win = pg.GraphicsLayoutWidget(title="2D scatter plot")
p = win.addPlot()
p.setXRange(-0.5,0.5)
p.setYRange(0,1.5)
p.setLabel('left',text = 'Y position (m)')
p.setLabel('bottom', text= 'X position (m)')
s = p.plot([],[],pen=None,symbol='o')
win.show()
# Main loop
detObj = {}
frameData = {}
currentIndex = 0
while True:
try:
# Update the data and check if the data is okay
dataOk = update()
if dataOk:
# Store the current frame into frameData
frameData[currentIndex] = detObj
currentIndex += 1
time.sleep(0.03) # Sampling frequency of 30 Hz
# Stop the program and close everything if Ctrl + c is pressed
except KeyboardInterrupt:
CLIport.write(('sensorStop\n').encode())
CLIport.close()
Dataport.close()
win.close()
break```
[1]: https://i.stack.imgur.com/BYLnW.png

Sending file over UDP divided into fragments

I have been dealing with sending file which is divided into fragments set by user on input. Problem is, I am getting error:
rec_list[fragIndex - 1] = data
IndexError: list assignment index out of range
I am also sending single string messages like in a chat and it works normally.
I can't find a bug in my code but maybe you can.
Btw, there are variables which might help with math which doesn't fit probably.
fragSize = 3
fragIndex = 216
fragCount = 215
Problem is, total number of fragments should be 215 (precalculated before sending - IS OK), index shouldn't be more than count! That is the problem. And it doesn't happen with strings. Only here with file.
Sending:
fragSize = int(input('Fragment size: ')) #max size of fragment
while True:
message = input('Enter message: ')
fragIndex=0 #reset fragment indexing
#asking for fragment size
if(message[:3] == '-sf'):
fragSize = int(input('Fragment size: '))
And here is sending function for files:
if (message[:2] == '-f'):
mType = 3
if message.startswith('-f'):
message = message[3:]
file_name = message
f=open(file_name,"rb")
contents = f.read()
fragCount = math.ceil(len(contents) / fragSize)
while contents!= '':
data = bytearray()
data.extend(contents[:fragSize])
fragIndex += 1
crc = crc32(data)
header = struct.pack('!hIIII', mType, fragSize, fragIndex, fragCount, crc)
self.sock.sendto(header + bytearray(data), (self.host, self.port))
contents = contents[fragSize:]
Receiving:
while True:
received_chunks = 0
rec_list = []
while True:
data, addr = sock.recvfrom(65535)
header = data[:18]
data = data[18:]
(mType, fragSize, fragIndex, fragCount, crc) = struct.unpack('!hIIII', header)
print(
'\nTyp: ' + str(mType) +
'\nFragSize: ' + str(fragSize) +
'\nFragIndex: ' + str(fragIndex) +
'\nFragCount: ' + str(fragCount) +
'\nCRC: ' + str(crc)
)
if len(rec_list) < fragCount:
need_to_add = fragCount - len(rec_list)
rec_list.extend([''] * need_to_add) # empty list for messages of size fragCount
rec_list[fragIndex - 1] = data
received_chunks += 1
if received_chunks == fragCount:
break # This is where the second while loop ends
This is only if I want to receive message of type file: (because it is divided into more message types)
if mType == 3:
content = b''.join(rec_list)
f = open('filename.py','wb')
f.write(content)
You tried to compare apples to oranges. Well, bytes to str but wikipedia doesn't say anything about that.
while contents!='':
...
contents is a bytes object and '' is a str object. In python 3, those two things can never be equal. Firing up the shell we see that
>>> b''==''
False
>>>
>>> contents = b"I am the very model"
>>> while contents != '':
... if not contents:
... print("The while didn't catch it!")
... break
... contents = contents[3:]
...
The while didn't catch it!
Since all objects have a truthiness (that is, bool(some_object) is meaningful) and bytes objects turn False when they are empty, you can just do
while contents:
....
UPDATE
Not part of the original answer but a question was raised about sending retries back to the client. The server side is sketched in here
while True:
received_chunks = 0
fragCount = -1
rec_list = []
while True:
# wait forever for next conversation
if fragCount == -1:
sock.settimeout(None)
try:
data, addr = sock.recvfrom(65535)
except socket.timeout:
# scan for blank slots in rec_list
retries = [i for i, data in rec_list if not data]
# packet is mType, numFrags, FragList
# TODO: I just invented 13 for retry mtype
sock.sendto(struct.pack("!{}h".format(len(retries+2)), 13,
len(retries), *retries)
continue
# our first packet, set timeout for retries
if fragCount == -1:
sock.settimeout(2)
header = data[:18]
data = data[18:]
(mType, fragSize, fragIndex, fragCount, crc) = struct.unpack('!hIIII', header)
print(
'\nTyp: ' + str(mType) +
'\nFragSize: ' + str(fragSize) +
'\nFragIndex: ' + str(fragIndex) +
'\nFragCount: ' + str(fragCount) +
'\nCRC: ' + str(crc)
)
if len(rec_list) < fragCount:
need_to_add = fragCount - len(rec_list)
rec_list.extend([''] * need_to_add) # empty list for messages of size fragCount
rec_list[fragIndex - 1] = data
received_chunks += 1
if received_chunks == fragCount:
break # This is where the second while loop ends

Categories

Resources