python BCD format into Struct - python

I have the below code in CPP that I am trying to port to Python to send data to a UDPS
#define VERSION_MAIN "V6.60"
#define VERSION_BIN_MAJOR 0x06
#define VERSION_BIN_MINOR 0x60
unsigned char temp[3];
temp[0] = VERSION_MAIN[0];
temp[1] = VERSION_BIN_MAJOR;
temp[2] = VERSION_BIN_MINOR;
I have tried code like the following:
byteone = bytes(VERSION_MAIN, 'utf-8')
hex_string = '0x06'
decimal_int = int(hex_string, 16)
decimal_string = str(decimal_int)
digits = [int(c) for c in decimal_string]
zero_padded_BCD_digits = [format(d, '04b') for d in digits]
s = ''.join(zero_padded_BCD_digits)
bytetwo = bytes(int(s[i : i + 8], 2) for i in range(0, len(s), 8))
hex_string = '0x60'
decimal_int = int(hex_string, 16)
decimal_string = str(decimal_int)
digits = [int(c) for c in decimal_string]
zero_padded_BCD_digits = [format(d, '04b') for d in digits]
s = ''.join(zero_padded_BCD_digits)
bytethree = bytes(int(s[i : i + 8], 2) for i in range(0, len(s), 8))
values = (byteonw,bytetwo,bytethree )
s= struct.Struct(f'!3B')
packed_data = s.pack(*values)
but I keep getting pesky errors
struct.error: required argument is not an integer
Can anyone give me a hand please.
Thanks

No need to convert V into an int, pack can manage the char type as well.
from struct import pack
VERSION_MAIN = "V6.60"
VERSION_BIN_MAJOR = 0x06
VERSION_BIN_MINOR = 0x60
version = pack("!c2B", VERSION_MAIN[0].encode('utf-8'), VERSION_BIN_MAJOR, VERSION_BIN_MINOR)
# version = b'V\x06`'

Related

How to pass multiple pointer to C function using python

I am attempting to access a function in a C file using Python ctypes. The code is below.
class PacketInfo_t(Structure):
_fields_ = [("pPayload",c_char_p),
("Payload_len",c_uint),
("usSrcPort",c_ushort),
("usDstPort",c_ushort),
("unSrcIP",c_uint),
("unDstIP",c_uint),
("enDirection",c_uint)
]
def func(self):
packets = [(packet,direction) for packet, direction in self.flow.packets]
c_packets = []
packet_num = len(packets)
packet_info_p_array = (POINTER(PacketInfo_t) * packet_num)()
for i,(packet,dire) in enumerate(packets):
if "TCP" in packet:
sport = packet["TCP"].sport
dport = packet["TCP"].dport
payload = packet["TCP"].payload
elif "UDP" in packet:
sport = packet["UDP"].sport
dport = packet["UDP"].dport
payload = packet["UDP"].payload
cpayload=cast(bytes(payload), c_char_p)
if dire == PacketDirection.FORWARD:
int_dire = 0
else:
int_dire = 1
# print sport in python
print("sport in python : ", sport)
packet_info_value = [cpayload,
c_uint(len(payload)),
c_ushort(sport),
c_ushort(dport),
c_uint(ip2long(packet["IP"].src)),
c_uint(ip2long(packet["IP"].dst)),
c_uint(int_dire)]
packet_obj = PacketInfo_t(*packet_info_value)
packet_info_p_array[i] = pointer(packet_obj)
# pdb.set_trace()
print("before into C function, pram's address is ", byref(packet_info_p_array))
print("before into C function, packet_num is ", packet_num)
res = solib.Check_MKCP(byref(packet_info_p_array), packet_num)
return res
The processing object of the program is the network flow, which contains a lot of data packets.
int func_C(PacketInfo_t ** ppPacketInfo, int nPacket){
int i = 0;
unsigned int payload_len = 0;
unsigned int tmplen,f;
unsigned char *payload;
// address
printf("ppPacketInfo's address is %p\n", ppPacketInfo);
printf("start func_C function! nPacket = %u\n", nPacket);
for(i=0;i<nPacket;i++){
payload_len = ppPacketInfo[i]->Payload_len;
// print sport in C
printf("sport = %u\n",ppPacketInfo[i]->usSrcPort);
if(payload_len != 0){
break;
}
}
...
}
But The content of multiple pointer is different in python and C code. image:
enter image description here
Why does this problem occur and how should I solve or think about it?
The minimal case can be download by https://drive.google.com/file/d/1Pkca1J0kJmTd5jp1HkCAxCCsQY2wlUOY/view?usp=sharing

