platform_driver.interfaces package

Driver Development

New drivers are implemented by subclassing BaseInterface.

While it is possible to create an Agent which handles communication with a new device it will miss out on the benefits of creating a proper interface for the Platform Driver Agent.

Creating an Interface for a device allows users of the device to automatically benefit from the following platform features:

  • Existing Agents can interact with the device via the Actuator Agent without any code changes.

  • Configuration follows the standard form of other devices. Existing and future tools

    for configuring devices on the platform will work with the new device driver.

  • Historians will automatically capture data published by the new device driver.

  • Device data can be graphed in VOLTTRON Central in real time.

  • If the device can receive a heartbeat signal the driver framework can be configured to

    automatically send a heartbeat signal.

  • When the configuration store feature is rolled out the device can by dynamically configured

    through the platform.

Creating a New Interface

To create a new device driver create a new module in the PlatformDriverAgent.platform_driver.interfaces package. The name of this module will be the name to use in the “driver_type” setting in a driver configuration file in order to load the new driver.

In the new module create a subclass of BaseInterface called Interface.

The Interface class must implement the following methods:

These methods are required but can be implemented using the BasicRevert mixin.

Each point on the device must be represented by an instance of the BaseRegister. Create one or more subclasses of BaseRegister as needed to represent the points on a device.

Interface Configuration and Startup

When processing a driver configuration file the Platform Driver Agent will use the “driver_type” setting to automatically find and load the appropriate Interface class for the desired driver.

After loading the class the Platform Driver Agent will call BaseInterface.configure() with the contents of the “driver_config” section of the driver configuration file parsed into a python dictionary and the contents of the file referenced in “registry_config” entry.

BaseInterface.configure() must setup register representations of all points on a device by creating instances of BaseRegister (or a subclass) and adding them to the Interface with BaseInterface.insert_register().

After calling BaseInterface.configure() the Platform Driver Agent will use the created registers to create meta data for each point on the device.

Device Scraping

The work scheduling and publish periodic device scrapes is handled by the Platform Driver Agent. When a scrape starts the Platform Driver Agent calls the BaseInterface.scrape_all(). It will take the results of the call and attach meta data and and publish as needed.

Device Interaction

Requests to interact with the device via any method supported by the platform are routed to the correct Interface instance by the Platform Driver Agent.

Most commands originate from RPC calls to the Actuator Agent and are forwarded to the Platform Driver Agent.

Registers

The Platform Driver Agent uses the BaseInterface.get_register_names() and BaseInterface.get_register_by_name() methods to get registers to setup meta data.

This means that its a requirement to use the BaseRegister class to store information about points on a devices.

Using the BasicRevert Mixin

If the device protocol has no support for reverting to a default state an Interface this functionality can be implemented with the BasicRevert mixin.

When using the BasicRevert mixin you must specify it first in the list of parent classes, otherwise it won’t Python won’t detect that the BaseInterface.revert_point() and BaseInterface.revert_all() have been implemented.

If desired the BasicRevert.set_default() can be used by the Interface class to set values for each point to revert to.

class platform_driver.interfaces.BaseInterface(vip=None, core=None, **kwargs)[source]

Bases: object

Main class for implementing support for new devices.

All interfaces must subclass this.

Parameters
  • vip – A reference to the PlatformDriverAgent vip subsystem.

  • core – A reference to the parent driver agent’s core subsystem.

build_register_map()[source]
abstract configure(config_dict, registry_config_str)[source]

Configures the Interface for the specific instance of a device.

Parameters
  • config_dict (dict) – The “driver_config” section of the driver configuration file.

  • registry_config_str (str) – The contents of the registry configuration file.

This method must setup register representations of all points on a device by creating instances of BaseRegister (or a subclass) and adding them to the Interface with BaseInterface.insert_register().

get_multiple_points(path, point_names, **kwargs)[source]

Read multiple points from the interface.

Parameters
  • path (str) – Device path

  • point_names ([str]) – Names of points to retrieve

  • kwargs (dict) – Any interface specific parameters

Returns

Tuple of dictionaries to results and any errors

Return type

(dict, dict)

abstract get_point(point_name, **kwargs)[source]

Get the current value for the point name given.

Parameters
  • point_name (str) – Name of the point to retrieve.

  • kwargs – Any interface specific parameters.

Returns

Point value

get_register_by_name(name)[source]

Get a register by it’s point name.

Parameters

name (str) – Point name of register.

Returns

An instance of BaseRegister

Return type

BaseRegister

get_register_names()[source]

Get a list of register names. :return: List of names :rtype: list

get_register_names_view()[source]

Get a dictview of register names. :return: Dictview of names :rtype: dictview

get_registers_by_type(reg_type, read_only) List[BaseRegister][source]

Get a list of registers by type. Useful for an Interface that needs to categorize registers by type when doing a scrape.

Parameters
  • reg_type (str) – Register type. Either “bit” or “byte”.

  • read_only (bool) – Specify if the desired registers are read only.

Returns

An list of BaseRegister instances.

Return type

list

insert_register(register)[source]

Inserts a register into the Interface.

Parameters

register (BaseRegister) – Register to add to the interface.

abstract revert_all(**kwargs)[source]

Revert entire device to it’s default state

Parameters

