Table Of Contents

3. The base field

Base abstract class for all BitPacket fields.

API reference: Field

The Field class is the abstract root class for all other BitPacket classes. Initially, a field only has a name and no value. Field subclasses must provide field details, such as the size of the field, the implementation of how the field value will look like, that is, how the field should be built, and other field related details.

3.1. Naming fields

The most simple field accessor is its name. A field name is built upon creation but can be changed at run-time (special care should be taken, though). It is recommended to follow python variable naming when assigning a name to a field. This is because with the Container subclass (and its subclasses) fields can be accessed directly as class members.

Note: changing the field name at run-time is not recommended unless you know what you are doing.

3.2. Building and parsing fields

The main purpose of BitPacket is to provide an easy way to represent packets (or, say it another way, data structures). In BitPacket, packets can be built from and to an string of bytes, arrays and streams.

A field subclass, then, needs to provide the following methods:

def value():_

This method returns the actual value of the field, whatever that is, a number, a string, etc.:

def set_value(value):_

This method sets a new value to the current field. The value might be a number, a string, etc. depending on the field’s type:

def size():_

This method must return the field’s size. Note that some fields are bit-oriented, so the method might return values for different units (basically, bits and bytes):

def str_value():_

This method must return the text string representation for the given field:

def str_hex_value():_

This method must return the hexadecimal string representation for the given field. That is, how the field looks like in memory. For example, for a float value, the hexadecimal representation could bbe the bytes forming the IEEE-754 representation:

def str_eng_value():_

This method must return the text string representation of the result obtained after applying the field’s calibration curve. Therefore, it is necessary to call the calibration curve of the field first and then return the result (after applying any extra desired formatting):

def _encode(stream):_

This method will write the field’s value into the given stream (byte or bit oriented):

def _decode(stream):_

This method will convert the given stream (byte or bit oriented) into the internal field representation.

3.3. Calibration curves

Sometimes a field might need to be expressed in another way, or a calculation might be necessary to determine the final value of the field. Consider, for example, a numeric field that represents a temperature with a 16-bit precision and covers a range from 0 to 50 celsius degrees. The calibration curve comes in handy by letting the user to specify this conversion function:

def set_calibration_curve(self, curve):_

This method lets the user to provide a function to compute the calibration curve. The function must be unary taking the field’s value as it’s argument and computing (using a the desired conversion function) a result.

For the temperature example mentioned above, the calibration function could be something like:

def temp_conv(x):
    return (x / 65535.0) * 50.0