Why is my hash value off did I do something wrong with my code?

I am writing a SHA256 Hash function and it's mostly complete but when I run the code the hash is way to high and it's not correct. What is wrong with my code that's making it far off from the actual value to be? Now keep in mind I do not have a chunk loop so it might look a bit different. This also A GUI as well.
#VARIABLES
FF = (1 >> 32)-1
#Right rotate
def rr(a,b):
return((a >> b) | (a << (32 - b))) & FF
h0 = 0x6a09e667
h1 = 0xbb67ae85
h2 = 0x3c6ef372
h3 = 0xa54ff53a
h4 = 0x510e527f
h5 = 0x9b05688c
h6 = 0x1f83d9ab
h7 = 0x5be0cd19
#Messages
word_Hash = "1: Please write below what\n word you would like to hash."
words = []
playerinput = []
varwords = [word_Hash]
#FUNCTIONS
count = 0
def SHA256():
global playerinput, wordtohash, A, B, C, D, E, F, G, H
#get input
wordtohash = playerinput.pop(0)
#convert to binary
BinaryConversion = ''.join(format(ord(i), '08b') for i in wordtohash) + "1"
#pad helped by Dr.Glynn, Maple
if len(BinaryConversion) <= 512:
count = len(BinaryConversion)
while count <= 448:
BinaryConversion = BinaryConversion + "0"
count += 1
wordtohash = len(wordtohash)
endofpad = int(wordtohash) * 8
numberofzeros = 0
while numberofzeros < 63 - int(len(bin(endofpad)[2:])):
BinaryConversion = BinaryConversion + "0"
numberofzeros += 1
#BinaryConversion = (BinaryConversion) + str(endofpad)
BinaryConversion = str(BinaryConversion) + str(bin(endofpad)[2:])
#numbers = len(BinaryConversion)
#print(BinaryConversion)
#first 16 messages
w = [int('0b'+BinaryConversion[0:31], 2),
int('0b'+BinaryConversion[32:63], 2),
int('0b'+BinaryConversion[64:95],2),
int('0b'+BinaryConversion[96:127],2),
int('0b'+BinaryConversion[128:159],2),
int('0b'+BinaryConversion[160:191],2),
int('0b'+BinaryConversion[192:223],2),
int('0b'+BinaryConversion[224:255],2),
int('0b'+BinaryConversion[256:287],2),
int('0b'+BinaryConversion[288:319],2),
int('0b'+BinaryConversion[320:351],2),
int('0b'+BinaryConversion[352:383],2),
int('0b'+BinaryConversion[384:415],2),
int('0b'+BinaryConversion[416:447],2),
int('0b'+BinaryConversion[448:479],2),
int('0b'+BinaryConversion[480:511],2)]
#Message Scedule
#rest of the messages
for c in range(16,64):
S0 = rr(w[c-15], 7) ^ rr(w[c-15], 18) ^ (w[c-15] >> 3)
S1 = rr(w[c - 2], 17) ^ rr(w[c - 2], 19) ^ (w[c - 2] >> 10)
w.append((w[c - 16] + S0 + w[c-7] + S1) & FF)
print(w)
A = h0
B = h1
C = h2
D = h3
E = h4
F = h5
G = h6
H = h7
for i in range(64):
s1 = rr(E, 6) ^ rr(E, 11) ^ rr(E, 25)
ch = (E & F) ^ (~E & G)
temp1 = H + s1 + ch + K[i] + w[i]
s0 = rr(A, 2) ^ rr(A, 13) ^ rr(A, 22)
maj = (A & B) ^ (A & C) ^ (B & C)
temp2 = s0 + maj
H = G
G = F
F = E
E = D + temp1
D = C
C = B
B = A
A = temp1 + temp2
A = hex(A)[2:]
B = hex(B)[2:]
C = hex(C)[2:]
D = hex(D)[2:]
E = hex(E)[2:]
F = hex(F)[2:]
G = hex(G)[2:]
H = hex(H)[2:]
print(A)
def finish():
global count, varwords, playerinput, words
if count >= 1:
screenframe1.pack_forget()
frm_screen2.pack()
SHA256()
lbl_story["text"] = "Your word is {}\n Your hash value is {}{}{}{}{}{}{}{}".format(wordtohash,A,B,C,D,E,F,G,H)

Converting RIJNDAEL 256 function from .Net to Python

