Multiple Sensor Configuration File

liveserial can handle multiple serial ports simultaneously, as well as multiple sensor streams per serial port. Since each device can have a different data format arriving at the serial port, we need a way for the user to specify what to expect for each sensor.

An example file is in the repo (see sensors.cfg).

Sensor Configuration Options

Each sensor has its own section and should be labelled [sensor.name], where name is the user-defined sensor name. This sensor name is also used as the name for the CSV files that are generated by the logging. Then, the following possible options can be specified as key=value pairs:

  • key text that identifies this sensor when it is part of a multi-sensor stream on a single port.
  • format comma-separated list of python data types (str, int, float) and key to specify the column location that the key will be at.
  • port name of the serial port on the local machine that this sensor’s data will arive at.
  • label for plotting, what label to include on the y axis.
  • value_index when multiple columns are present, a comma-separated list of column indices (0-based) that will be used for plotting. These columns will be included on the same subplot of the figure. They can be labelled using the legends option (described below).
  • logging comma-separated list of 0-based column indices to include in the log file generated for this sensor.
  • columns comma-separated list of custom column names to use in the CSV files. There should be the same number of entries in logging and columns.
  • legends comma-separated list of legend labels for cases where more than one index is specified in value_index.

Note

if a key is not specified, then one will be auto-generated using the id() of the ComMonitorThread object instance assigned to the port where the data originated from.

Note

for the value_index and logging options, they are zero-based. However, the zero index is reserved for the timestamp of the local computer. You can reference it in these options using 0.

Since the config file format is extensible, it is easy to add additional options later on. The default ConfigParser is used to extract the sections (sensors) and their options.

Aggregate Sensor Types

In addition to physical sensors on serial ports, we can also plot aggregate information for multiple sensors. For example, suppose we know that the sum of two sensor values should be conserved, then we could configure an aggregate sensor to take the sum of the two physical sensor values.

[sensor.total]
port=aggregate
label=Total Sensor
value_index=1,2
sensors=cardio,weight
function=sum
legends=I,F
columns=isum,fsum

This takes the total of cardio and weight physical sensor values and sums them (each column is summed separately) to create a new, aggregate sensor called total. The columns in the CSV file are labeled isum and fsum respectively and the plotting will show two lines on the subplot, with legend labels of I and F.

Port Configuration Options

In addition to the sensor configuration, port configuration can be specified using the same config-file format. Port sections are named [port.portname], where portname is the name of the local port (should exist in the results returned by enumerate_serial_ports()). The following options are possible:

  • port_baud: Rate at which information is transferred in a communication channel (in bits/second). Default 9600.
  • port_stopbits: Serial communication parameter; one of (1, 1.5, 2). Default 1.
  • port_parity: Serial communication parameter; one of [‘N’, ‘E’, ‘O’, ‘M’, ‘S’]. Default N.
  • port_timeout: The timeout used for reading the COM port. If this value is low, the thread will return data in finer grained chunks, with more accurate timestamps, but it will also consume more CPU. Default 0.01.
  • virtual: when True, additional serial port parameters are set so that the monitor can work with socat or other virtual ports. Default 0.
  • encoding: by default, we assume the encoding on the serial port to be UTF-8. If it is different, then specify the encoding here; a common alternative option is ASCII, though we have also seen UTF-16 before.
  • delimiter: by default, we assume whitespace separated values on each line of the serial stream. If you use , or | or something else, specify it here. The value is interpreted as regular expression (hence the default valued of s).

Script Configuration Options

Any of the options that can be passed as command-line arguments to the script can also be set in the configuration file under the [global] section heading. These are documented internally in the livemon.py script and can be seen by executing livemon.py -h.

liveserial.livemon.script_options Default script parameter arguments.

dict – default command-line arguments and their argparse.ArgumentParser.add_argument() keyword arguments.

  • refresh: How often (in milliseconds) to plot new data obtained from the serial port. Default: 100 (int).
  • method: Specifies how buffered data is aggregated each time it is read from the serial port. Default: average (str).Must be one of [‘last’, ‘average’]
  • maxpts: Maximum number of values to keep in the plot for each sensor Default: 100 (int).
  • config: Specify a configuration file to get sensor setup information from. Default: None (str).
  • sensors: Filter the list of sensors being logged/plotted. Default: all (str).
  • noplot: Don’t plot the data; only log it. Default: None (bool).
  • parity: Serial communication parameter. Default: N (str).Must be one of [‘N’, ‘E’, ‘O’, ‘M’, ‘S’]
  • buffertime: How often (in milliseconds) to query buffered data obtained from the serial port. Default: 25 (float).
  • ort: Name of the port(s) to plot/log. Default: None (str).
  • wait: Number of seconds to wait before failing because no data is present on the stream for plotting. Default: 1.0 (float).
  • timeout: The timeout used for reading the COM port. If this value is low, the thread will return data in finer grained chunks, with more accurate timestamps, but it will also consume more CPU. Default: 0.01 (float).
  • listen: Prints the raw output from the serial port instead of plotting and logging it. Useful for debugging port connection issues. Default: None (bool).
  • autoconf: Runs in automatic mode by loading a configuration file in the current directory called ‘sensors.cfg’. Default: None (bool).
  • stopbits: Serial communication parameter. Default: 1.0 (float).Must be one of [1, 1.5, 2]
  • baudrate: Rate at which information is transferred in a communication channel (in bits/second). Default: 9600 (int).
  • logdir: Path to the directory where sensor data will be logged. Default: None (str).
  • window: Width of window in time units. Default: 20.0 (float).
  • logfreq: How often (in seconds) to save the buffered data points to CSV. Default: 10 (float).
  • virtual: Specifies that the port being connected to is virtual (e.g., with socat), which changes the parameters for connection. Default: None (bool).