kwargs – Any interface specific parameters.

abstract revert_point(point_name, **kwargs)[source]

Revert point to it’s default state.

Parameters

kwargs – Any interface specific parameters.

abstract scrape_all()[source]

Method the Platform Driver Agent calls to get the current state of a device for publication.

Returns

Point names to values for device.

Return type

dict

set_multiple_points(path, point_names_values, **kwargs)[source]

Set multiple points on the interface.

Parameters
  • path (str) – Device path

  • point_names_values – Point names and values to be set to.

  • kwargs (dict) – Any interface specific parameters

Returns

Dictionary of points to any exceptions raised

Return type

dict

abstract set_point(point_name, value, **kwargs)[source]

Set the current value for the point name given.

Implementations of this method should make a reasonable effort to return the actual value the point was set to. Some protocols/devices make this difficult. (I’m looking at you BACnet) In these cases it is acceptable to return the value that was requested if no error occurs.

Parameters
  • point_name (str) – Name of the point to retrieve.

  • value – Value to set the point to.

  • kwargs – Any interface specific parameters.

Returns

Actual point value set.

class platform_driver.interfaces.BaseRegister(register_type, read_only, pointName, units, description='')[source]

Bases: object

Class for containing information about a point on a device. Should be extended to support the device protocol to be supported.

The member variable python_type should be overridden with the equivalent python type object. Defaults to int. This is used to generate meta data.

Parameters
  • register_type (str) – Type of the register. Either “bit” or “byte”. Usually “byte”.

  • read_only (bool) – Specify if the point can be written to.

  • pointName (str) – Name of the register.

  • units (str) – Units of the value of the register.

  • description (str) – Description of the register.

The Platform Driver Agent will use BaseRegister.get_units() to populate metadata for publishing. When instantiating register instances be sure to provide a useful string for the units argument.

get_description()[source]
Returns

Register description

Return type

str

get_register_python_type()[source]
Returns

The python type of the register.

Return type

type

get_register_type()[source]
Returns

(register_type, read_only)

Return type

tuple

get_units()[source]
Returns

Register units

Return type

str

class platform_driver.interfaces.BasicRevert(**kwargs)[source]

Bases: object

A mixin that implements the BaseInterface.revert_all() and BaseInterface.revert_point() methods on an Interface.

It works by tracking change to all writable points until a set_point call is made. When this happens the point is marked dirty and the previous value is remembered. When a point is reverted via either a revert_all or revert_point call the dirty values are set back to the clean value using the BasicRevert._set_point() method.

As it must hook into the setting and scraping of points it implements the BaseInterface.scrape_all() and BaseInterface.set_point() methods. It then adds BasicRevert._set_point() and BasicRevert._scrape_all() to the abstract interface. An existing interface that wants to use this class can simply mix it in and rename it’s set_point and scrape_all methods to _set_point and _scrape_all respectively.

An BaseInterface may also override the detected clean value with its own value to revert to by calling BasicRevert.set_default(). While default values can be set anytime they should be set in the BaseInterface.configure() call.

revert_all(**kwargs)[source]

Implementation of BaseInterface.revert_all()

Calls BasicRevert._set_point() with point_name and the value to revert the point to for every writable point on a device.

Currently **kwargs is ignored.

revert_point(point_name, **kwargs)[source]

Implementation of BaseInterface.revert_point()

Revert point to its default state.

Calls BasicRevert._set_point() with point_name and the value to revert the point to.

Parameters

point_name (str) – Name of the point to revert.

Currently **kwargs is ignored.

scrape_all()[source]

Implementation of BaseInterface.scrape_all()

set_default(point, value)[source]

Set the value to revert a point to.

Parameters
  • point (str) – name of point to set.

  • value – value to set the point to.

set_point(point_name, value)[source]

Implementation of BaseInterface.set_point()

Passes arguments through to BasicRevert._set_point()

exception platform_driver.interfaces.DriverInterfaceError[source]

Bases: Exception

class platform_driver.interfaces.RevertTracker[source]

Bases: object

A helper class for tracking the state of writable points on a device.

clear_dirty_point(point)[source]

Clears the dirty flag on a point.

Parameters

point (str) – Name of dirty point flag to clear.

get_all_revert_values()[source]

Returns a dict of points to revert values.

If no default is set use the clean value, otherwise returns the default value.

If no default value is set and a no clean values have been submitted a point value will be an instance of DriverInterfaceError.

Parameters

point (str) – Name of point to get.

Returns

Values to revert to.

Return type

dict

get_revert_value(point)[source]

Returns the clean value for a point if no default is set, otherwise returns the default value.

If no default value is set and a no clean values have been submitted raises DriverInterfaceError.

Parameters

point (str) – Name of point to get.

Returns

Value to revert to.

mark_dirty_point(point)[source]

Sets the dirty flag on a point.

Ignores points with a default value.

Parameters

point (str) – Name of point flag to dirty.

set_default(point, value)[source]

Set the value to revert a point to. Overrides any clean value detected.

Parameters
  • point (str) – name of point to set.

  • value – value to set the point to.

update_clean_values(points)[source]

Update all state of all the clean point values for a device.

If a point is marked dirty it will not be updated.

Parameters

points (dict) – dict of point names to values.

Subpackages