Can someone please help me with converting this code?
I tried to make RIJNDAEL256 function out of this code:
EncryptRJ256("lkirwf897+22#bbtrm8814z5qq=498j5", "741952hheeyy66#cs!9hjv887mxx7#8y", "A padded string to BLOCKSIZE length.")
Public Function EncryptRJ256(ByVal prm_key As String, ByVal prm_iv As String, ByVal prm_text_to_encrypt As String) As String
Dim s As String = prm_text_to_encrypt
Dim managed2 As New RijndaelManaged With {
.Padding = PaddingMode.Zeros,
.Mode = CipherMode.CBC,
.BlockSize = 256
}
Dim stream As New MemoryStream
Dim stream2 As New CryptoStream(stream, managed2.CreateEncryptor(Encoding.ASCII.GetBytes(prm_key), Encoding.ASCII.GetBytes(prm_iv)), CryptoStreamMode.Write)
Dim bytes As Byte() = Encoding.ASCII.GetBytes(s)
stream2.Write(bytes, 0, bytes.Length)
stream2.FlushFinalBlock()
Return Convert.ToBase64String(stream.ToArray)
End Function
I need the output of the encrypted string to be something like this:
Dv0Y/AFXdFMlDrcldFCu8v5o9zAlLNgyM+vO+PFeSrpO8Ve82mdUcc4rkzp9afDYc75NmkSd4mdflt38kceOdA==
A padded string to BLOCKSIZE length
I came up with this but the output is invalid. It's probably because of wrong padding but I have no idea how to fix it:
from rijndael.cipher.crypt import new
from rijndael.cipher.blockcipher import MODE_CBC
import base64
PADDING = b'.'
def r_pad(payload, block_size=32):
return payload + (block_size - len(payload) % block_size) * PADDING
KEY = 'lkirwf897+22#bbtrm8814z5qq=498j5'
IV = '741952hheeyy66#cs!9hjv887mxx7#8y'
plain_text = "A padded string to BLOCKSIZE length."
rjn = new(KEY, MODE_CBC, IV, blocksize=32)
encd = rjn.encrypt(r_pad(plain_text))
data = base64.b64encode(encd)
print(data)
rjn = new(KEY, MODE_CBC, IV, blocksize=32)
data = base64.b64decode(data)
decd = rjn.decrypt(r_pad(data))
print (decd)
This is the output:
Dv0Y/AFXdFMlDrcldFCu8v5o9zAlLNgyM+vO+PFeSrqWdzP1S1cumviFiEjNAjz5njnMMC9lfxsBl71x5y+xCw==
A padded string to BLOCKSIZE length.............................Å¿:è°⌐┘n┤«╞Px╜:æC┬♣╬Q┤▼«U_♦â☻ìr
How silly of me! Here's what fixed my issue:
from rijndael.cipher.crypt import new
from rijndael.cipher.blockcipher import MODE_CBC
import base64
PADDING = b'\x00'
def pad(payload, block_size=32):
return payload + (block_size - len(payload) % block_size) * PADDING
def un_pad(payload):
return payload.replace(PADDING, '')
KEY = 'lkirwf897+22#bbtrm8814z5qq=498j5'
IV = '741952hheeyy66#cs!9hjv887mxx7#8y'
plain_text = "A padded string to BLOCKSIZE length."
rjn = new(KEY, MODE_CBC, IV, blocksize=32)
encd = rjn.encrypt(pad(plain_text))
data = base64.b64encode(encd)
print(data)
rjn = new(KEY, MODE_CBC, IV, blocksize=32)
data = base64.b64decode(data)
decd = rjn.decrypt(un_pad(data))
print (decd)

How to send both integers and floats in the correct way for serial (write) communication in Python 2.7

