This page presents the base API that one needs to implement to add support for new sensors or actuators.
This API can only be used to implement drivers for single sensors (this limitation is due to the fact that the base API only allows the driver to define a single Feature of Interest (FOI) and a single sensor description). This means that a driver implementing only the base API would have to be instantiated N times to connect to a network of N sensors. Fortunately, SensorHub also defines an extension to the base sensor API allowing one to write drivers that can wrap sensor networks of any size within a single module. Please see the Sensor Network API page for more details.
When implementing the base sensor API, each new sensor (or actuator) driver is composed of at least 4 classes:
- An implementation of the
- Zero or more implementations of
ISensorDataInterface(at least one for a sensor)
- Zero or more implementations of
ISensorControlInterface(at least one for an actuator)
- An extension of the
- An implementation of the
Details about these different classes are given in the next sections.
Note: Several sensor drivers can be packaged in a single Maven module, although we encourage this only if the drivers are very closely related and/or have tight inter-dependencies.
ISensorModule interface is the top-level one to be implemented by sensor drivers. It provides methods for:
- Getting the SensorML description of an installed sensor or actuator
- Getting the feature of interest (FOI) currently observed by the sensor
- Checking for the presence of the device
- Subscribing for high level sensor events (activation, connection, etc.)
- Giving access to the sensor measurement outputs and control inputs
The main functions of the sensor module are shown on the figure below:
Each data interface is an output that gives access to a stream of sensor measurements and is an implementation of
ISensorDataInterface. Data interfaces are asynchornous in the sense that each of them can produce data at a different rate.
Each control interface is an input that can receive commands and is an implementation of
ISensorControlInterface. Each control input can receive different types of command messages.
A sensor module implementation must also provide the description of the sensor as a SensorML process (any class derived from
AbstractProcess is acceptable). Usually, this sensor description is a mix between information auto-generated by the driver and information provided as a SensorML file by the user. Versioning and updating the sensor description can be optionnally supported by the driver.
In order to help you implement the API, we provide the
AbstractSensorModule class that is a simple partial implementation of
ISensorModule and can be used as the base for most sensor modules. It provides default implementations of most methods in the API.
Data produced by each output must be made available by an implementation of
ISensorDataInterface that provides methods for:
- Describing the data structure of each measurement record
- Reading data produced by a sensor (poll mode)
- Subscribing for data produced by a sensor (push mode)
- Discovery methods allowing to advertise if push and storage are supported
The measurement record description must be provided as a tree of SWE Common data components (DataRecord, DataArray, Quantity, Time, Count, etc.). This structure will automatically be used to populate the output section of the SensorML description.
A recommended encoding must also be defined which is usually text for simple measurements and some binary flavor for imagery, video and other multi-dimensionnal datasets.
These components and encodings are provided by the lib-swe-common module.
All data streamed through the same data interface must be synchronous and time-tagged together.
AbstractSensorOutput class is provided to reduce redundant code and help you get started. It is a basic partial implementation of
ISensorDataInterface that can be used as the base for most sensor modules.
Commands can be sent to the sensor via implementations of
ISensorControlInterface that provides methods for:
- Sending commands to the sensor/actuator (synchronous or asynchronous)
- Scheduling commands to be sent asynchronously and/or at specific times
- Subscribing to events related to a command that is executed asynchronously
AbstractSensorControl class is provided to reduce redundant code and help you get started. It is a basic partial implementation of
ISensorControlInterface that can be used as the base for most sensor modules.
A configuration class derived from SensorConfig must be provided with the new driver. This class is used as a struct that contain public fields carrying the configuration of the sensor module.
All public fields in this class are used to automatically generate the administration user interface of this particular driver. Nesting configuration classes is supported.
You can use the
DisplayInfo annotation to give hints to the UI renderer, by providing:
- A more readable label (if non is provided, the label is automatically derived from the field name)
- A description that will show up in a popup
AbstractSensorModule class can serve as a base to develop most sensor drivers. It provides default implementation for the following aspects:
- Keeping maps of outputs and command inputs. Derived classes should thus call the
- Generation of SensorML description (more details are given below)
However, there is no default support for:
- Updating the sensor description from outside the driver (except by changing the base SensorML file)
- Maintaining a history of sensor descriptions (this is because, by default, this feature is better handled by the persistence layer in SensorHub).
AbstractSensorModule class returns false in the two methods reporting support of these functionalities.
Default workflow for generating the SensorML description
The default workflow shown on the figure below illustrates the way the current sensor decription is generated when you derive a concrete driver implementation from
Output, control inputs and configuration parameter descriptions are actually defined by concrete driver implementation but appending to SensorML is done in
Autogenerated content is usually info obtained directly from sensor hardware (e.g. serial number, etc.) and/or internal driver state (e.g. depending on commands received)
Like any SensorHub module, a sensor driver must implement a class derived from this interface to become discoverable.