OpenADMS Node Modules
=====================
The logic of the OpenADMS Node application is outsourced to several modules in
the directory ``modules/``. New features can be added to the monitoring system
by writing additional modules. Each module must be loaded before it can be used.
+-------------------------------------+--------------------------------------------------------+-----+
| **Database** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`couch-driver` | Database connectivity for Apache CouchDB. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Export** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`cloud-exporter` | Exports observations to an OpenADMS Server instance. | 0.8 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`file-exporter` | Exports observations to flat files in CSV format. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`real-time-publisher` | Distributes observations in real time over MQTT. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Notification** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`alerter` | Collects alert messages. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`alert-message-formatter` | Formats alert messages (e-mail, SMS, IRC, etc.). | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`cloud-agent` | Sends messages to an OpenADMS Server instance. | 0.8 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`heartbeat` | Sends heartbeats to an OpenADMS Server instance. | 0.8 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`irc-agent` | Sends messages to an Internet Relay Chat network. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`mail-agent` | Sends e-mails via SMTP. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`mastodon-agent` | Sends “toots” to the Mastodon social network. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`rss-agent` | Exports alert messages as RSS feed. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`short-message-agent` | Sends short messages to an TCP/IP-based SMS gateway. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Port** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`bluetooth-port` | Experimental communication with Bluetooth. | 0.5 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`serial-port` | Serial port communication (RS-232/RS-422/RS-485). | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Processing** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`pre-processor` | Extracts values from raw observation responses. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`response-value-inspector` | Validates observation responses. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`return-code-inspector` | Checks the return codes of Leica Geosystems sensors. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`unit-converter` | Converts units of observation response values. | 0.5 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Prototype** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`prototype` | Blueprint for new OpenADMS module. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Raspberry Pi** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`interrupt-counter` | Counts interrupts on a GPIO pin of the Raspberry Pi. | 0.5 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Schedule** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`scheduler` | General scheduling of observations. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Server** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`local-control-server` | Webserver for simple remote control. | 0.5 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Testing** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`error-generator` | Creates warning, error, and critical log messages. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Totalstation** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`distance-corrector` | Removes atmospheric influences from distances. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`helmert-transformer` | Free stationing of total stations. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`polar-transformer` | Converts polar coordinates to Cartesian coordinates. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`refraction-corrector` | Corrects the atmospheric refraction. | 0.4 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`serial-measurement-processor` | Processing of observations in two faces. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Unix** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`gpio-controller` | Interacts with the GPIO interface of the Raspberry Pi. | 0.6 |
+-------------------------------------+--------------------------------------------------------+-----+
| **Virtual** | | |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`virtual-dtm` | Virtual STS DTM temperature/pressure sensor. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`virtual-indicator-one` | Virtual Sylvac S\_Dial One digital indicator. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
| :ref:`virtual-total-station-tm30` | Virtual Leica TM30 total station. | 0.3 |
+-------------------------------------+--------------------------------------------------------+-----+
Modules can be loaded by adding them to the ``modules`` section of the OpenADMS
Node core configuration. In the example below, the modules :ref:`scheduler` and
:ref:`file-exporter` will be loaded:
.. code:: javascript
{
"core":
"modules": {
"fileExporter": "modules.export.FileExporter",
"schedulerCom1": "modules.schedule.Scheduler"
}
},
"modules": {}
}
The key ``fileExporter`` sets the name of the instance, the value
``modules.export.FileExporter`` the path to the module (class ``FileExporter``
in file ``modules/export.py``). The configuration of each loaded module must be
added to the ``modules`` section of the file.
The name of an instance can be chosen freely. For instance, instead of
``fileExporter`` the name ``myFileExporter`` is valid too, but the key of the
FileExporter configuration in the ``modules`` section has to be renamed as well.
Multiple instances of a module are possible, if they have distinct names (e.g.,
``scheduler1``, ``scheduler2``, and so on). Each instance has its own
configuration.
Database
--------
Drivers for various database management systems are provided in this package.
.. _couch-driver:
CouchDriver
~~~~~~~~~~~
CouchDriver is a connectivity module for `Apache CouchDB`_ 1/2 (see
:numref:`couchdb`). It is used to store observation data sets (timeseries) in a
CouchDB database defined in the module’s configuration. Observations are cached
before inserting them into the database. On connection error, the transmission
will be repeated until the server has stored them successfully. If a file-based
cache database is used, observation are persistent between restarts of OpenADMS
Node.
.. _couchdb:
.. figure:: _static/couchdb.png
:alt: An observation data set stored in an Apache CouchDB database
An observation data set stored in an Apache CouchDB database
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the following line to the ``modules`` section of the configuration file to
load the CouchDriver:
.. code:: javascript
{
"modules": {
"couchDriver": "modules.database.CouchDriver"
}
}
Configuration
^^^^^^^^^^^^^
An example CouchDB server on
``https://alice:secret@db.example.com:443/couchdb/`` may has the following
configuration.
.. code:: javascript
{
"couchDriver": {
"server": "db.example.com",
"path": "couchdb/",
"port": 5984,
"tls": true,
"user": "alice",
"password": "secret",
"db": "openadms",
"cacheFile": "cache.json"
}
}
+---------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+===============+=============+=========================================================+
| ``server`` | String | IP address or FQDN of the CouchDB server. |
+---------------+-------------+---------------------------------------------------------+
| ``path`` | String | URI path (if available). |
+---------------+-------------+---------------------------------------------------------+
| ``port`` | String | Port number (CouchDB default is ``5984``). |
+---------------+-------------+---------------------------------------------------------+
| ``tls`` | Boolean | If true, uses encrypted HTTPS instead of HTTP (depends |
| | | on server). |
+---------------+-------------+---------------------------------------------------------+
| ``user`` | String | Name of the CouchDB user. |
+---------------+-------------+---------------------------------------------------------+
| ``password`` | String | Password of the CouchDB user. |
+---------------+-------------+---------------------------------------------------------+
| ``db`` | String | Name of the CouchDB database. |
+---------------+-------------+---------------------------------------------------------+
| ``cacheFile`` | String | File name of the local cache database. If not set, an |
| | | in-memory database is used instead. |
+---------------+-------------+---------------------------------------------------------+
Export
------
Modules in the *Export* package store observation data locally or forward it to
external receivers.
.. _cloud-exporter:
CloudExporter
~~~~~~~~~~~~
The CloudExporter module sends observations to local or remote OpenADMS Server
instances. Make sure to add the name of the CloudExporter module to the
``receivers`` list of the observations that should be transmitted to the
server.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the CloudExporter to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"cloudExporter": "modules.export.CloudExporter"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"cloudExporter": {
"host": "https://api.example.com/",
"user": "",
"password": "",
"cache": "file",
"db": "cache.json"
}
}
+-----------------------+-------------+-------------------------------------------------+
| Name | Data Type | Description |
+=======================+=============+=================================================+
| ``host`` | String | OpenADMS Server URL or IP address. |
+-----------------------+-------------+-------------------------------------------------+
| ``user`` | String | OpenADMS Sever user name. |
+-----------------------+-------------+-------------------------------------------------+
| ``password`` | String | OpenADMS Sever password. |
+-----------------------+-------------+-------------------------------------------------+
| ``cache`` | String | Cache type (either ``file`` or ``memory``). |
+-----------------------+-------------+-------------------------------------------------+
| ``db`` | String | File name of the cache database (if ``file``). |
+-----------------------+-------------+-------------------------------------------------+
.. _file-exporter:
FileExporter
~~~~~~~~~~~~
The FileExporter module is used to export observations as comma-separated values
to flat files. Each file starts with a header, introduced by the character
``#``. Observations are stored line by line in the file, with new lines
appended to the end.
Each line starts with date and time of the observation, followed by ID, target
name and all response sets in alphabetical order. The format of date and time
can be modified in the configuration. A response set consists of response name,
response value, and response unit (for example: ``distance``, ``27.412``,
``m``).
Example
^^^^^^^
A single observation in a CSV file, with a header line at the beginning:
.. code:: text
# Target "EXT" of "Extensometer" on "USB0"
2016-10-09T15:29:38,6dc84c06018043ba84ac90636ed0f677,EXT,distance,19.212,mm
+----------+--------------------------------------+---------------------------------+
| No. | Value | Description |
+==========+======================================+=================================+
| 1 | ``2016-10-09T15:29:38`` | Date and time (ISO 8601). |
+----------+--------------------------------------+---------------------------------+
| 2 | ``6dc84c06018043ba84ac90636ed0f677`` | ID of the observation. |
+----------+--------------------------------------+---------------------------------+
| 2 | ``EXT`` | Target name of the observation. |
+----------+--------------------------------------+---------------------------------+
| 3 | ``distance`` | Name of the response set. |
+----------+--------------------------------------+---------------------------------+
| 4 | ``19.212`` | Value of the response set. |
+----------+--------------------------------------+---------------------------------+
| 5 | ``mm`` | Unit of the response set. |
+----------+--------------------------------------+---------------------------------+
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the FileExporter to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"fileExporter": "modules.export.FileExporter"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"fileExporter": {
"fileExtension": ".csv",
"fileName": "{{port}}_{{target}}_{{date}}",
"fileRotation": "monthly",
"paths": [
"./data",
"/media/usbstick/backup"
],
"separator": ",",
"dateTimeFormat": "YYYY-MM-DDTHH:mm:ss.SSSSS",
"saveObservationId": true
}
}
+-----------------------+-------------+-------------------------------------------------+
| Name | Data Type | Description |
+=======================+=============+=================================================+
| ``fileExtension`` | String | Extension of the CSV file. |
+-----------------------+-------------+-------------------------------------------------+
| ``fileName`` | String | File name with possible placeholders |
| | | ``{{date}}``, ``{{target}}``, ``{{name}}``, |
| | | ``{{port}}``. |
+-----------------------+-------------+-------------------------------------------------+
| ``fileRotation`` | String | File rotation (``none``, ``daily``, |
| | | ``monthly``, or ``yearly``). |
+-----------------------+-------------+-------------------------------------------------+
| ``paths`` | Array | Paths to save files to (multiple paths |
| | | possible). |
+-----------------------+-------------+-------------------------------------------------+
| ``separator`` | String | Separator between values within the CSV file. |
+-----------------------+-------------+-------------------------------------------------+
| ``dateTimeFormat`` | String | Format of date and time (see `Arrow tokens`_). |
+-----------------------+-------------+-------------------------------------------------+
| ``saveObservationId`` | Boolean | If ``true``, save the ID of each observation. |
+-----------------------+-------------+-------------------------------------------------+
.. _real-time-publisher:
RealTimePublisher
~~~~~~~~~~~~~~~~~
The RealTimePublisher module pushes an observation to a list of MQTT topics.
The receivers can be any third party application connected to the MQTT server.
Observation are published under their target name. For example, observations
with target “bridge1” and a topic “onlineViewer” will be published to the MQTT
topic ``onlineViewer/bridge1``.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the RealTimePublisher to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"realTimePublisher": "modules.export.RealTimePublisher"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"realTimePublisher": {
"enabled": true,
"topics": [
"onlineViewer"
]
}
}
Notification
------------
.. _alerter:
Alerter
~~~~~~~
The Alerter module captures warning and error messages. The messages are drained
off from the OpenADMS logger and then send to an arbitrary number of
AlertMessageFormatter modules. These will format the messages and forward them
to MailAgent, ShortMessageAgent, RssAgent, IrcAgent, or MastodonAgent modules,
where they are send to their defined receivers.
The sequences could be:
- Alerter → CloudAgent
- Alerter → AlertMessageFormatter → MailAgent
- Alerter → AlertMessageFormatter → ShortMessageAgent
- Alerter → AlertMessageFormatter → RssAgent
- Alerter → AlertMessageFormatter → IrcAgent
- Alerter → AlertMessageFormatter → MastodonAgent
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the Alerter to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"alerter": "modules.notification.Alerter"
}
}
Alert Message Format
^^^^^^^^^^^^^^^^^^^^
The Alerter module forwards the message in a particular JSON-based format with
the type ``alert``. Example:
.. code:: javascript
[
{
"type": "alert"
},
{
"dt": "2017-09-12 21:40:57",
"level": "error",
"module": "serialPort",
"message": "Observation 'getP09' of 'P09': No target detected",
"receiver": "engineer@example.com"
}
]
+--------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+==============+=============+=========================================================+
| ``dt`` | Integer | Time stamp of the alert message. |
+--------------+-------------+---------------------------------------------------------+
| ``level`` | String | Alert level (``warning``, ``error``, or ``critical``). |
+--------------+-------------+---------------------------------------------------------+
| ``module`` | String | Name of the module which sent the message. |
+--------------+-------------+---------------------------------------------------------+
| ``message`` | String | Message text. |
+--------------+-------------+---------------------------------------------------------+
| ``receiver`` | String | Receiver of the message (e.g., e-mail address, phone |
| | | number, IRC channel). |
+--------------+-------------+---------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"alerter": {
"enabled": true,
"modules": {
"cloudAgent": {
"enabled": true,
"receivers": {
"critical": [ "default" ],
"error": [ "default" ],
"warning": [ "default" ]
}
},
"shortMessageFormatter": {
"enabled": true,
"receivers": {
"error": [ "+49152 12345678" ],
"critical": [ "+49178 110010101" ]
}
},
"mailFormatter": {
"enabled": true,
"receivers": {
"warning": [ "warnings@example.com" ],
"error": [ "engineer@example.com", "customer@example.com" ]
}
}
}
}
}
+---------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+===============+=============+=========================================================+
| ``modules`` | Object | Modules to process alert messages. |
+---------------+-------------+---------------------------------------------------------+
| ``enabled`` | Boolean | Turns forwarding to module on/off. |
+---------------+-------------+---------------------------------------------------------+
| ``receivers`` | Object | Alert levels and their respective receivers (depend on |
| | | module). |
+---------------+-------------+---------------------------------------------------------+
.. _alert-message-formatter:
AlertMessageFormatter
~~~~~~~~~~~~~~~~~~~~~
The AlertMessageFormatter is used to format alert messages before sending them
to the :ref:`mail-agent`, the :ref:`short-message-agent`, the :ref:`rss-agent`,
or the :ref:`irc-agent`. The style of an e-mail or SMS can be defined by writing
simple templates. Furthermore, the module is capable of caching incoming
messages a certain time, forwarding them as a whole.
Cached alerts will be concatenated in the body of the message, with the same
header and footer. An example e-mail message is:
.. code:: text
The following incident(s) occurred:
2017-03-20T02:53:51 - warning - Observation "getP03" of target "P03": Only angle measurement valid, but without full correction (code 1288 in response "rcGetValues1")
2017-03-20T02:57:55 - error - Observation "getP11" of target "P11": No target detected (code 8710 in response "rcChangeFace")
Please do not reply as this e-mail was sent from an automated alerting system.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the AlertMessageFormatter to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"alertMessageFormatter": "modules.notification.AlertMessageFormatter"
}
}
Configuration
^^^^^^^^^^^^^
Given are two AlertMessageFormatter, ``mailFormatter`` and
``shortMessageFormatter``:
.. code:: javascript
{
"modules": {
"mailFormatter": "modules.notify.AlertMessageFormatter",
"shortMessageFormatter": "modules.notify.AlertMessageFormatter"
}
}
They are used to format e-mails and short messages.
.. code:: javascript
{
"mailFormatter": {
"messageCollectionEnabled": true,
"messageCollectionTime": 600,
"receiver": "mailAgent",
"type": "email",
"templates": {
"header": "The following incident(s) occurred:\n\n",
"body": "{{dt}} - {{level}} - {{message}}\n",
"footer": "\nPlease do not reply as this e-mail was sent from an automated alerting system."
},
"properties": {
"subject": "[OpenADMS] Alert Message - Project X",
"from": "OpenADMS",
"to": "{{receiver}}"
}
},
"shortMessageFormatter": {
"messageCollectionEnabled": false,
"messageCollectionTime": 0,
"receiver": "shortMessageAgent",
"type": "sms",
"templates": {
"header": "",
"body": "{{dt}} - {{level}} - {{message}}",
"footer": ""
},
"properties": {
"number": "{{receiver}}"
}
}
}
+------------------------------+-------------+----------------------------------------------+
| Name | Data Type | Description |
+==============================+=============+==============================================+
| ``messageCollectionEnabled`` | Boolean | Collect messages in a cache before sending. |
+------------------------------+-------------+----------------------------------------------+
| ``messageCollectionTime`` | Float | Time in seconds to cache messages. |
+------------------------------+-------------+----------------------------------------------+
| ``receiver`` | String | Name of the receiving module. |
+------------------------------+-------------+----------------------------------------------+
| ``type`` | String | Type of the message (e.g., ``email`` or |
| | | ``sms``). |
+------------------------------+-------------+----------------------------------------------+
| ``templates`` | Object | Message templates with ``header``, ``body``, |
| | | and ``footer``. |
+------------------------------+-------------+----------------------------------------------+
| ``properties`` | Object | Additional properties expected by the |
| | | receiver. |
+------------------------------+-------------+----------------------------------------------+
The templates ``header``, ``body``, and ``footer`` are parsed for placeholders:
+-------------------------+---------------------------------------------------------+
| Name | Description |
+=========================+=========================================================+
| ``{{dt}}`` | Date and time of the log entry. |
+-------------------------+---------------------------------------------------------+
| ``{{level}}`` | Log level (``warning``, ``error``, or ``critical``). |
+-------------------------+---------------------------------------------------------+
| ``{{message}}`` | Log message text. |
+-------------------------+---------------------------------------------------------+
| ``{{nid}}`` | ID of the sensor node. |
+-------------------------+---------------------------------------------------------+
| ``{{node}}`` | Name of the sensor node. |
+-------------------------+---------------------------------------------------------+
| ``{{pid}}`` | ID of the project. |
+-------------------------+---------------------------------------------------------+
| ``{{project}}`` | Name of the project. |
+-------------------------+---------------------------------------------------------+
.. _cloud-agent:
CloudAgent
~~~~~~~~~~~~
The CloudAgent module sends log messages to local or remote OpenADMS Server
instances.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the CloudAgent to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"cloudAgent": "modules.notification.CloudAgent"
}
}
Configuration
^^^^^^^^^^^^^
Add the connection details of the OpenADMS Server you want to access to the
configuration:
.. code:: javascript
{
"cloudAgent": {
"host": "https://api.example.com/",
"user": "",
"password": ""
}
}
+------------------------------+-------------+----------------------------------------------+
| Name | Data Type | Description |
+==============================+=============+==============================================+
| ``host`` | String | OpenADMS Server URL or IP address. |
+------------------------------+-------------+----------------------------------------------+
| ``user`` | String | OpenADMS Server user name. |
+------------------------------+-------------+----------------------------------------------+
| ``password`` | String | OpenADMS Server password. |
+------------------------------+-------------+----------------------------------------------+
Connect the :ref:`alerter` module with the CloudAgent:
.. code:: javascript
{
"alerter": {
"enabled": true,
"modules": {
"cloudAgent": {
"enabled": true,
"receivers": {
"warning": ["default"],
"error": ["default"],
"critical": ["default"]
}
}
}
},
"cloudAgent": {
"host": "https://api.example.com/",
"user": "",
"password": ""
}
}
It is necessary to add dummy receivers (e. g., ``default``) to the Alerter
module.
.. _heartbeat:
Heartbeat
~~~~~~~~~
The Heartbeat sends signals periodically in a defined interval to a list of
receivers. The module is used to inform the receivers that the OpenADMS Node
instance is still alive (see `Wikipedia`_).
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the Heartbeat to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"heartbeat": "modules.notification.Heartbeat"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"heartbeat": {
"host": "https://api.example.com/",
"user": "",
"password" : "",
"frequency": 300
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``host`` | String | OpenADMS Server URL or IP address. |
+------------------+-------------+------------------------------------------------------+
| ``user`` | String | OpenADMS Server user name. |
+------------------+-------------+------------------------------------------------------+
| ``password`` | String | OpenADMS Server password. |
+------------------+-------------+------------------------------------------------------+
| ``frequency`` | Integer | Heartbeat frequency in seconds. |
+------------------+-------------+------------------------------------------------------+
.. _irc-agent:
IrcAgent
~~~~~~~~
The IrcAgent connects to an Internet Relay Chat (IRC) server and sends messages
to a given channel or user. The module accepts messages of type ``irc``.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the IrcAgent to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"ircAgent": "modules.notification.IrcAgent"
}
}
IRC Message Format
^^^^^^^^^^^^^^^^^^
The messages send to the module have to be structured in JSON format:
.. code:: javascript
[
{
"type": "irc"
},
{
"message": "2017-09-08T11:55:58 - error - preProcessor - No response in observation 'getDistance' of target 'disto'",
"target": "#mychannel"
}
]
+-------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+=============+=============+=========================================================+
| ``message`` | String | Message text. |
+-------------+-------------+---------------------------------------------------------+
| ``target`` | String | IRC channel or user to send the message to. |
+-------------+-------------+---------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"ircAgent": {
"server": "irc.freenode.net",
"port": 6697,
"tls": true,
"nickname": "iot_bot",
"password": "",
"target": "#flood",
"channel": "#flood"
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``server`` | String | IRC server (IP address or FQDN). |
+------------------+-------------+------------------------------------------------------+
| ``port`` | String | Port number (e.g., ``6667`` for plain or ``6697`` |
| | | for TLS). |
+------------------+-------------+------------------------------------------------------+
| ``tls`` | Boolean | If ``true``, use TLS-encrypted connection. |
+------------------+-------------+------------------------------------------------------+
| ``nickname`` | String | Nickname to register with. |
+------------------+-------------+------------------------------------------------------+
| ``password`` | String | Password of the nickname (optional). |
+------------------+-------------+------------------------------------------------------+
| ``target`` | String | Default target to send messages to (channel or |
| | | user). |
+------------------+-------------+------------------------------------------------------+
| ``channel`` | String | Channel to join at start-up (optional). |
+------------------+-------------+------------------------------------------------------+
Example
^^^^^^^
An :ref:`alerter` instance and an :ref:`alert-message-formatter`
instance can be used to send log messages to an IRC server:
.. code:: javascript
{
"modules": {
"alerter": "modules.notification.Alerter",
"ircFormatter": "modules.notification.AlertMessageFormatter",
"ircAgent": "modules.notification.IrcAgent"
},
"alerter": {
"enabled": true,
"modules": {
"ircFormatter": {
"enabled": true,
"receivers": {
"warning": [ "#mychannel" ],
"error": [ "#mychannel" ],
"critical": [ "#mychannel" ]
}
}
}
},
"ircFormatter": {
"messageCollectionEnabled": false,
"messageCollectionTime": 0,
"type": "irc",
"receiver": "ircAgent",
"templates": {
"body": "{{dt}} - {{level}} - {{name}} - {{message}}"
},
"properties": {
"target": "{{receiver}}"
}
},
"ircAgent": {
"server": "irc.freenode.net",
"port": 6697,
"tls": true,
"nickname": "openadms___",
"target": "#mychannel",
"channel": "#mychannel"
}
}
The setup can be tested with the :ref:`error-generator` module.
.. _mail-agent:
MailAgent
~~~~~~~~~
The MailAgent is used to send arbitrary messages as e-mails via an SMTP server.
The module expects the messages to be in a particular format, which is described
below.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the MailAgent to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"mailAgent": "modules.notification.MailAgent"
}
}
E-Mail Message Format
^^^^^^^^^^^^^^^^^^^^^
The messages have to be structured in JSON format:
.. code:: javascript
[
{
"type": "email"
},
{
"subject": "E-mail subject",
"from": "OpenADMS",
"to": "recipient@example.com",
"message": "Hello, world!"
}
]
+-------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+=============+=============+=========================================================+
| ``subject`` | String | Subject of the e-mail. |
+-------------+-------------+---------------------------------------------------------+
| ``from`` | String | Sender of the e-mail. |
+-------------+-------------+---------------------------------------------------------+
| ``to`` | String | Receiver of the e-mail. |
+-------------+-------------+---------------------------------------------------------+
| ``message`` | String | E-mail text. |
+-------------+-------------+---------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"mailAgent": {
"defaultSubject": "[OpenADMS] Message",
"charset": "utf-8",
"userMail": "monitoring@example.com",
"userName": "monitoring",
"userPassword": "secret",
"host": "smtp.example.com",
"port": 465,
"tls": true,
"startTls": false
}
}
+--------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+====================+=============+======================================================+
| ``defaultSubject`` | Boolean | Default subject of the e-mail. |
+--------------------+-------------+------------------------------------------------------+
| ``charset`` | String | Charset of the e-mail. |
+--------------------+-------------+------------------------------------------------------+
| ``userMail`` | String | E-mail address of the sender. |
+--------------------+-------------+------------------------------------------------------+
| ``userName`` | String | SMTP login name. |
+--------------------+-------------+------------------------------------------------------+
| ``userPassword`` | String | SMTP login password. |
+--------------------+-------------+------------------------------------------------------+
| ``host`` | String | SMTP host (IP address or FQDN). |
+--------------------+-------------+------------------------------------------------------+
| ``port`` | Integer | SMTP port. |
+--------------------+-------------+------------------------------------------------------+
| ``tls`` | Boolean | If ``true``, use TLS encryption. |
+--------------------+-------------+------------------------------------------------------+
| ``startTls`` | Boolean | If ``true``, use TLS encryption with StartTLS. |
+--------------------+-------------+------------------------------------------------------+
.. _mastodon-agent:
MastodonAgent
~~~~~~~~~~~~~
The MastodonAgent sends “toots” to the Twitter-like social network `Mastodon`_
(see :numref:`mastodon-screenshot`). You need an account on one of the Mastodon
instances. See `joinmastodon.org`_ for a list of servers. The length of
messages send to the Mastodon network is limited to 500 characters.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the MastodonAgent to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"mastodonAgent": "modules.notification.MastodonAgent"
}
}
.. _mastodon-screenshot:
.. figure:: _static/mastodon.png
:alt: OpenADMS alert message on Mastodon
:align: center
:scale: 80%
OpenADMS alert message on Mastodon
Mastodon Message Format
^^^^^^^^^^^^^^^^^^^^^^^
The messages have to be structured in JSON format:
.. code:: javascript
[
{
"type": "mastodon"
},
{
"message": "Hello, world!"
}
]
+-------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+=============+=============+=========================================================+
| ``message`` | String | The text of the “toot” (< 500 characters). |
+-------------+-------------+---------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"mastodonAgent": {
"email": "mail@example.com",
"password": "secret",
"url": "https://mastodon.at"
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``email`` | String | E-mail address associated with the Mastodon account. |
+------------------+-------------+------------------------------------------------------+
| ``password`` | String | Password of the Mastodon account. |
+------------------+-------------+------------------------------------------------------+
| ``url`` | String | URL of the Mastodon instance. |
+------------------+-------------+------------------------------------------------------+
Example
^^^^^^^
An :ref:`alerter` instance and an :ref:`alert-message-formatter` instance can be
used to send log messages to the MastodonAgent:
.. code:: javascript
{
"modules": {
"alerter": "modules.notification.Alerter",
"mastodonFormatter": "modules.notification.AlertMessageFormatter",
"mastodonAgent": "modules.notification.MastodonAgent"
},
"alerter": {
"enabled": true,
"modules": {
"mastodonFormatter": {
"enabled": true,
"receivers": {
"warning": [ "mastodonAgent" ],
"error": [ "mastodonAgent" ],
"critical": [ "mastodonAgent" ]
}
}
}
},
"mastodonFormatter": {
"messageCollectionEnabled": false,
"messageCollectionTime": 0,
"type": "mastodon",
"receiver": "mastodonAgent",
"templates": {
"body": "{{dt}} - {{project}} - {{node}} - {{name}} - {{level}} - {{message}}"
},
"properties": {}
},
"mastodonAgent": {
"email": "mail@example.com",
"password": "secret",
"url": "https://mastodon.at"
}
}
The setup can be tested with the :ref:`error-generator` module.
.. _rss-agent:
RssAgent
~~~~~~~~
The RssAgent exports messages as an RSS 2.0 feed. Users can subscribe a public
feed to access log messages with a feed reader (see :numref:`rss-android`).
The RSS format is based on XML. The module accepts messages of type ``rss``.
.. _rss-android:
.. figure:: _static/openadms_rss.png
:alt: RSS feed with alert messages on Android
:align: center
:scale: 30%
RSS feed with alert messages on Android
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the RssAgent to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"rssAgent": "modules.notification.RssAgent"
}
}
RSS Message Format
^^^^^^^^^^^^^^^^^^
The messages send to the module have to be structured in JSON format:
.. code:: javascript
[
{
"type": "rss"
},
{
"author": "mail@example.com (John Doe)",
"dt": "2017-09-18T19:55:45.955084+00:00",
"guid": "urn:uuid:4d8fc364-f3fc-46d5-869b-7a7c1b9c8972",
"message": "2017-09-18T19:55:42 - error - preProcessor - No response in observation 'getDistance' of target 'disto'",
"title": "[OpenADMS] Alert Message - Example Project"
}
]
+-------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+=============+=============+=========================================================+
| ``author`` | String | Author of the RSS entry (optional). |
+-------------+-------------+---------------------------------------------------------+
| ``dt`` | String | Date and time of the RSS entry in UTC (optional). |
+-------------+-------------+---------------------------------------------------------+
| ``guid`` | String | Globally Unique Identifier (GUID) of the RSS entry |
| | | (optional). |
+-------------+-------------+---------------------------------------------------------+
| ``message`` | String | Message of the RSS entry. |
+-------------+-------------+---------------------------------------------------------+
| ``title`` | String | Title of the RSS entry (optional). |
+-------------+-------------+---------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"rssAgent": {
"author": "mail@example.com (John Doe)",
"description": "OpenADMS RSS 2.0 Feed - Example Project",
"filePath": "./feed.rss",
"language": "en",
"link": "https://www.example.com/feed.rss",
"size": 25,
"title": "OpenADMS Monitoring - Example Project"
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``author`` | String | E-mail and name of the author (optional). |
+------------------+-------------+------------------------------------------------------+
| ``description`` | String | Description text of the RSS feed. |
+------------------+-------------+------------------------------------------------------+
| ``filePath`` | String | Path of the RSS file. |
+------------------+-------------+------------------------------------------------------+
| ``language`` | String | ISO 639-1 language code (optional). |
+------------------+-------------+------------------------------------------------------+
| ``link`` | String | URL of the RSS feed. |
+------------------+-------------+------------------------------------------------------+
| ``size`` | Integer | Number of entries in the RSS feed. |
+------------------+-------------+------------------------------------------------------+
| ``title`` | String | Title of the RSS feed. |
+------------------+-------------+------------------------------------------------------+
Example
^^^^^^^
An :ref:`alerter` instance and an :ref:`alert-message-formatter` instance can be
used to send log messages to the RssAgent:
.. code:: javascript
{
"modules": {
"alerter": "modules.notification.Alerter",
"rssFormatter": "modules.notification.AlertMessageFormatter",
"rssAgent": "modules.notification.RssAgent"
},
"alerter": {
"enabled": true,
"modules": {
"rssFormatter": {
"enabled": true,
"receivers": {
"warning": [ "rssAgent" ],
"error": [ "rssAgent" ],
"critical": [ "rssAgent" ]
}
}
}
},
"rssFormatter": {
"messageCollectionEnabled": true,
"messageCollectionTime": 600,
"type": "rss",
"receiver": "rssAgent",
"templates": {
"header": "The following incident(s) occurred on node \"{{node}}\":
\n\n",
"body": "{{dt}} - {{level}} - {{message}}
\n",
"footer": "
]]>"
},
"properties": {
"title": "[OpenADMS] Alert Message - Example Project",
"author": "mail@example.com (OpenADMS)",
"link": "http://www.example.com/feed.rss"
}
},
"rssAgent": {
"author": "mail@example.com (John Doe)",
"description": "OpenADMS RSS 2.0 Feed - Example Project",
"filePath": "./feed.rss",
"language": "en",
"link": "https://www.example.com/feed.rss",
"size": 25,
"title": "OpenADMS Monitoring - Example Project"
}
}
The setup can be tested with the :ref:`error-generator` module.
.. _short-message-agent:
ShortMessageAgent
~~~~~~~~~~~~~~~~~
The ShortMessageAgent can be used to establish a socket connection to a
2G/3G/LTE modem/router and sending an XML-based alerting message to it. The
message will then be forwarded by Short Message Service (SMS). The module is
designed for industrial routers of `MC Technologies`_, but should also work with
other socket-based SMS servers.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the ShortMessageAgent to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"shortMessageAgent": "modules.notification.ShortMessageAgent"
}
}
SMS Message Format
^^^^^^^^^^^^^^^^^^
The messages have to be structured in JSON format:
.. code:: javascript
[
{
"type": "sms"
},
{
"number": "+49176 012345678",
"message": "Hello, world!"
}
]
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``number`` | String | Phone number of the receiver. |
+------------------+-------------+------------------------------------------------------+
| ``message`` | String | SMS message text. |
+------------------+-------------+------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"shortMessageAgent": {
"host": "10.59.0.40",
"port": 1432
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``host`` | String | Socket host (IP address or FQDN). |
+------------------+-------------+------------------------------------------------------+
| ``port`` | Integer | Socket port. |
+------------------+-------------+------------------------------------------------------+
Port
----
.. _bluetooth-port:
BluetoothPort
~~~~~~~~~~~~~
The BluetoothPort can be used for RFCOMM serial communication. The module
initiates a socket connection to a sensor by using the native Bluetooth support
of Python 3.3. At the moment, the module is experimental and needs further
testing. It may be easier to use the Bluetooth driver to mount the Bluetooth
port as a local serial port.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the BluetoothPort to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"bt3": "modules.port.BluetoothPort"
}
}
Configuration
^^^^^^^^^^^^^
The configuration of BluetoothPort modules has to be placed in ``ports`` →
``bluetooth`` → *instance name*, as shown below for the BluetoothPort instance
``bt3``.
.. code:: javascript
{
"ports": {
"bluetooth": {
"bt3": {
"port": 3,
"serverMacAddress": "5D:4F:4E:F4:55:FD"
}
}
}
}
+----------------------+-------------+-------------------------------------------------+
| Name | Data Type | Description |
+======================+=============+=================================================+
| ``port`` | Integer | Bluetooth port number. |
+----------------------+-------------+-------------------------------------------------+
| ``serverMacAddress`` | String | MAC address of the Bluetooth server/sensor. |
+----------------------+-------------+-------------------------------------------------+
.. _serial-port:
SerialPort
~~~~~~~~~~
The SerialPort module is used for the communication with sensors connected to a
serial interface (RS-232, RS-422, or RS-485). The requests defined in the
``requestSets`` dictionary of the observation will be send one after another to
the sensor. The sensor’s responses are then each stored in the corresponding
request set. The SerialPort module also sets the time stamp of the observation
to the moment the last response has been received.
The SerialPort can communicate with an attached sensor either in *active* or
*passive* mode:
active
The port sends actively commands to a connected sensor in order to receive
responses (default mode).
passive
The port listens passively for incoming data of a connected sensor (must be
activated by an observation).
An observation can demand passive mode by setting its key ``passiveMode`` to
``true``. The passive mode can be left by a further observation with
``passiveMode`` set to ``false``. In passive mode, the serial port module
creates new observations as fast as incoming data from a sensor is received. As
a prerequisite it is required that the one and only request set of the
observation is named ``draft``, for instance:
.. code:: javascript
{
"sensors": {
"thermometer": {
"description": "example of a thermometer in passive mode",
"type": "thermometer",
"observations": [
{
"name": "getTemperature",
"description": "get temperature",
"id": "9dd4ac4d872547028bc287c66f64b8b0",
"target": "temp",
"receivers": [
"com1",
"preProcessor"
],
"nextReceiver": 0,
"enabled": true,
"onetime": true,
"passiveMode": true,
"requestsOrder": [
"draft"
],
"requestSets": {
"draft": {
"enabled": true,
"request": "",
"responseDelimiter": "\r\n",
"responsePattern": "(?P[+-]?\\d+\\.\\d+)",
"sleepTime": 0.0,
"timeout": 1.0
}
},
"responseSets": {
"temp": {
"type": "float",
"unit": "degC"
}
},
"sleepTime": 0.0
}
]
}
}
}
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the SerialPort to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"com1": "modules.port.SerialPort",
"com2": "modules.port.SerialPort"
}
}
Configuration
^^^^^^^^^^^^^
In contrast to other modules, the configuration of SerialPort modules has to be
placed in ``ports`` → ``serial`` → *instance name*, as shown below for the
SerialPort instances ``com1`` and ``com2``.
.. code:: javascript
{
"ports": {
"serial": {
"com1": {
"port": "COM1",
"baudRate": 9600,
"byteSize": 8,
"stopBits": 1,
"parity": "none",
"timeout": 2,
"softwareFlowControl": false,
"hardwareFlowControl": false,
"maxAttempts": 1
},
"com2": {
"port": "COM2",
"baudRate": 4800,
"byteSize": 7,
"stopBits": 2,
"parity": "even",
"timeout": 2,
"softwareFlowControl": false,
"hardwareFlowControl": false,
"maxAttempts": 1
}
}
}
}
+-------------------------+-------------+-------------------------------------------------+
| Name | Data Type | Description |
+=========================+=============+=================================================+
| ``port`` | String | Name of the port (``COMX`` or ``/dev/ttyX``). |
+-------------------------+-------------+-------------------------------------------------+
| ``baudRate`` | Integer | Baud rate (e.g., ``4800``, ``9600``, or |
| | | ``115200``). |
+-------------------------+-------------+-------------------------------------------------+
| ``byteSize`` | Integer | Start bits, either ``5``, ``6``, ``7``, or |
| | | ``8``. |
+-------------------------+-------------+-------------------------------------------------+
| ``stopBits`` | Integer | Stop bits, either ``1`` or ``2``. |
+-------------------------+-------------+-------------------------------------------------+
| ``parity`` | String | Parity, either ``none``, ``even``, or ``odd``. |
+-------------------------+-------------+-------------------------------------------------+
| ``timeout`` | Float | Timeout in seconds. |
+-------------------------+-------------+-------------------------------------------------+
| ``softwareFlowControl`` | Boolean | XON/XOFF flow control. |
+-------------------------+-------------+-------------------------------------------------+
| ``hardwareFlowControl`` | Boolean | RTS/CTS flow control. |
+-------------------------+-------------+-------------------------------------------------+
| ``maxAttempts`` | Integer | Maximum number of attempts to access the port. |
+-------------------------+-------------+-------------------------------------------------+
Processing
----------
.. _pre-processor:
PreProcessor
~~~~~~~~~~~~
The PreProcessor module is used to extract values from a raw response of an
observation and convert them to given data types (i.e., from string to integer
or from string to float). Every observation object has both ``requestSets`` and
``responseSets``, with a regular expression stored in the ``response`` of each
request set. In order to extract single values from the raw response, so called
named groups have to be defined within the regular expressions (`more
information`_). The groups are mapped by the PreProcessor module to the
according response sets.
Example
^^^^^^^
The sensor configuration of a fictional extensometer is listed below. The
request set ``getValues`` has the response pattern
``(?P[-]?\\d\\.\\d+)`` with a named group ``distance`` in it. The
character ``\`` has to be escaped in JSON, therefore it is written as ``\\``.
The fitting response set ``distance`` expects the data type ``float``. Note,
that group name and response set have the very same name (in this case
``distance``).
The value of group ``distance`` is extracted from the (raw) response
``>+25.1203`` by the PreProcessor using the regular expression, converted to
float, and then stored in the corresponding response set ``distance`` by adding
a key ``value`` to the dictionary, containing the actual measurement value
(``25.1203``).
The PreProcessor performs the following steps:
1. Read raw sensor data ``>+25.1203`` from field ``response`` of request set
``getValue``.
2. Extract ``+25.1203`` using the (escaped) regular expression
``(?P[-]?\\d\\.\\d+)``.
3. Convert the string ``+25.1203`` to the float ``25.1203``.
4. Write value ``25.1203`` to response set ``distance``.
The observation data object is then forwarded to the next receiver.
.. code:: javascript
{
"sensors": {
"extensometer": {
"description": "example of an extensometer",
"type": "extensometer",
"observations": [
{
"name": "doMeasure",
"description": "get sensor value",
"id": "6dc84c06018043ba84ac90636ed0f677",
"target": "EXT",
"receivers": [
"com1",
"preProcessor"
],
"nextReceiver": 1,
"enabled": true,
"onetime": false,
"passiveMode": false,
"requestsOrder": [
"getValue"
],
"requestSets": {
"getValue": {
"enabled": true,
"request": "?\r",
"response": ">+25.1203",
"responseDelimiter": "\r",
"responsePattern": "(?P[+-]?\\d+\\.\\d+)",
"sleepTime": 0,
"timeout": 1
}
},
"responseSets": {
"distance": {
"type": "float",
"value": "25.1203",
"unit": "mm"
}
},
"sleepTime": 1
}
]
}
}
}
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the PreProcessor to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"preProcessor": "modules.processing.PreProcessor"
}
}
Configuration
^^^^^^^^^^^^^
The module PreProcessor has nothing to configure.
.. _response-value-inspector:
ResponseValueInspector
~~~~~~~~~~~~~~~~~~~~~~
The ResponseValueInspector checks if response values of observations are within
defined thresholds. It works by checking received observations against the
allowed minimum and maximum values of responses defined in the configuration. A
log messages of level “critical” will be raised if a response value deceeds the
minimum or exceeds the maximum.
Example
^^^^^^^
The response ``slopeDist`` of an arbitrary observation ``getDistance`` should be
between definied lower and upper boundaries. The minimum distance allowed is 2.0
m, the maximum is 300.0 m. Add the name of the observation to the configuration
of the module and set the ``min`` and ``max`` values of the response
``slopeDist`` to the designated values:
.. code:: javascript
{
"responseValueInspector": {
"observations": {
"getDistance": {
"slopeDist": {
"min": 2.0,
"max": 300.0
}
}
}
}
}
The ResponseValueInspector can be used to watch directions, angles, and other
numerical values (integer or float) as well.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the ResponseValueInspector to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"responseValueInspector": "modules.processing.ResponseValueInspector"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"responseValueInspector": {
"observations": {
"": {
"": {
"min": 20.0,
"max": 300.0
}
}
}
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``observations`` | Object | Observations with response names and there minimum |
| | | and maximum values. |
+------------------+-------------+------------------------------------------------------+
| ``min`` | Float | Minimum value of the response. |
+------------------+-------------+------------------------------------------------------+
| ``max`` | Float | Maximum value of the response. |
+------------------+-------------+------------------------------------------------------+
.. _return-code-inspector:
ReturnCodeInspector
~~~~~~~~~~~~~~~~~~~
The ReturnCodeInspector module generates log messages out of responses of
sensors of Leica Geosystems. Generally, every response of a sensor of Leica
Geosystem contains a so called *return code*, a decimal number which reveals
further information about the sensor or the measurement.
The return codes and their descriptions are hard-coded into the module, as well
as the log level (debug, info, warning, error, critical) and the setting whether
or not a failed measurement should be repeated. The number of retries and the
names of return code response sets can be defined in the configuration.
Example
^^^^^^^
In the example below, an observation of a total station is listed. The response
pattern of the request set ``getSensorId`` contains a named group
``returnCode``, which will be mapped to the corresponding response set
``returnCode`` by the PreProcessor module. The ReturnCodeInspector checks the
response sets with the key ``returnCode``. If the return code is greater ``0``
it will generate a log message.
.. code:: javascript
{
"name": "initialize",
"description": "initialize the sensor",
"receivers": [
"preProcessor",
"returnCodeInspector"
],
"nextReceiver": 0,
"enabled": true,
"onetime": true,
"sleepTime": 5,
"target": "init",
"requestSets": {
"getSensorId": {
"enabled": true,
"request": "%R1Q,5003:\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)(?:,(?P\\d+))?",
"responseDelimiter": "\r\n",
"sleepTime": 0.5,
"timeout": 30
}
},
"requestsOrder": [
"getSensorId"
],
"responseSets": {
"returnCode": {
"type": "integer",
"unit": "none",
"value": 7
},
"sensorId": {
"type": "string",
"unit": "none",
"value": 9999999
}
}
}
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the ReturnCodeInspector to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"returnCodeInspector": "modules.processing.ReturnCodeInspector"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"returnCodeInspector": {
"retries": 3,
"responseSets": [
"returnCode",
"returnCodeSetDirection"
]
}
}
+------------------+-------------+-------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+=======================================================+
| ``retries`` | Integer | Number of retries after a failed observation. |
+------------------+-------------+-------------------------------------------------------+
| ``responseSets`` | Array | List of return code response set names to search for. |
+------------------+-------------+-------------------------------------------------------+
.. _unit-converter:
UnitConverter
~~~~~~~~~~~~~
The UnitConverter module can be used to convert observation values from one unit
to another. For instance, a given distance in millimetres can be converted to
metres by scaling it with the factor ``0.001``. Add a definition to the
configuration of the module for each response you want to convert. The name of
the response is used as an identifier in the configuration.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the UnitConverter to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"unitConverter": "modules.processing.UnitConverter"
}
}
Configuration
^^^^^^^^^^^^^
The configuration below shows the definition of a unit conversion from ``mm`` to
``m`` for a response set with the name ``slopeDist``.
.. code:: javascript
{
"unitConverter": {
"slopeDist": {
"conversionType": "scale",
"sourceUnit": "mm",
"scalingValue": 0.01,
"targetUnit": "m"
}
}
}
+--------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+====================+=============+======================================================+
| ``conversionType`` | String | Currently, only the conversion type ``scale`` is |
| | | supported. |
+--------------------+-------------+------------------------------------------------------+
| ``sourceUnit`` | String | Unit of the source value (e.g., ``mm``). |
+--------------------+-------------+------------------------------------------------------+
| ``targetUnit`` | String | New unit of the result value (e.g., ``m``). |
+--------------------+-------------+------------------------------------------------------+
| ``scalingValue`` | Float | Scaling value (e.g., ``0.1`` or ``1000.0``). |
+--------------------+-------------+------------------------------------------------------+
Prototype
---------
All OpenADMS Node modules are a subclass of the module ``core.Prototype``.
.. _prototype:
Prototype
~~~~~~~~~
The Prototype class is used for prototypal inheritance only. All OpenADMS Node
modules are based on Prototype. A minimal OpenADMS Node module can be
implemented as:
.. code:: python
class MyModule(Prototype):
def __init__(self, module_name: str, module_type: str, manager: Manager):
super().__init__(module_name, module_type, manager)
def process_observation(self, obs: Observation) -> Observation:
return obs
The (processed) Observation object has always to be returned to the calling
routine. Please be aware that the function ``process_observation()`` runs
already inside a Thread.
Raspberry Pi
------------
Modules in this package are compatible with the Raspberry Pi single-board
computer running Linux only.
.. _interrupt-counter:
InterruptCounter
~~~~~~~~~~~~~~~~
The InterruptCounter counts interrupts on one of the GPIO pins of the Raspberry
Pi single-board computer. This module should be compatible with all Raspberry Pi
models and ARMv6/ARMv7-based Linux operating systems. It is necessary to install
the Python package `RPi.GPIO`_ before using InterruptCounter. Please run:
::
$ python3 -m pip install RPi.GPIO
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the InterruptCounter to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"interruptCounter": "modules.rpi.InterruptCounter"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"interruptCounter": {
"gpio": 4,
"bounceTime": 250,
"countTime": 60,
"receiver": "fileExporter",
"sensorName": "Tipping Spoon"
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``gpio`` | Integer | GPIO pin to observe. |
+------------------+-------------+------------------------------------------------------+
| ``bounceTime`` | Integer | Time to wait after each interrupt to prevent |
| | | bouncing (in milliseconds). |
+------------------+-------------+------------------------------------------------------+
| ``countTime`` | Float | Collection time (in seconds). |
+------------------+-------------+------------------------------------------------------+
| ``receiver`` | String | Name of the receiving module. |
+------------------+-------------+------------------------------------------------------+
| ``sensorName`` | String | Name of the connected sensor. |
+------------------+-------------+------------------------------------------------------+
Schedule
--------
.. _scheduler:
Scheduler
~~~~~~~~~
The Scheduler module coordinates the monitoring process by following a schedule
with start and end time to send observations to a defined sensor. It is
mandatory to create a scheduler for each (serial) port instance to start a
deformation monitoring.
The Scheduler works as a facilitator between the sensor and the port.
Observations of a sensor listed in ``observations`` are send one by one to the
bind port instance, using the according schedule.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the Scheduler to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"schedulerCom1": "modules.schedule.Scheduler",
"schedulerCom2": "modules.schedule.Scheduler"
}
}
The name of each instance can be chosen freely.
Configuration
^^^^^^^^^^^^^
Schedulers are configured separately in the ``schedulers`` section of the
configuration, defined by the name of the respective module instance (e.g.,
``schedulerCom1``, ``schedulerCom2``, and so on).
.. code:: javascript
{
"schedulers": {
"schedulerCom1": {
"port": "com1",
"sensor": "leicaTm30",
"schedules": [
{
"enabled": true,
"startDate": "2016-02-01",
"endDate": "2017-07-30",
"weekdays": {
"monday": [
{
"startTime": "00:00:00",
"endTime": "08:00:00"
},
{
"startTime": "10:00:00",
"endTime": "23:59:59"
}
],
"tuesday": [],
"wednesday": [],
"thursday": [],
"friday": [],
"saturday": [],
"sunday": []
},
"observations": [
"doInit",
"getTargetP1",
"getTargetP2",
"getTargetP3"
]
}
]
},
"schedulerCom2": {
"port": "com2",
"sensor": "stsDtm",
"schedules": [
{
"enabled": true,
"startDate": "2016-02-01",
"endDate": "2017-07-30",
"weekdays": {},
"observations": [
"getValues"
]
}
]
}
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``port`` | String | Name of the port module instance (e.g., ``com1``). |
+------------------+-------------+------------------------------------------------------+
| ``sensor`` | String | Name of the sensor as defined in ``sensors``. |
+------------------+-------------+------------------------------------------------------+
| ``schedules`` | Array | List of schedules. |
+------------------+-------------+------------------------------------------------------+
Server
------
.. _local-control-server:
LocalControlServer
~~~~~~~~~~~~~~~~~~
The LocalControlServer provides a simple web-based user interface for remote
control that can be accessed with a browser (see :numref:`lcs`). The module shows
some project information, system parameters, loaded modules, used sensors, and
log messages.
.. warning::
The web interface does not feature any kind of authentication or password
protection. For public Internet access it is strongly recommended to run a
reverse proxy server, like nginx or Hiawatha, in front of OpenADMS Node.
.. _lcs:
.. figure:: _static/localcontrolserver.png
:alt: The web-based user interface of the LocalControlServer
The web-based user interface of the LocalControlServer
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the LocalControlServer to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"localControlServer": "modules.server.LocalControlServer"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"localControlServer": {
"host": "127.0.0.1",
"port": 8080
}
}
+----------+-------------+--------------------------------------------------------------+
| Name | Data Type | Description |
+==========+=============+==============================================================+
| ``host`` | String | FQDN or IP address. Use a public IP or ``0.0.0.0`` if the |
| | | server should be accessible from outside. |
+----------+-------------+--------------------------------------------------------------+
| ``port`` | Integer | Port number (e.g., ``80`` or ``8080``). |
+----------+-------------+--------------------------------------------------------------+
Testing
-------
Modules in this package are used to test the monitoring system.
.. _error-generator:
ErrorGenerator
~~~~~~~~~~~~~~
The ErrorGenerator creates log messages in a set interval. The module can be
used to test the processing of warning, error, and critical log messages.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the ErrorGenerator to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"errorGenerator": "modules.testing.ErrorGenerator"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"errorGenerator": {
"warning": true,
"error": false,
"critical": false,
"interval": 30
}
}
+------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+==================+=============+======================================================+
| ``warning`` | Boolean | Turns log messages of level “warning” on or off. |
+------------------+-------------+------------------------------------------------------+
| ``error`` | Boolean | Turns log messages of level “error” on or off. |
+------------------+-------------+------------------------------------------------------+
| ``critical`` | Boolean | Turns log messages of level “critical” on or off. |
+------------------+-------------+------------------------------------------------------+
| ``interval`` | Float | Interval in which new log messages are generated. |
+------------------+-------------+------------------------------------------------------+
Totalstation
------------
.. _distance-corrector:
DistanceCorrector
~~~~~~~~~~~~~~~~~
The DistanceCorrector module applies atmospheric and sea level reductions to
measured EDM distances of total stations.
The atmospheric correction uses temperature, pressure, and humidity to calculate
the reduced distance. The values can be updated by sending observations of a
weather station to the DistanceCorrector. The response sets must have the names
``temperature``, ``pressure``, and ``humidity`` to be noticed by the module. The
calculated atmospheric PPM value is stored in the response set
``atmosphericPpm`` of the observation.
The sea level correction reduces the distance to sealevel (0 m). The calculated
sea level delta value is stored in the response set ``seaLevelDelta`` of the
observation.
The name of the response set of the distance can be set in the configuration.
The raw distance is moved to a new response set with the postfix ``Raw`` (e.g.,
the raw response set ``slopeDist`` is moved to ``slopeDistRaw``). The original
response set gets overwritten by the corrected value (``slopeDist`` then stores
the corrected distance).
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the DistanceCorrector to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"distanceCorrector": "modules.totalstation.DistanceCorrector"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"distanceCorrector": {
"distanceName": "slopeDist",
"temperature": 20.0,
"pressure": 1010.0,
"humidity": 0.6,
"atmosphericCorrectionEnabled": true,
"seaLevelCorrectionEnabled": false,
"sensorHeight": 100.0,
}
}
+----------------------------------+-------------+-----------------------------------------------+
| Name | Data Type | Description |
+==================================+=============+===============================================+
| ``distanceName`` | String | Name of the response set of the raw distance. |
+----------------------------------+-------------+-----------------------------------------------+
| ``temperature`` | Float | Default temperature in °C. |
+----------------------------------+-------------+-----------------------------------------------+
| ``pressure`` | Float | Default pressure in mbar/hPa. |
+----------------------------------+-------------+-----------------------------------------------+
| ``humidity`` | Float | Default humidity between ``0.0`` and ``1.0``. |
+----------------------------------+-------------+-----------------------------------------------+
| ``atmosphericCorrectionEnabled`` | Boolean | Enables atmospheric correction of distances. |
+----------------------------------+-------------+-----------------------------------------------+
| ``seaLevelCorrectionEnabled`` | Boolean | Enables sea level reduction of distances. |
+----------------------------------+-------------+-----------------------------------------------+
| ``sensorHeight`` | Float | Sensor height for sealevel reduction. |
+----------------------------------+-------------+-----------------------------------------------+
.. _helmert-transformer:
HelmertTransformer
~~~~~~~~~~~~~~~~~~
The HelmertTransformer module does a distortion-free seven-parameter
transformation from one datum to another in order to calculate the view point of
a total station and the coordiantes of observed target points. The coordinates
of the fixed points must be defined in the configuration.
An observation will be created for the view point and send to a list of
receivers. The calculated coordinates of the target points are stored as
response sets in the observations (``x``, ``y``, and ``z``).
.. note::
Please be aware that the keys of the fixed points defined in the dictionary
``fixedPoints`` must match the target names of the actual fixed points
observed by the total station. Otherwise, an assignment between them is not
possible.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the HelmertTransformer to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"helmertTransformer": "modules.totalstation.HelmertTransformer"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"helmertTransformer": {
"residualMismatchTransformationEnabled": true,
"viewPoint": {
"target": "p6",
"receivers": [
"fileExporter"
]
},
"fixedPoints": {
"p1": {
"x": 2000,
"y": 1000,
"z": 100
},
"p2": {
"x": 1995.488,
"y": 1003.768,
"z": 100.008
},
"p3": {
"x": 1994.49,
"y": 996.26,
"z": 100.021
}
}
}
}
+-------------------------------------------+-------------+------------------------------------------------------+
| Name | Data Type | Description |
+===========================================+=============+======================================================+
| ``residualMismatchTransformationEnabled`` | Boolean | Prorate residuals between the target points. |
+-------------------------------------------+-------------+------------------------------------------------------+
| ``viewPoint`` | Object | Target names and receivers of the view point. |
+-------------------------------------------+-------------+------------------------------------------------------+
| ``fixedPoints`` | Object | Target names and coordinates of the fixed points. |
+-------------------------------------------+-------------+------------------------------------------------------+
.. _polar-transformer:
PolarTransformer
~~~~~~~~~~~~~~~~
The PolarTransformer module is used to calculate polar coordinates from
Cartesian coordinates. The position of the sensor and the azimuth must be
defined in the configuration. The coordinates of a target point (``x``, ``y``,
and ``z``) are calculated by using trigonometric functions and then saved as
response sets in the observation.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the PolarTransformer to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"polarTransformer": "modules.totalstation.PolarTransformer"
}
}
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"polarTransformer": {
"viewPoint": {
"x": 2000,
"y": 992.51,
"z": 100
},
"fixedPoints": {
"p1": {
"x": 2000,
"y": 1000,
"z": 100
},
"p2": {
"x": 1995.488,
"y": 1003.768,
"z": 100.008
},
"p3": {
"x": 1994.49,
"y": 996.26,
"z": 100.021
}
},
"azimuthPointName": "p1",
"azimuthAngle": 100,
"adjustmentEnabled": true
}
}
+-----------------------+-------------+-------------------------------------------------+
| Name | Data Type | Description |
+=======================+=============+=================================================+
| ``viewPoint`` | Object | Coordinates of the sensor position (``x``, |
| | | ``y``, ``z``). |
+-----------------------+-------------+-------------------------------------------------+
| ``fixedPoints`` | Object | Coordinates of the fixed points (``x``, ``y``, |
| | | ``z``). |
+-----------------------+-------------+-------------------------------------------------+
| ``azimuthPointName`` | Object | Name of the fixed point that sets the azimuth. |
+-----------------------+-------------+-------------------------------------------------+
| ``azimuthAngle`` | Object | Global azimuth in gon. Set to ``0`` if no |
| | | global coordinate system is used. |
+-----------------------+-------------+-------------------------------------------------+
| ``adjustmentEnabled`` | Object | Turns the adjustment of the orientation using |
| | | more than one fixed point on or off (in German: |
| | | *Abriss*). |
+-----------------------+-------------+-------------------------------------------------+
.. _refraction-corrector:
RefractionCorrector
~~~~~~~~~~~~~~~~~~~
RefractionCorrector removes the influence of the refraction from a measured
distance and corrects the Z value of an observed target.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the RefractionCorrector to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"refractionCorrector": "modules.totalstation.RefractionCorrector"
}
}
Configuration
^^^^^^^^^^^^^
The module RefractionCorrector has nothing to configure.
.. _serial-measurement-processor:
SerialMeasurementProcessor
~~~~~~~~~~~~~~~~~~~~~~~~~~
The SerialMeasurementProcessor is used for total station observations in two
faces. The response sets of the first face have to be named ``hz0``, ``v0``, and
``slopeDist0``, whereas the response sets of the second face must be ``hz1``,
``v1``, and ``slopeDist1``. The module creates a new response set inside the
observation object for each arithmetically averaged value (named ``hz``, ``v``,
and ``slopeDist``).
An appropriate requests order is necessary for a measurement in two faces:
1. Set the direction to the target.
2. Do measure in face 0.
3. Get the measured values (``hz0``, ``v0``, ``slopeDist0``, etc.).
4. Change the total station to face 1.
5. Do measure face 1.
6. Get the measured values (``hz1``, ``v1``, ``slopeDist1``, etc.).
7. Change the total station back to face 0.
Example
^^^^^^^
The example shows a measurement with the Leica TM30 total station in two faces.
Both measurements, in face 0 and face 1, are done in one observation, with
response sets for each face.
.. code:: javascript
{
"name": "getP1",
"target": "p1",
"description": "complete measurement of P1",
"enabled": true,
"nextReceiver": 0,
"onetime": false,
"receivers": [
"preProcessor",
"returnCodeInspector",
"serialMeasurementProcessor",
"distanceCorrector",
"polarTransformer",
"fileExporter"
],
"requestSets": {
"changeFace": {
"enabled": true,
"request": "%R1Q,9028:1,1,0\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)",
"sleepTime": 0,
"timeout": 30
},
"getFace0": {
"enabled": true,
"request": "%R1Q,2026:\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)(?:,(?P\\d+))?",
"sleepTime": 0,
"timeout": 30
},
"getFace1": {
"enabled": true,
"request": "%R1Q,2026:\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)(?:,(?P\\d+))?",
"sleepTime": 0,
"timeout": 30
},
"getValuesFace0": {
"enabled": true,
"request": "%R1Q,2167:5000,1\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)(?:,(?P\\d*\\.?\\d+),(?P\\d*\\.?\\d+),(?P-?\\d*\\.?\\d+),(?P-?\\d*\\.?\\d*),(?P-?\\d*\\.?\\d*),(?P-?\\d*\\.?\\d*),(?P\\d*\\.?\\d*),(?P-?\\d*))?",
"sleepTime": 0,
"timeout": 30
},
"getValuesFace1": {
"enabled": true,
"request": "%R1Q,2167:5000,1\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)(?:,(?P\\d*\\.?\\d+),(?P\\d*\\.?\\d+),(?P-?\\d*\\.?\\d+),(?P-?\\d*\\.?\\d*),(?P-?\\d*\\.?\\d*),(?P-?\\d*\\.?\\d*),(?P\\d*\\.?\\d*),(?P-?\\d*))?",
"sleepTime": 0,
"timeout": 30
},
"measureDistanceFace0": {
"enabled": true,
"request": "%R1Q,2008:1,1\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)",
"sleepTime": 0,
"timeout": 30
},
"measureDistanceFace1": {
"enabled": true,
"request": "%R1Q,2008:1,1\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)",
"sleepTime": 0,
"timeout": 30
},
"setDirection": {
"enabled": true,
"request": "%R1Q,9027:0.0,1.59115,2,1,0\r\n",
"responseDelimiter": "\r\n",
"responsePattern": "(?:%R1P,0,0:)(?P\\d+)",
"sleepTime": 2,
"timeout": 30
}
},
"requestsOrder": [
"setDirection",
"getFace0",
"measureDistanceFace0",
"getValuesFace0",
"changeFace",
"getFace1",
"measureDistanceFace1",
"getValuesFace1",
"changeFace"
],
"responseSets": {
"accAngle0": {
"type": "float",
"unit": "rad"
},
"accAngle1": {
"type": "float",
"unit": "rad"
},
"accIncl0": {
"type": "float",
"unit": "rad"
},
"accIncl1": {
"type": "float",
"unit": "rad"
},
"c0": {
"type": "float",
"unit": "rad"
},
"c1": {
"type": "float",
"unit": "rad"
},
"distTime0": {
"type": "integer",
"unit": "ns"
},
"distTime1": {
"type": "integer",
"unit": "ns"
},
"face0": {
"Type": "integer",
"unit": "none"
},
"face1": {
"type": "integer",
"Unit": "none"
},
"hz0": {
"type": "float",
"unit": "rad"
},
"hz1": {
"type": "float",
"unit": "rad"
},
"l0": {
"type": "float",
"unit": "rad"
},
"l1": {
"type": "float",
"unit": "rad"
},
"rcChangeFace": {
"type": "integer",
"unit": "none"
},
"rcGetFace0": {
"type": "integer",
"unit": "none"
},
"rcGetFace1": {
"type": "integer",
"unit": "none"
},
"rcGetValues0": {
"type": "integer",
"unit": "none"
},
"rcGetValues1": {
"type": "integer",
"unit": "none"
},
"rcMeasureDistance0": {
"type": "integer",
"unit": "none"
},
"rcMeasureDistance1": {
"type": "integer",
"unit": "none"
},
"rcSetDirection": {
"type": "integer",
"unit": "none"
},
"slopeDist0": {
"type": "float",
"unit": "m"
},
"slopeDist1": {
"type": "float",
"unit": "m"
},
"v0": {
"type": "float",
"unit": "rad"
},
"v1": {
"type": "float",
"unit": "rad"
}
},
"sleepTime": 25
}
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the SerialMeasurementProcessor to the ``modules`` section of the core
configuration:
.. code:: javascript
{
"modules": {
"serialMeasurementProcessor": "modules.totalstation.SerialMeasurementProcessor"
}
}
Configuration
^^^^^^^^^^^^^
The module SerialMeasurementProcessor has nothing to configure.
Unix
----
Modules in the Unix package can be used on selected Unix operating systems only,
for example, FreeBSD, DragonFly BSD, NetBSD, and OpenBSD. This limitation may be
due to dependencies or system calls that are available on Unix only. In general,
modules of the Unix package are not compatible with Linux. Further restrictions
may apply.
.. _gpio-controller:
GpioController
~~~~~~~~~~~~~~
The GpioController uses system tools of FreeBSD, NetBSD, and OpenBSD to control
the GPIO interface of the Raspberry Pi single-board computer. The state of a
single pin can be set to either ``0`` or ``1`` in order to control external
devices or relays. The pin is switched by sending a message of type ``gpio`` to
the module instance. After the set duration the pin changes back to the default.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the GpioController to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"gpioController": "modules.unix.GpioController"
}
}
GPIO Message Format
^^^^^^^^^^^^^^^^^^^
The messages have to be structured in JSON format:
.. code:: javascript
[
{
"type": "gpio"
},
{
"value": "1"
}
]
+-------------+-------------+---------------------------------------------------------+
| Name | Data Type | Description |
+=============+=============+=========================================================+
| ``value`` | String | Value to set the pin to (e.g., ``"0"`` or ``"1"``). |
+-------------+-------------+---------------------------------------------------------+
Configuration
^^^^^^^^^^^^^
.. code:: javascript
{
"gpioController": {
"defaultState": 0,
"duration": 5.0,
"pin": "pin_17"
}
}
+-------------------+-------------+---------------------------------------------------+
| Name | Data Type | Description |
+===================+=============+===================================================+
| ``defaultState`` | Integer | Default state of the pin (either ``0`` or ``1``). |
+-------------------+-------------+---------------------------------------------------+
| ``duration`` | Float | Duration of the state change. |
+-------------------+-------------+---------------------------------------------------+
| ``pin`` | String | Name of the pin defined in the GPIO configuration |
| | | of the OS. |
+-------------------+-------------+---------------------------------------------------+
Virtual
-------
OpenADMS supports virtual sensors, which simulate physical ones. The logic of
the virtual sensors is stored in single modules in the file
``module/virtual.py``. The Python class ``VirtualSensor`` is the parent class
for the inheritance of new sensors.
.. _virtual-dtm:
VirtualDTM
~~~~~~~~~~
The VirtualDTM simulates an `STS DTM`_ temperature/pressure sensor. The virtual
sensor returns random temperature values between –20 and +40 °C as well as
random pressure values between 980 and 1150 hPa.
The VirtualDTM can be used like a real sensor. Create a :ref:`scheduler` and set
the name of the sensor to the name of the VirtualDTM instance.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the VirtualDTM to the ``modules`` section of the core configuration:
.. code:: javascript
{
"modules": {
"virtualDtm": "modules.virtual.VirtualDTM"
}
}
Configuration
^^^^^^^^^^^^^
The module VirtualDTM has nothing to configure.
.. _virtual-indicator-one:
VirtualIndicatorOne
~~~~~~~~~~~~~~~~~~~
The VirtualIndicatorOne simulates a `Sylvac S\_Dial ONE`_ digital
indicator/extensometer. The virtual sensor returns values of a sine wave between
0.0 and 26.0 mm (measurement range of the physical sensor).
The virtual sensor can be used like a real one. Create a :ref:`scheduler`
and set the name of the sensor to the name of the VirtualIndicatorOne instance.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the VirtualIndicatorOne to the ``modules`` section of the core
configuration:
.. code:: javascript
{
"modules": {
"virtualIndicatorOne": "modules.virtual.VirtualIndicatorOne"
}
}
Configuration
^^^^^^^^^^^^^
The module VirtualIndicatorOne has nothing to configure.
.. _virtual-total-station-tm30:
VirtualTotalStationTM30
~~~~~~~~~~~~~~~~~~~~~~~
The VirtualTotalStationTM30 simulates a Leica TM30 total station, but can also
be used as any other modern total station of Leica Geosystems. The module
returns just random data in defined ranges. The following Leica GeoCOM commands
are implemented yet:
+-------------+--------------------------------------------------+
| Return Code | Description |
+=============+==================================================+
| ``2008`` | Measure the distance. |
+-------------+--------------------------------------------------+
| ``2167`` | Do a complete measurement and return the values. |
+-------------+--------------------------------------------------+
| ``5003`` | Get the sensor ID. |
+-------------+--------------------------------------------------+
| ``5004`` | Get the sensor name. |
+-------------+--------------------------------------------------+
| ``9027`` | Set the direction. |
+-------------+--------------------------------------------------+
More GeoCOM commands can be added easily. Later versions of the module may
include further ones.
The VirtualTotalStationTM30 can be used like a real sensor. Create a
:ref:`scheduler` and set the name of the sensor to the name of the
VirtualTotalStationTM30 instance.
Loading the Module
^^^^^^^^^^^^^^^^^^
Add the VirtualTotalStationTM30 to the ``modules`` section of the core
configuration:
.. code:: javascript
{
"modules": {
"virtualTotalStationTM30": "modules.virtual.VirtualTotalStationTM30"
}
}
Configuration
^^^^^^^^^^^^^
The module VirtualTotalStationTM30 has nothing to configure.
.. _Apache CouchDB: http://couchdb.apache.org/
.. _Arrow tokens: http://arrow.readthedocs.io/en/latest/#tokens
.. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO
.. _Wikipedia: https://en.wikipedia.org/wiki/Heartbeat_(computing)
.. _Mastodon: https://mastodon.social/
.. _joinmastodon.org: https://joinmastodon.org/
.. _MC Technologies: https://www.mc-technologies.net/
.. _more information: http://www.regular-expressions.info/named.html
.. _STS DTM: http://www.sts-sensors.com/us/LinkClick.aspx?link=media%2Fdatasheets%2FDatasheet_DTM_Pressure_transmitter_485_232_us.pdf&tabid=403&mid=900
.. _Sylvac S\_Dial ONE: http://www.studenroth.com/de/pdf/Messuhren_2013_PDF/Dial_One.pdf