from ctypes import Structure,c_uint8,Union import struct class saej1939_message_id(Structure): #_fields_ = [('data_page',c_uint8,1),#does work correct with inversed bit fields #('extended_data_page',c_uint8,1), #('priority',c_uint8,3), #('reserved',c_uint8,3), #('pdu_format',c_uint8), #('pdu_specific',c_uint8), #('source_address',c_uint8), #] #output with reversed bit fields #python test_structure.py #1c000003 #(0, 0, 0, 0, 3, 7) _fields_ = [('reserved',c_uint8,3),#does not work correct but is common c notation afaik ('priority',c_uint8,3), ('extended_data_page',c_uint8,1), ('data_page',c_uint8,1), ('pdu_format',c_uint8), ('pdu_specific',c_uint8), ('source_address',c_uint8) ] #output with common c notation #python test_structure.py #38000003 #(0, 0, 0, 0, 3, 7) def __init__(self,prio=None, pgn=None, da = None, sa=None): self.reserved = 0 self.priority = 0 self.extended_data_page = 0 self.data_page = 0 self.pdu_format = 0 self.pdu_specific = 0 self.source_address = 0 if prio: self.priority = prio if pgn: if pgn < 0xF000: self.pdu_format = pgn >> 8 if da: self.pdu_specific = da else: self.pdu_specific = 0xFF else: self.pdu_format = (pgn >> 8) & 0xFF self.pdu_specific = pgn & 0xFF if sa: self.source_address = sa def from_integer(self,msg_id): msg_union = saej1939_message_id_union() if isinstance(msg_id,int): msg_id_as_bytes = struct.pack('>I',msg_id) elif isinstance(msg_id,bytes): msg_id_as_bytes = msg_id else: raise NotImplementedError('expected integer as msg_id') assert(len(msg_id_as_bytes) == 4) for idx,b in enumerate(msg_id_as_bytes): msg_union.bytes[idx] = b return msg_union.obj def to_integer(self): msg_union = saej1939_message_id_union() msg_union.obj = self msg_id_as_bytes = bytearray() for i in range(len(msg_union.bytes)): msg_id_as_bytes.append(msg_union.bytes[i]) msg_id_as_int = struct.unpack('>I',msg_id_as_bytes)[0] return msg_id_as_int class saej1939_message_id_union(Union): _fields_ = [('bytes',c_uint8*4), ('obj',saej1939_message_id), ] if __name__ == '__main__': a = saej1939_message_id(prio=7, pgn=0, da=0, sa=3) print('{0:08x}'.format(a.to_integer())) print( a.extended_data_page, a.data_page, a.pdu_format, a.pdu_specific, a.source_address, a.priority)