I'm struggling with serial write communication. Basically I don't know which option to choose to combine both integers and float values in the correct way for serial write.
The problem: I need to send data values (chars,int, floats) to a microcontroller (ARM8 processor) for control of wheels for a robot platform. By means of a RS422 to USB converter I'm able to read data values from the same microcontroller, by means of this Python code:
import serial
from struct import unpack
# Initialization
counter = 0
#open serial for reading (BMW to PC communication)
s_port = 'COM8'
b_rate = 460800
ser = serial.Serial(port=s_port,baudrate=b_rate,timeout=0.01)
#method for reading incoming bytes on serial
while counter<20:
data = ser.readline()
data = data.encode("hex")
strlen = len(data)
rev_data = "".join(reversed([data[i:i+2] for i in range(0, len(data), 2)]))
if strlen==80:
Soh = data[0:2]
Nob = data[2:4]
Adr = data[4:6]
Cmd = data[6:8]
Hrt = data[8:12]
Po1 = data[12:28]
Po2 = data[28:44]
En1 = data[44:60]
En2 = data[60:76]
Crc = data[76:78]
Eot = data[78:80]
So1 = unpack('B', Soh.decode("hex")) # unsigned char
No1 = unpack('B', Nob.decode("hex")) # unsigned char
Ad1 = unpack('B', Adr.decode("hex")) # unsigned char
Cm1 = unpack('B', Cmd.decode("hex")) # unsigned char
Hr1 = unpack('h', Hrt.decode("hex")) # short
Po1 = unpack('d', Po1.decode("hex")) # double
Po2 = unpack('d', Po2.decode("hex")) # double
En1 = unpack('d', En1.decode("hex")) # double
En2 = unpack('d', En2.decode("hex")) # double
Cr1 = unpack('B', Crc.decode("hex")) # unsigned char
Eo1 = unpack('B', Eot.decode("hex")) # unsigned char
StartOfHeader = So1[0]
NoOfBytes = No1[0]
Address = Ad1[0]
Command = Cm1[0]
Heartbeat = Hr1[0]
Potentiometer1 = Po1[0]
Potentiometer2 = Po2[0]
Encoder1 = En1[0]
Encoder2 = En2[0]
CRC = Cr1[0]
EndOfTransmission = Eo1[0]
counter = counter+1
ser.close()
In Labview the serial write communication is already working, so that is my starting point:
But as I need to work with Python the trick is to make it working in Python.
To my knowledge the data is converted to ASCII, based on the "Type Cast" function in Labview (http://digital.ni.com/public.nsf/allkb/287D59BAF21F58C786256E8A00520ED5)
Honestly I don't nothing about ASCII messages, so I'm not 100% sure.
Now, I want to do the same trick for the serial write in Python 2.7. Starting from chr,int, float values converting to hexadecimal string and then write to the serial port. I suppose to use an ASCII conversion at the end, but I don't know if it's ASCII and the right Python command to do the conversion in the right way.
This is my serial write coding in Python so far (excuse me, for the long and inefficient coding lines):
# Initialization
counter = 0
#open serial for reading (BMW to PC communication)
s_port = 'COM9'
b_rate = 460800
ser = serial.Serial(port=s_port,baudrate=b_rate,timeout=0.05)
#method for writing to serial
while counter<100:
Soh = chr(1)
Nob = chr(46)
Adr = chr(49)
Cmd = chr(32)
DFS = float(1)
DRS = float(2)
DFD = int(3)
DRD = int(4)
DFC = int(5)
DRC = int(6)
SFCP = float(7)
SRCP = float(8)
SFC = int(9)
SRC = int(10)
CRC = chr(77)
EOT = chr(4)
S1 = Soh.encode("hex")
N1 = Nob.encode("hex")
A1 = Adr.encode("hex")
C1 = Cmd.encode("hex")
D11 = hex(struct.unpack('<I', struct.pack('<f', DFS))[0])
D1 = D11[2:]
D12 = hex(struct.unpack('<I', struct.pack('<f', DRS))[0])
D2 = D12[2:]
D3 = '{0:08x}'.format(DFD)
D4 = '{0:08x}'.format(DRD)
D5 = '{0:08x}'.format(DFC)
D6 = '{0:08x}'.format(DRC)
S11 = hex(struct.unpack('<I', struct.pack('<f', SFCP))[0])
S2 = S11[2:]
S12 = hex(struct.unpack('<I', struct.pack('<f', SRCP))[0])
S3 = S12[2:]
S4 = '{0:08x}'.format(SFC)
S5 = '{0:08x}'.format(SRC)
C2 = CRC.encode("hex")
E1 = EOT.encode("hex")
hex_string = E1 + C2 + S5 + S4 + S3 + S2 + D6 + D5 + D4 + D3 + D2 + D1 + C1 + A1 + N1 + S1
rev_hex_string = "".join(reversed([hex_string[i:i+2] for i in range(0, len(hex_string), 2)]))
##command = ...
ser.write(command)
counter = counter+1
ser.close()
This Python code generates the same hexadecimal string (called rev_hex_string) as the Labview programm. But till now, I was unable to do the serial write with Python.
I don't know how to proceed. Do I need ASCII for serial write? And which Python codes to use? encode("ascii"), decode("hex")? I'm totally lost in the many possibilities....
In case I use encode("ascii") or decode("hex") in Python it only generates a " .01" (ASCII???) message.
When I switch the normal view in Labview it has a much longer message:
" .01 €? # | - à# A M"
(I still missing some characters, but this is the most)
Besides that; do I need carriage returns and/or buffer flushing?
I have to say I'm new to serial write communication. I hope you can help me.
Sorry for the long post, I hope to be as precise as possible.

Parse C-like declarations using pyparsing

I would like to parse declarations using pyparsing in a C-like source (GLSL code) such that I get a list of (type, name, value).
For example:
int a[3];
int b=1, c=2.0;
float d = f(z[2], 2) + 3*g(4,a), e;
Point f = {1,2};
I would like to obtain something like:
[ ('int', 'a[3]', ''),
('int', 'b', '1'),
('int', 'c', '2.0'),
('float', 'd', 'f(z[2], 2) + 3*g(4,a)'),
('float', 'e', ''),
('Point', 'f', '{1,2}') ]
I've played with Forward() and operatorPrecedence() to try to parse the rhs expression but I suspect it is not necessary in my case.
So far I have:
IDENTIFIER = Regex('[a-zA-Z_][a-zA-Z_0-9]*')
INTEGER = Regex('([+-]?(([1-9][0-9]*)|0+))')
EQUAL = Literal("=").suppress()
SEMI = Literal(";").suppress()
SIZE = INTEGER | IDENTIFIER
VARNAME = IDENTIFIER
TYPENAME = IDENTIFIER
VARIABLE = Group(VARNAME.setResultsName("name")
+ Optional(EQUAL + Regex("[^,;]*").setResultsName("value")))
VARIABLES = delimitedList(VARIABLE.setResultsName("variable",listAllMatches=True))
DECLARATION = (TYPENAME.setResultsName("type")
+ VARIABLES.setResultsName("variables", listAllMatches=True) + SEMI)
code = """
float a=1, b=3+f(2), c;
float d=1.0, e;
float f = z(3,4);
"""
for (token, start, end) in DECLARATION.scanString(code):
for variable in token.variable:
print token.type, variable.name, variable.value
but the last expression (f=z(3,4)) is not parsed because of the ,.
There is a C struct parser on the pyparsing wiki that might give you a good start.
This seems to work.
IDENTIFIER = Word(alphas+"_", alphas+nums+"_" )
INT_DECIMAL = Regex('([+-]?(([1-9][0-9]*)|0+))')
INT_OCTAL = Regex('(0[0-7]*)')
INT_HEXADECIMAL = Regex('(0[xX][0-9a-fA-F]*)')
INTEGER = INT_HEXADECIMAL | INT_OCTAL | INT_DECIMAL
FLOAT = Regex('[+-]?(((\d+\.\d*)|(\d*\.\d+))([eE][-+]?\d+)?)|(\d*[eE][+-]?\d+)')
LPAREN, RPAREN = Literal("(").suppress(), Literal(")").suppress()
LBRACK, RBRACK = Literal("[").suppress(), Literal("]").suppress()
LBRACE, RBRACE = Literal("{").suppress(), Literal("}").suppress()
SEMICOLON, COMMA = Literal(";").suppress(), Literal(",").suppress()
EQUAL = Literal("=").suppress()
SIZE = INTEGER | IDENTIFIER
VARNAME = IDENTIFIER
TYPENAME = IDENTIFIER
OPERATOR = oneOf("+ - * / [ ] . & ^ ! { }")
PART = nestedExpr() | nestedExpr('{','}') | IDENTIFIER | INTEGER | FLOAT | OPERATOR
EXPR = delimitedList(PART, delim=Empty()).setParseAction(keepOriginalText)
VARIABLE = (VARNAME("name") + Optional(LBRACK + SIZE + RBRACK)("size")
+ Optional(EQUAL + EXPR)("value"))
VARIABLES = delimitedList(VARIABLE.setResultsName("variables",listAllMatches=True))
DECLARATION = (TYPENAME("type") + VARIABLES + SEMICOLON)
code = """
int a[3];
int b=1, c=2.0;
float d = f(z[2], 2) + 3*g(4,a), e;
Point f = {1,2};
"""
for (token, start, end) in DECLARATION.scanString(code):
vtype = token.type
for variable in token.variables:
name = variable.name
size = variable.size
value = variable.value
s = "%s / %s" % (vtype,name)
if size: s += ' [%s]' % size[0]
if value: s += ' / %s' % value[0]
s += ";"
print s

Categories