PyChapter10¶
PyChapter10 is an open source pure Python library for reading and writing IRIG 106 Chapter 10 (now 11) files.
Library Overview¶
Basic Structure & Usage¶
PyChapter10 makes every effort to provide a pythonic interface to Chapter 10 data as in the following example:
for packet in C10('file.c10'):
for message in packet:
print(message.rtc)
The top-level C10 object represents a given Chapter 10 file or stream and can be initialized from file or filename (default) or from bytes/string using the from_string method. C10 objects contain Packet objects of various data types (see API reference above). Packets attributes containing parsed/generated packet information and generally consist of a number of messages which can be iterated over and modified in turn.
All of these types and classes respond to the usual python introspection resources such as help() and dir().
Modifying Data¶
Calling bytes() on a packet will compile the packet header, CSDW (channel specific data word), and body (including messages) to raw bytes. You can modify packets and messages before dumping to bytes and those changes will be reflected in the resulting bytes object. For example:
for msg in ethernet_packet:
msg.ethernet_speed = 3
out_file.write(bytes(ethernet_packet))
Generating Data from Scratch¶
You can also generate your own data. By creating a packet object of the intended type and passing header values (or even CSDW and data) as keyword arguments:
messages = ...
p = EthernetF0(count=10)
for message in messages:
p.append(EthernetF0.Message(data=message, length=len(message)))
Defining Data Types¶
Data formats are specified using a wrapper around bitstruct. Every data type has a channel specific data word (CSDW) that may look something like this (Ethernet given as an example):
class EthernetF0(packet.Packet):
# ...
csdw_format = BitFormat('''
u16 count
p9
u3 ttb
u4 format''')
Similar to a C struct fields are specified with a type (uint by default) and bit length. “p” signifies padding or “reserved” as the chapter 10 standard may call it. Various data types will also specify the format of the messages they contain be that 1553, ethernet, etc. Going back to the Ethernet example:
class EthernetF0(packet.Packet):
# ...
class Message(packet.Message):
# ...
def __repr__(self):
return '<Ethernet frame %s bytes>' % len(self.data)
FORMAT = BitFormat('''
u64 ipts
u14 length
u1 data_length_error
u1 data_crc_error
u8 network_id
u1 crc_error
u1 frame_error
u2 content
u4 ethernet_speed''')
Now we have the intra-packet/message header defined and since it includes a “length” field the appropriate number of bytes are read each time we get a new message. We also define a “__repr__” function to help with debugging.
Contributing¶
Feedback, issues, and pull requests are all welcome on the main repo. See the CONTRIBUTING document in github for more details. If you’re not sure where to get started check out the issue tracker on github.