Examples
EEPROM-Content
Let’s say you want to create an eeprom content using OSER.
The content has the following structure:
Entry |
Type |
Position |
Description |
---|---|---|---|
type |
U8 |
0 |
the module type |
serial number |
String[9] |
1 .. 9 |
serial number: four upper case letters, a minus and four digits |
hardware-type |
U8 |
10 |
the hardware-type |
calibration |
F32[2] |
11 .. 18 |
calibration factors |
crc |
U32 |
12 .. 22 |
32-bit CRC, polynomial 0x1EDC6F41 |
All values are stored in big endian.
The following abstraction lets you create this mapping easily:
>>> from oser import ByteStruct, UBInt8, BFloat, RegularExpressionMatch, \
Array, CRCB32, to_hex
>>> class EEPROM(ByteStruct):
... def __init__(self, *args, **kwargs):
... ByteStruct.__init__(self, *args, **kwargs)
...
... self.type = UBInt8(0)
... self.serial_number = RegularExpressionMatch(pattern=r"[A-Z]{4}-[0-9]{4}", length=9, value=b"AAAA-0000")
... self.hardware_type = UBInt8(0)
... self.calibration = Array(length=2, prototype=BFloat)
... self.crc = CRCB32(strict=True, polynomial=0x1EDC6F41)
...
>>> eeprom = EEPROM()
>>> eeprom.type.set(3)
>>> eeprom.serial_number.set(b"ASDF-1337")
>>> eeprom.hardware_type.set(23)
>>> for ii in range(2):
... eeprom.calibration[ii].set((.1+ii)**3)
...
>>> binary = eeprom.encode()
>>> print(to_hex(binary))
0| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22
\x03\x41\x53\x44\x46\x2D\x31\x33\x33\x37\x17\x3A\x83\x12\x6F\x3F\xAA\x5E\x35\x3D\x10\xBB\xCB
>>> print(eeprom.introspect())
- - EEPROM():
0 \x03 type: 3 (UBInt8)
- - serial_number: RegularExpressionMatch():
1 \x41 'A'
2 \x53 'S'
3 \x44 'D'
4 \x46 'F'
5 \x2d '-'
6 \x31 '1'
7 \x33 '3'
8 \x33 '3'
9 \x37 '7'
10 \x17 hardware_type: 23 (UBInt8)
- - calibration: Array():
- - [
11 \x3a @0: 0.001 (BFloat)
12 \x83
13 \x12
14 \x6f
15 \x3f @1: 1.331 (BFloat)
16 \xaa
17 \x5e
18 \x35
- - ]
19 \x3d crc: 1024506827 (CRCB32)
20 \x10
21 \xbb
22 \xcb
You can now write this data into your eeprom.
Custom Network Protocol
You may want to create a custom network protocol for you device or software.
Because the message is transmitted via any serial connection
it starts with a magic number 0x23
. This is a U8
.
This magic number is followed by the destination address
and the source address. Both are U16
.
Additionally there is a service-id as U32
.
The service-id is followed by the total payload length as U16
without crc. This way
the transport-layer must not be aware of the protocol itself.
The payload consists of a type, a length and the data itself. The type has symbolic names:
0: string
1: list of 16-bit integers
2: list of floats
A frame ends with a 32-bit crc with polynomial 0x1EDC6F41.
All values are transmitted in big endian.
The following abstraction creates a frame for this protocol:
>>> from oser import ByteStruct, Constant, UBInt8, BFloat, UBInt16, UBInt32, \
... Enum, Array, Switch, String, CRCB32, to_hex
>>>
>>> a1 = Array(length=1, prototype=UBInt16)
>>> a2 = Array(length=2, prototype=BFloat)
>>>
>>> class SerialProtocol(ByteStruct):
... def __init__(self, *args, **kwargs):
... ByteStruct.__init__(self, *args, **kwargs)
...
... self.start_of_frame = Constant(UBInt8, 0x23)
... self.destination = UBInt16(0)
... self.source = UBInt16(0)
... self.service_id = UBInt32(0)
... self.payload_length = UBInt16(0)
... self.payload = Payload()
... self.crc = CRCB32(strict=True, polynomial=0x1EDC6F41)
...
... def encode(self, full_data=b"", context_data=b""):
... self.payload_length.set(self.payload.size())
... return super(SerialProtocol, self).encode(full_data, context_data)
...
>>> class Payload(ByteStruct):
... def __init__(self, *args, **kwargs):
... ByteStruct.__init__(self, *args, **kwargs)
...
... self.type = Enum(UBInt32,
... values={
... "string": 0,
... "u16list": 1,
... "f32list": 2,
... }, value="string")
... self.length = UBInt16(0)
... self.data = Switch(
... condition=lambda self: self.type.get(),
... values={
... "string": String(length=lambda self: self.length.get()),
... "u16list": Array(length=lambda self: self.length.get(), prototype=UBInt16),
... "f32list": Array(length=lambda self: self.length.get(), prototype=BFloat),
... })
...
>>> frame = SerialProtocol()
>>> frame.service_id.set(1337)
>>>
>>> # string
>>> frame.payload.type.set("string")
>>> frame.payload.length.set(10)
>>> frame.payload.data.set("abcdefghij")
>>>
>>> binary = frame.encode()
>>> print(frame)
SerialProtocol():
start_of_frame: 35 (UBInt8)
destination: 0 (UBInt16)
source: 0 (UBInt16)
service_id: 1337 (UBInt32)
payload_length: 16 (UBInt16)
payload: Payload():
type: 'string' (UBInt32)
length: 10 (UBInt16)
data: b'abcdefghij'
crc: 0x57c9544f (CRCB32)
>>> print(to_hex(binary))
0| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 30
\x23\x00\x00\x00\x00\x00\x00\x05\x39\x00\x10\x00\x00\x00\x00\x00\x0a\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x57\xc9\x54\x4f
>>> print(frame.introspect())
- - SerialProtocol():
0 \x23 start_of_frame: 35 (UBInt8)
1 \x00 destination: 0 (UBInt16)
2 \x00
3 \x00 source: 0 (UBInt16)
4 \x00
5 \x00 service_id: 1337 (UBInt32)
6 \x00
7 \x05
8 \x39
9 \x00 payload_length: 16 (UBInt16)
10 \x10
- - payload: Payload():
11 \x00 type: 0 (UBInt32)
12 \x00
13 \x00
14 \x00
15 \x00 length: 10 (UBInt16)
16 \x0a
- - data: String():
17 \x61 'a'
18 \x62 'b'
19 \x63 'c'
20 \x64 'd'
21 \x65 'e'
22 \x66 'f'
23 \x67 'g'
24 \x68 'h'
25 \x69 'i'
26 \x6a 'j'
27 \x57 crc: 0x57c9544f (CRCB32)
28 \xc9
29 \x54
30 \x4f
>>> # list of u16
>>> frame.payload.type.set("u16list")
>>> frame.payload.length.set(3)
>>> for ii in range(3):
... frame.payload.data[ii].set(ii)
...
>>> binary = frame.encode()
>>> print(frame)
SerialProtocol():
start_of_frame: 35 (UBInt8)
destination: 0 (UBInt16)
source: 0 (UBInt16)
service_id: 1337 (UBInt32)
payload_length: 12 (UBInt16)
payload: Payload():
type: 'u16list' (UBInt32)
length: 3 (UBInt16)
data: Array():
[
@0: 0 (UBInt16)
@1: 1 (UBInt16)
@2: 2 (UBInt16)
]
crc: 0x224b28ee (CRCB32)
>>> print(to_hex(binary))
0| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23| 24| 25| 26
\x23\x00\x00\x00\x00\x00\x00\x05\x39\x00\x0c\x00\x00\x00\x01\x00\x03\x00\x00\x00\x01\x00\x02\x22\x4b\x28\xee
>>> print(frame.introspect())
- - SerialProtocol():
0 \x23 start_of_frame: 35 (UBInt8)
1 \x00 destination: 0 (UBInt16)
2 \x00
3 \x00 source: 0 (UBInt16)
4 \x00
5 \x00 service_id: 1337 (UBInt32)
6 \x00
7 \x05
8 \x39
9 \x00 payload_length: 12 (UBInt16)
10 \x0c
- - payload: Payload():
11 \x00 type: 1 (UBInt32)
12 \x00
13 \x00
14 \x01
15 \x00 length: 3 (UBInt16)
16 \x03
- - data: Array():
- - [
17 \x00 @0: 0 (UBInt16)
18 \x00
19 \x00 @1: 1 (UBInt16)
20 \x01
21 \x00 @2: 2 (UBInt16)
22 \x02
- - ]
23 \x22 crc: 0x224b28ee (CRCB32)
24 \x4b
25 \x28
26 \xee
>>> # list of float
>>> frame.payload.type.set("f32list")
>>> frame.payload.length.set(2)
>>> for ii in range(2):
... frame.payload.data[ii].set(float(ii*1.5))
...
>>> binary = frame.encode()
>>> print(frame)
SerialProtocol():
start_of_frame: 35 (UBInt8)
destination: 0 (UBInt16)
source: 0 (UBInt16)
service_id: 1337 (UBInt32)
payload_length: 14 (UBInt16)
payload: Payload():
type: 'f32list' (UBInt32)
length: 2 (UBInt16)
data: Array():
[
@0: 0.0 (BFloat)
@1: 1.5 (BFloat)
]
crc: 0x4db8bf4 (CRCB32)
>>> print(to_hex(binary))
0| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28
\x23\x00\x00\x00\x00\x00\x00\x05\x39\x00\x0e\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x3f\xc0\x00\x00\x04\xdb\x8b\xf4
>>> print(frame.introspect())
- - SerialProtocol():
0 \x23 start_of_frame: 35 (UBInt8)
1 \x00 destination: 0 (UBInt16)
2 \x00
3 \x00 source: 0 (UBInt16)
4 \x00
5 \x00 service_id: 1337 (UBInt32)
6 \x00
7 \x05
8 \x39
9 \x00 payload_length: 14 (UBInt16)
10 \x0e
- - payload: Payload():
11 \x00 type: 2 (UBInt32)
12 \x00
13 \x00
14 \x02
15 \x00 length: 2 (UBInt16)
16 \x02
- - data: Array():
- - [
17 \x00 @0: 0.0 (BFloat)
18 \x00
19 \x00
20 \x00
21 \x3f @1: 1.5 (BFloat)
22 \xc0
23 \x00
24 \x00
- - ]
25 \x04 crc: 0x4db8bf4 (CRCB32)
26 \xdb
27 \x8b
28 \xf4
>>> #decode data
>>> data = b"\x23\x00\x00\x00\x00\x00\x00\x05\x39\x00\x1A\x00\x00\x00\x02\x00" \
... b"\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
... b"\x00\x00\x00\x00\x00\xA4\x58\x03\x64"
>>> frame.decode(data)
41
>>> print(frame)
SerialProtocol():
start_of_frame: 35 (UBInt8)
destination: 0 (UBInt16)
source: 0 (UBInt16)
service_id: 1337 (UBInt32)
payload_length: 26 (UBInt16)
payload: Payload():
type: 'f32list' (UBInt32)
length: 5 (UBInt16)
data: Array():
[
@0: 0.0 (BFloat)
@1: 0.0 (BFloat)
@2: 0.0 (BFloat)
@3: 0.0 (BFloat)
@4: 0.0 (BFloat)
]
crc: 0xa4580364 (CRCB32)
>>> print(frame.introspect())
- - SerialProtocol():
0 \x23 start_of_frame: 35 (UBInt8)
1 \x00 destination: 0 (UBInt16)
2 \x00
3 \x00 source: 0 (UBInt16)
4 \x00
5 \x00 service_id: 1337 (UBInt32)
6 \x00
7 \x05
8 \x39
9 \x00 payload_length: 26 (UBInt16)
10 \x1a
- - payload: Payload():
11 \x00 type: 2 (UBInt32)
12 \x00
13 \x00
14 \x02
15 \x00 length: 5 (UBInt16)
16 \x05
- - data: Array():
- - [
17 \x00 @0: 0.0 (BFloat)
18 \x00
19 \x00
20 \x00
21 \x00 @1: 0.0 (BFloat)
22 \x00
23 \x00
24 \x00
25 \x00 @2: 0.0 (BFloat)
26 \x00
27 \x00
28 \x00
29 \x00 @3: 0.0 (BFloat)
30 \x00
31 \x00
32 \x00
33 \x00 @4: 0.0 (BFloat)
34 \x00
35 \x00
36 \x00
- - ]
37 \xa4 crc: 0xa4580364 (CRCB32)
38 \x58
39 \x03
40 \x64
HTTP-Request
This example shows how to abstract a http request transmitted via TCP and IPv4.
First an ethernet frame must be constructed:
class EthernetFrame(ByteStruct):
def __init__(self, *args, **kwargs):
ByteStruct.__init__(self, *args, **kwargs)
self.destination = MacAddress(6)
self.source = MacAddress(6)
self.type = Enum(prototype=UBInt16, values={"IP" : 0x0800})
self.payload = Switch(condition=lambda self: self.type.get(),
values={
"IP" : InternetProtocolPayload(),
},
default=Null())
The MAC address is a oser.String
with little modifications for printing:
class MacAddress(String):
def get(self):
return ":".join(map(lambda c: f"{c:X}", super(MacAddress, self).get()))
Now the IPv4 payload must be constructed:
class InternetProtocolPayload(ByteStruct):
def __init__(self, *args, **kwargs):
ByteStruct.__init__(self, *args, **kwargs)
self.header = BitStruct()
self.header.version = Nibble(0)
self.header.ihl = Nibble(0) # ip header type
self.header.tos = BitStruct() # type of service
self.header.dscp = BitField(length=6) # differentiated service code point
self.header.ecn = BitField(length=2) # explicit congestion notification (ip flowcontrol)
self.header.total_length = BitField(length=16)
self.header.identification = BitField(length=16)
self.header.flags = BitField(length=3)
self.header.fragment_offset = BitField(length=13)
self.header.ttl = BitField(length=8)
self.protocol = Enum(UBInt8, values={"TCP" : 0x06})
self.header_checksum = UBInt16(0)
self.payload = Switch(condition=lambda self: self.protocol.get(),
values={
"TCP" : TransmissionControlProtocolPayload(),
})
And for TCP a payload must be constructed, too:
class TransmissionControlProtocolPayload(ByteStruct):
def __init__(self, *args, **kwargs):
ByteStruct.__init__(self, *args, **kwargs)
self.source_address = UBInt32(0)
self.destination_address = UBInt32(0)
self.source_port = UBInt16(0)
self.destination_port = UBInt16(0)
self.sequence_number = UBInt32(0)
self.acknowledgement_number = UBInt32(0)
self.offset_and_flags = BitStruct()
self.offset_and_flags.offset = BitField(length=4)
self.offset_and_flags.reserved = BitField(length=6)
self.offset_and_flags.urgent_flag = Flag()
self.offset_and_flags.acknowledgement_flag = Flag()
self.offset_and_flags.psh_flag = Flag()
self.offset_and_flags.rst_flag = Flag()
self.offset_and_flags.syn_flag = Flag()
self.offset_and_flags.fin_flag = Flag()
self.window = UBInt16()
self.checksum = UBInt16()
self.urgent_pointer = UBInt16()
self.options = Array(length=3, prototype=UBInt32)
self.payload = HTTPPayload(length=lambda self: self.up().header.total_length.get()-52)
The HTTP payload is a oser.String
with little modifications too. That helps to show
the plain text payload in a human readable way:
class HTTPPayload(String):
def _toString(self):
return "\n" + "\n".join(self.get().split("\r\n"))
To decode an http request use the following code (the data came from Wireshark. Right-click a packet -> Copy -> Bytes -> Hex Stream):
>>> frame = EthernetFrame()
>>> data = binascii.unhexlify(
... b"f4ec38c9b85438607713fa070800450003162ac740004006fabbc0a80003c163"
... b"9050ac2f005062b7938d1e3de4bb80187210156800000101080a0173bd0013d6"
... b"d56f474554202f20485454502f312e310d0a486f73743a2068656973652e6465"
... b"0d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a557365722d41"
... b"67656e743a204d6f7a696c6c612f352e3020285831313b204c696e7578207838"
... b"365f363429204170706c655765624b69742f3533352e313920284b48544d4c2c"
... b"206c696b65204765636b6f29204368726f6d652f31382e302e313032352e3136"
... b"32205361666172692f3533352e31390d0a4163636570743a20746578742f6874"
... b"6d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c6170706c696361"
... b"74696f6e2f786d6c3b713d302e392c2a2f2a3b713d302e380d0a416363657074"
... b"2d456e636f64696e673a20677a69702c6465666c6174652c736463680d0a4163"
... b"636570742d4c616e67756167653a2064652d44452c64653b713d302e382c656e"
... b"2d55533b713d302e362c656e3b713d302e340d0a4163636570742d4368617273"
... b"65743a2049534f2d383835392d312c7574662d383b713d302e372c2a3b713d30"
... b"2e330d0a436f6f6b69653a2077745f76743d3776303030253342367633357431"
... b"3430393539373433353731383b207774335f6569643d25334232383836383936"
... b"3336393230313734253743323134323531313732373230303232303339313b20"
... b"6f7074696d697a656c79456e645573657249643d6f6575313432383735373231"
... b"3735343972302e393837303834313034393132333535353b206f7074696d697a"
... b"656c795365676d656e74733d2537422532323232383632353038353825323225"
... b"3341253232676325323225324325323232333031313130373332253232253341"
... b"25323266616c7365253232253243253232323331363235303236342532322533"
... b"412532327365617263682532322537443b206f7074696d697a656c794275636b"
... b"6574733d25374225323232373435383230343039253232253341253232302532"
... b"322537443b207774335f7369643d253342323838363839363336393230313734"
... b"0d0a0d0a"
... )
>>> frame.decode(data)
804
>>> print(frame)
EthernetFrame():
destination: 'F4:EC:38:C9:B8:54'
source: '38:60:77:13:FA:7'
type: 'IP' (UBInt16)
payload: InternetProtocolPayload():
header: BitStruct():
version: 4 (Nibble)
ihl: 5 (Nibble)
tos: BitStruct():
dscp: 0 (BitField(6))
ecn: 0 (BitField(2))
total_length: 790 (BitField(16))
identification: 10951 (BitField(16))
flags: 2 (BitField(3))
fragment_offset: 0 (BitField(13))
ttl: 64 (BitField(8))
protocol: 'TCP' (UBInt8)
header_checksum: 64187 (UBInt16)
payload: TransmissionControlProtocolPayload():
source_address: 3232235523 (UBInt32)
destination_address: 3244527696 (UBInt32)
source_port: 44079 (UBInt16)
destination_port: 80 (UBInt16)
sequence_number: 1656198029 (UBInt32)
acknowledgement_number: 507372731 (UBInt32)
offset_and_flags: BitStruct():
offset: 8 (BitField(4))
reserved: 0 (BitField(6))
urgent_flag: False (Flag)
acknowledgement_flag: True (Flag)
psh_flag: True (Flag)
rst_flag: False (Flag)
syn_flag: False (Flag)
fin_flag: False (Flag)
window: 29200 (UBInt16)
checksum: 5480 (UBInt16)
urgent_pointer: 0 (UBInt16)
options: Array():
[
@0: 16844810 (UBInt32)
@1: 24362240 (UBInt32)
@2: 332846447 (UBInt32)
]
payload: b'GET / HTTP/1.1\r\nHost: heise.de\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\nCookie: wt_vt=7v000%3B6v35t1409597435718; wt3_eid=%3B288689636920174%7C2142511727200220391; optimizelyEndUserId=oeu1428757217549r0.9870841049123555; optimizelySegments=%7B%222286250858%22%3A%22gc%22%2C%222301110732%22%3A%22false%22%2C%222316250264%22%3A%22search%22%7D; optimizelyBuckets=%7B%222745820409%22%3A%220%22%7D; wt3_sid=%3B288689636920174\r\n\r\n'
>>> print(frame.introspect())
- - EthernetFrame():
- - destination: MacAddress():
0 \xf4 'ô'
1 \xec 'ì'
2 \x38 '8'
3 \xc9 'É'
4 \xb8 '¸'
5 \x54 'T'
- - source: MacAddress():
6 \x38 '8'
7 \x60 '`'
8 \x77 'w'
9 \x13 '\x13'
10 \xfa 'ú'
11 \x07 '\x07'
12 \x08 type: 2048 (UBInt16)
13 \x00
- - payload: InternetProtocolPayload():
- - header: BitStruct():
14.7 0 version: 4 (Nibble)
14.6 1
14.5 0
14.4 0
14.3 0 ihl: 5 (Nibble)
14.2 1
14.1 0
14.0 1
- - tos: BitStruct():
15.7 0 dscp: 0 (BitField(6))
15.6 0
15.5 0
15.4 0
15.3 0
15.2 0
15.1 0 ecn: 0 (BitField(2))
15.0 0
16.7 0 total_length: 790 (BitField(16))
16.6 0
16.5 0
16.4 0
16.3 0
16.2 0
16.1 1
16.0 1
17.7 0
17.6 0
17.5 0
17.4 1
17.3 0
17.2 1
17.1 1
17.0 0
18.7 0 identification: 10951 (BitField(16))
18.6 0
18.5 1
18.4 0
18.3 1
18.2 0
18.1 1
18.0 0
19.7 1
19.6 1
19.5 0
19.4 0
19.3 0
19.2 1
19.1 1
19.0 1
20.7 0 flags: 2 (BitField(3))
20.6 1
20.5 0
20.4 0 fragment_offset: 0 (BitField(13))
20.3 0
20.2 0
20.1 0
20.0 0
21.7 0
21.6 0
21.5 0
21.4 0
21.3 0
21.2 0
21.1 0
21.0 0
22.7 0 ttl: 64 (BitField(8))
22.6 1
22.5 0
22.4 0
22.3 0
22.2 0
22.1 0
22.0 0
23 \x06 protocol: 6 (UBInt8)
24 \xfa header_checksum: 64187 (UBInt16)
25 \xbb
- - payload: TransmissionControlProtocolPayload():
26 \xc0 source_address: 3232235523 (UBInt32)
27 \xa8
28 \x00
29 \x03
30 \xc1 destination_address: 3244527696 (UBInt32)
31 \x63
32 \x90
33 \x50
34 \xac source_port: 44079 (UBInt16)
35 \x2f
36 \x00 destination_port: 80 (UBInt16)
37 \x50
38 \x62 sequence_number: 1656198029 (UBInt32)
39 \xb7
40 \x93
41 \x8d
42 \x1e acknowledgement_number: 507372731 (UBInt32)
43 \x3d
44 \xe4
45 \xbb
- - offset_and_flags: BitStruct():
46.7 1 offset: 8 (BitField(4))
46.6 0
46.5 0
46.4 0
46.3 0 reserved: 0 (BitField(6))
46.2 0
46.1 0
46.0 0
47.7 0
47.6 0
47.5 0 urgent_flag: False (Flag)
47.4 1 acknowledgement_flag: True (Flag)
47.3 1 psh_flag: True (Flag)
47.2 0 rst_flag: False (Flag)
47.1 0 syn_flag: False (Flag)
47.0 0 fin_flag: False (Flag)
48 \x72 window: 29200 (UBInt16)
49 \x10
50 \x15 checksum: 5480 (UBInt16)
51 \x68
52 \x00 urgent_pointer: 0 (UBInt16)
53 \x00
- - options: Array():
- - [
54 \x01 @0: 16844810 (UBInt32)
55 \x01
56 \x08
57 \x0a
58 \x01 @1: 24362240 (UBInt32)
59 \x73
60 \xbd
61 \x00
62 \x13 @2: 332846447 (UBInt32)
63 \xd6
64 \xd5
65 \x6f
- - ]
- - payload: HTTPPayload():
66 \x47 'G'
67 \x45 'E'
68 \x54 'T'
69 \x20 ' '
70 \x2f '/'
71 \x20 ' '
72 \x48 'H'
73 \x54 'T'
74 \x54 'T'
75 \x50 'P'
76 \x2f '/'
77 \x31 '1'
78 \x2e '.'
79 \x31 '1'
%< %< %< %< %< %< %<
800 \x0d '\r'
801 \x0a '\n'
802 \x0d '\r'
803 \x0a '\n'
>>> binary = frame.encode()
>>> print(to_hex(binary))
0| 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 30| 31| 32| 33| 34| 35| 36| 37| 38| 39| 40| 41| 42| 43| 44| 45| 46| 47| 48| 49| 50| 51| 52| 53| 54| 55| 56| 57| 58| 59| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 70| 71| 72| 73| 74| 75| 76| 77| 78| 79| 80| 81| 82| 83| 84| 85| 86| 87| 88| 89| 90| 91| 92| 93| 94| 95| 96| 97| 98| 99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255|256|257|258|259|260|261|262|263|264|265|266|267|268|269|270|271|272|273|274|275|276|277|278|279|280|281|282|283|284|285|286|287|288|289|290|291|292|293|294|295|296|297|298|299|300|301|302|303|304|305|306|307|308|309|310|311|312|313|314|315|316|317|318|319|320|321|322|323|324|325|326|327|328|329|330|331|332|333|334|335|336|337|338|339|340|341|342|343|344|345|346|347|348|349|350|351|352|353|354|355|356|357|358|359|360|361|362|363|364|365|366|367|368|369|370|371|372|373|374|375|376|377|378|379|380|381|382|383|384|385|386|387|388|389|390|391|392|393|394|395|396|397|398|399|400|401|402|403|404|405|406|407|408|409|410|411|412|413|414|415|416|417|418|419|420|421|422|423|424|425|426|427|428|429|430|431|432|433|434|435|436|437|438|439|440|441|442|443|444|445|446|447|448|449|450|451|452|453|454|455|456|457|458|459|460|461|462|463|464|465|466|467|468|469|470|471|472|473|474|475|476|477|478|479|480|481|482|483|484|485|486|487|488|489|490|491|492|493|494|495|496|497|498|499|500|501|502|503|504|505|506|507|508|509|510|511|512|513|514|515|516|517|518|519|520|521|522|523|524|525|526|527|528|529|530|531|532|533|534|535|536|537|538|539|540|541|542|543|544|545|546|547|548|549|550|551|552|553|554|555|556|557|558|559|560|561|562|563|564|565|566|567|568|569|570|571|572|573|574|575|576|577|578|579|580|581|582|583|584|585|586|587|588|589|590|591|592|593|594|595|596|597|598|599|600|601|602|603|604|605|606|607|608|609|610|611|612|613|614|615|616|617|618|619|620|621|622|623|624|625|626|627|628|629|630|631|632|633|634|635|636|637|638|639|640|641|642|643|644|645|646|647|648|649|650|651|652|653|654|655|656|657|658|659|660|661|662|663|664|665|666|667|668|669|670|671|672|673|674|675|676|677|678|679|680|681|682|683|684|685|686|687|688|689|690|691|692|693|694|695|696|697|698|699|700|701|702|703|704|705|706|707|708|709|710|711|712|713|714|715|716|717|718|719|720|721|722|723|724|725|726|727|728|729|730|731|732|733|734|735|736|737|738|739|740|741|742|743|744|745|746|747|748|749|750|751|752|753|754|755|756|757|758|759|760|761|762|763|764|765|766|767|768|769|770|771|772|773|774|775|776|777|778|779|780|781|782|783|784|785|786|787|788|789|790|791|792|793|794|795|796|797|798|799|800|801|802|803
\xf4\xec\x38\xc9\xb8\x54\x38\x60\x77\x13\xfa\x07\x08\x00\x45\x00\x03\x16\x2a\xc7\x40\x00\x40\x06\xfa\xbb\xc0\xa8\x00\x03\xc1\x63\x90\x50\xac\x2f\x00\x50\x62\xb7\x93\x8d\x1e\x3d\xe4\xbb\x80\x18\x72\x10\x15\x68\x00\x00\x01\x01\x08\x0a\x01\x73\xbd\x00\x13\xd6\xd5\x6f\x47\x45\x54\x20\x2f\x20\x48\x54\x54\x50\x2f\x31\x2e\x31\x0d\x0a\x48\x6f\x73\x74\x3a\x20\x68\x65\x69\x73\x65\x2e\x64\x65\x0d\x0a\x43\x6f\x6e\x6e\x65\x63\x74\x69\x6f\x6e\x3a\x20\x6b\x65\x65\x70\x2d\x61\x6c\x69\x76\x65\x0d\x0a\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x58\x31\x31\x3b\x20\x4c\x69\x6e\x75\x78\x20\x78\x38\x36\x5f\x36\x34\x29\x20\x41\x70\x70\x6c\x65\x57\x65\x62\x4b\x69\x74\x2f\x35\x33\x35\x2e\x31\x39\x20\x28\x4b\x48\x54\x4d\x4c\x2c\x20\x6c\x69\x6b\x65\x20\x47\x65\x63\x6b\x6f\x29\x20\x43\x68\x72\x6f\x6d\x65\x2f\x31\x38\x2e\x30\x2e\x31\x30\x32\x35\x2e\x31\x36\x32\x20\x53\x61\x66\x61\x72\x69\x2f\x35\x33\x35\x2e\x31\x39\x0d\x0a\x41\x63\x63\x65\x70\x74\x3a\x20\x74\x65\x78\x74\x2f\x68\x74\x6d\x6c\x2c\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x68\x74\x6d\x6c\x2b\x78\x6d\x6c\x2c\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x6d\x6c\x3b\x71\x3d\x30\x2e\x39\x2c\x2a\x2f\x2a\x3b\x71\x3d\x30\x2e\x38\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x45\x6e\x63\x6f\x64\x69\x6e\x67\x3a\x20\x67\x7a\x69\x70\x2c\x64\x65\x66\x6c\x61\x74\x65\x2c\x73\x64\x63\x68\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x4c\x61\x6e\x67\x75\x61\x67\x65\x3a\x20\x64\x65\x2d\x44\x45\x2c\x64\x65\x3b\x71\x3d\x30\x2e\x38\x2c\x65\x6e\x2d\x55\x53\x3b\x71\x3d\x30\x2e\x36\x2c\x65\x6e\x3b\x71\x3d\x30\x2e\x34\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x43\x68\x61\x72\x73\x65\x74\x3a\x20\x49\x53\x4f\x2d\x38\x38\x35\x39\x2d\x31\x2c\x75\x74\x66\x2d\x38\x3b\x71\x3d\x30\x2e\x37\x2c\x2a\x3b\x71\x3d\x30\x2e\x33\x0d\x0a\x43\x6f\x6f\x6b\x69\x65\x3a\x20\x77\x74\x5f\x76\x74\x3d\x37\x76\x30\x30\x30\x25\x33\x42\x36\x76\x33\x35\x74\x31\x34\x30\x39\x35\x39\x37\x34\x33\x35\x37\x31\x38\x3b\x20\x77\x74\x33\x5f\x65\x69\x64\x3d\x25\x33\x42\x32\x38\x38\x36\x38\x39\x36\x33\x36\x39\x32\x30\x31\x37\x34\x25\x37\x43\x32\x31\x34\x32\x35\x31\x31\x37\x32\x37\x32\x30\x30\x32\x32\x30\x33\x39\x31\x3b\x20\x6f\x70\x74\x69\x6d\x69\x7a\x65\x6c\x79\x45\x6e\x64\x55\x73\x65\x72\x49\x64\x3d\x6f\x65\x75\x31\x34\x32\x38\x37\x35\x37\x32\x31\x37\x35\x34\x39\x72\x30\x2e\x39\x38\x37\x30\x38\x34\x31\x30\x34\x39\x31\x32\x33\x35\x35\x35\x3b\x20\x6f\x70\x74\x69\x6d\x69\x7a\x65\x6c\x79\x53\x65\x67\x6d\x65\x6e\x74\x73\x3d\x25\x37\x42\x25\x32\x32\x32\x32\x38\x36\x32\x35\x30\x38\x35\x38\x25\x32\x32\x25\x33\x41\x25\x32\x32\x67\x63\x25\x32\x32\x25\x32\x43\x25\x32\x32\x32\x33\x30\x31\x31\x31\x30\x37\x33\x32\x25\x32\x32\x25\x33\x41\x25\x32\x32\x66\x61\x6c\x73\x65\x25\x32\x32\x25\x32\x43\x25\x32\x32\x32\x33\x31\x36\x32\x35\x30\x32\x36\x34\x25\x32\x32\x25\x33\x41\x25\x32\x32\x73\x65\x61\x72\x63\x68\x25\x32\x32\x25\x37\x44\x3b\x20\x6f\x70\x74\x69\x6d\x69\x7a\x65\x6c\x79\x42\x75\x63\x6b\x65\x74\x73\x3d\x25\x37\x42\x25\x32\x32\x32\x37\x34\x35\x38\x32\x30\x34\x30\x39\x25\x32\x32\x25\x33\x41\x25\x32\x32\x30\x25\x32\x32\x25\x37\x44\x3b\x20\x77\x74\x33\x5f\x73\x69\x64\x3d\x25\x33\x42\x32\x38\x38\x36\x38\x39\x36\x33\x36\x39\x32\x30\x31\x37\x34\x0d\x0a\x0d\x0a
>>> print(len(binary))
804
Access Members By Name
To access members by name call getattr()
to get the member and call
oser.ByteType.set()
on the result.
>>> from oser import ByteStruct, ULInt8
>>> class Foo(ByteStruct):
... def __init__(self):
... super(Foo, self).__init__()
... self.a = ULInt8(1)
...
>>> foo = Foo()
>>> name = "a"
>>> getattr(foo, name).set(24)
>>> print(foo.introspect())
- - Foo():
0 \x18 a: 24 (ULInt8)
>>> print(foo.a == 24)
True