Plotting Configuration Options

matplotlib is used for plotting the live serial feeds. Within that framework, we have the following support:

  • figure: describes options that are passed as keyword arguments to figure() when the plot is initialized.
  • axes: keyword arguments passed to add_subplots(), which can override initialization behavior of the axes.
  • label: keyword arguments passed to set_xlabel() and set_ylabel(). They can format the font-size, color, etc. of the axes labels on the subplots.
  • ticks: keyword arguments passed to tick_params() once the plot has been initialized to format the ticks on the subplots.
  • animation: option for controlling the animation class used by matplotlib. Currently, only the blit option is supported. It takes a value of 1 if blitting should be enabled.

To override the keyword arguments, specify an option in a section (labelled [plot.figure], [plot.axes], [plot.label] or [plot.ticks]) that has the same name as the keyword argument and then the new value. For example, to override the font size on the axes labels, I would use fontsize=12 in a [plot.label] section of the configuration file.

Note that we do not cast the string values from the config file except in the case of figsize for the figure options. However, for most of the useful matplotlib keywords, this is not a problem since instead of a number like 12, matplotlib accepts strings with units (e.g., 12pt) which can be parsed. For strings without units specified, it will also usually interpret the string using whatever the default units are for the method/function call.

Configuration Objects

Method for sharing global sensor and port configuration values between modules.

class liveserial.config.Sensor(monitor, name, key=None, value_index=None, dtype=['key', 'int', 'float'], label=None, port=None, logging=None, columns=None, legends=None, function=None, sensors=None, **kwargs)[source]

Represents the configuration of a sensor on the serial port.

Parameters:
  • monitor (ComMonitorThread) – parent instance that this sensor is being logged with.
  • name (str) – name of the sensor in the configuration file.
  • key (str) – sensor key as it will be written to the serial stream, or None if there isn’t a key in the stream (i.e., only values).
  • value_index (list) – column index/indices of the value that will be plotted.
  • dtype (list) – of str or type; items must belong to [‘key’, int, float, str]. Represents the order in which values are found in a single line of data read from the serial port. Thus W 129229 0.928379 would be given by [“key”, int, float].
  • label (str) – for plots, what to put on the y-axis. Defaults to name.
  • port (str) – name of the port to read this sensor from. Defaults to ComMonitorThread.port.
  • logging (str) – comma-separated list of columns indices (zero-based) to include in the log file. If not specified, then the default is to include all data columns in the log file.
  • columns (str) – comma-separated list of columns headings for the CSV file; these are written in the first row of the file. If excluded, they default to Time and Value1, Value2, etc.
  • legends (str) – if the comma-separated list in value_index includes more than one index, multiple lines are plotted on the same subplot. In that case, legends allows a comma-separated list of legend labels to be provided for each of those lines.
  • sensors (str) – comma-separated list of sensor names to include in the data vector that will be passed to function to be aggregated to a single value. This only applies to the case of aggregate sensors.
  • function (str) – name of a function to use to transform the data. Only applies to the case of aggregate sensors.
  • kwargs (dict) – additional keyword arguments supported that do not require special processing (i.e., are just simple string values).
options

dict – additional keyword arguments (or configurable options) for the sensor.

parse(raw)[source]

Parses a single line read from the serial port and returns a tuple of values.

Parameters:raw (list) – of split ASCII-encoded strings from the serial port.
Returns:of values parsed using Sensor.dtype casting. None: if the key was not found in the correct location.
Return type:list
liveserial.config.plot(config, element)[source]

Returns the matplotlib configuration options for the specified plotting element.

Parameters:
  • config (ConfigParser) – instance from which to extract the port information. str is also allowed, in which case it should be the path to the config file to load.
  • element (str) – one of [‘line’, ‘axes’, ‘figure’, ‘label’, ‘ticks’]; specifies which part of the plot the options will apply to.
liveserial.config.portdefaults = {'port_baud': 9600, 'port_stopbits': 1, 'encoding': 'UTF-8', 'virtual': False, 'port_timeout': 0.01, 'delimiter': '\\s', 'port_parity': 'N'}

dict – default parameters passed to the serial.Serial constructor for communicating with the serial port.

liveserial.config.ports(config, port)[source]

Returns the port configuration dictionary for the specified port name.

Parameters:
  • config (ConfigParser) – instance from which to extract the port information. str is also allowed, in which case it should be the path to the config file to load.
  • port (str) – name of the port to return configuration for.
liveserial.config.reset_config()[source]

Resets the global config variables so that a session can be continued with a new config file.

liveserial.config.script(config)[source]

Returns the config options configured globally for the script.

Parameters:config (ConfigParser) – instance from which to extract the port information. str is also allowed, in which case it should be the path to the config file to load.
liveserial.config.sensors(config, sensor=None, port=None, monitor=None)[source]

Returns the list of liveserial.config.Sensor instances that have the specified port.

Parameters:
  • config (ConfigParser) – instance from which to extract the sensor list and port information. str is also allowed, in which case it should be the path to the config file to load.
  • port (str) – name of the port to configure for.