External API v1.0
Abstract
The External API is supposed to convey ECOLOG-PRO and ECOLOG-PRO RADIO device related deviations occurring inside elproMONITOR. The push concept is realized through a message broker, namely RabbitMQ.
RabbitMQ is a messaging broker that accepts messages from publishers, routes them, and delivers them to consumers
Supported protocols
AMQP 0-9-1 (ELPRO recommend the use of this protocol for communication).
High concept documentation: AMQP 0-9-1 Model Explained | RabbitMQ
Complete reference: AMQP 0-9-1 Complete Reference Guide | RabbitMQ
MQTT 3.1 (at least RabbitMQ 3.0)
MQTT 3.1.1 (at least RabbitMQ 3.3)
MQTT 5.0 (at least RabbitMQ 3.13)
AMQP
AMQP focuses on the exchange of messages between applications or organizations.
Message Orientation: AMQP focuses on the exchange of messages between applications or organizations.
Queuing: It supports message queuing, allowing messages to be stored and delivered in a reliable manner.
Routing: AMQP provides both point-to-point and publish-and-subscribe routing mechanisms.
Reliability: It ensures reliable message delivery, with options for at-most-once, at-least-once, and exactly-once semantics.
Security: AMQP supports authentication and encryption based on SASL and/or TLS.
MQTT
MQTT (Message Queuing Telemetry Transport) is a widely used protocol for lightweight messaging and communication in the Internet of Things (IoT) domain
MQTT Overview:
MQTT is designed for efficient communication between devices, especially in resource-constrained environments.
It follows a publish-subscribe model, where clients (devices or applications) publish messages to topics, and other clients subscribe to those topics to receive the messages.
The protocol is lightweight, making it suitable for low-bandwidth and high-latency networks.
MQTT Components:
Brokers/Server: MQTT brokers (or servers) manage the communication between clients. They handle message routing, topic subscriptions, and message persistence.
Clients: Devices or applications that communicate using MQTT. Clients can be publishers (sending messages) or subscribers (receiving messages).
Topics: Logical channels to which clients publish or subscribe. Topics allow fine-grained control over message distribution.
Quality of Service (QoS): MQTT supports different QoS levels (0, 1, and 2) to ensure reliable message delivery.
QoS 2 is not supported! The communication is based on AMQP in elproMONITOR.
Authentication and authorization
Each customer is provided their own space to consume and restrict information inside RabbitMQ called a virtual host
Basic authentication
Customers can authenticate to the broker by the provided username and password
Customers can only access and act inside their own given virtual host
Each customer has permissions to establish their desired topology, consume and publish messages inside the virtual host
Certificate based authentication TBD
Pre-existing topology
After or during installation of elproMONITOR we must provide a minimum pre-existing infrastructure by completing the steps below. These steps should be repeated for each and every customer (organization).
Creating a virtual host
Creating a user with configure, read, write permissions restricted to the above created virtual host
Tie the virtual host to the given organization inside elproMONITOR
Starting elproMONITOR service should take care of creating a topic exchange (RabbitMQ tutorial - Topics | RabbitMQ ) named “ex.elproMONITOR ” inside the virtual host, used to delegate messages pushed by the external API.
Provide the customer with the user’s credentials
We recommend installing the message broker on the elproMONITOR server.
If the message broker and the elproMONITOR are running on different servers, the messages should be encrypted with TLS to prevent them from being read or manipulated over the network.
This requires a more complex setup for both servers.
Topics and message types
Every topic/routing key starts with the MAJOR number of the version of the provided API. Multiple versions of the API can coexist inside elproMONITOR. The below message types are provided for the fist version (v1) of the API. The message format is JSON.
Be careful when providing topic/routing key for message consumption. RabbitMQ uses “.” as a default separator when you define routing keys for queues via AMQP.
If you want to subscribe with MQTT “/” should be used as a separator as defined in the protocol, RabbitMQ automatically translates it internally.
Last Will and Testament (LWT)
LWT is a MQTT feature for handling client disconnections.
elproMONITOR don’t support LWT. Communication is based on the AMQP protocol.
The connection from elproMONITOR to the broker is re-established automatically and any unprocessed messages are not lost and are forwarded.
Consumer Acknowledgements and Publisher Confirms
Systems that use a messaging broker such as RabbitMQ are by definition distributed. Since protocol methods (messages) sent are not guaranteed to reach the peer or be successfully processed by it, both publishers and consumers need a mechanism for delivery and processing confirmation.
elproMONITOR confirms are not aware of consumers: they only cover publisher's interactions with node it is connected to, and the queue (or stream) leader replica.
Consumer acknowledgements are not aware of publishers: their goal is to confirm to a RabbitMQ node that a given delivery was successfully received and processed successfully, so the delivered message can be marked for future deletion.
MQTT Persistent Session
It is recommend that the client (consumer/participant) sets up a persistent session with an MQTT broker. In this way, the client can continue communication seamlessly if it interrupts the connection and resumes it later.
AMQP Time-to-Live and Expiration
Message TTL (Time-to-Live) determines how long messages can be retained in a queue. If the retention period of a message in a queue exceeds the message TTL of the queue, the message expires and is discarded.
elproMONITOR messages do not contain an expiration property, so they remain in the queue until they are cancelled.
It is recommended to set up a durable queue that can survive a crash or restart of the broker, provided that the messages in the queue are also permanent.
Frame
Each message has a frame and a content inside that frame depending on the type of message that was pushed. The frame has the following format:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Message",
"type": "object",
"additionalProperties": false,
"properties": {
"MessageId": {
"type": "string",
"format": "guid"
},
"MessageDateTimeUtc": {
"type": "string",
"format": "date-time"
},
"OrganizationId": {
"type": "string",
"format": "guid"
},
"ApiVersion": {
"type": "string"
},
"MessageType": {
"type": "string"
},
"Content": {
"type": "object"
}
}
}
Name | Type | Format | Values | Description |
---|---|---|---|---|
MessageId | string | guid |
| Each message has an individual Id |
MessageDateTimeUtc | string | date-time |
| Represents the time in UTC the message was pushed by the external API |
OrganizationId | string | guid |
| Internal Id of the given organization |
ApiVersion | string |
| v1 | The version of the API that pushed the message |
MessageType | string |
| InputLimitDeviation, | Represents the message type which is tied to the content defined inside the frame |
Content | object |
|
| Content of the message |
InputLimitDeviationMessage
MessageType | InputLimitDeviation |
Topic/Routing key: | v1.inputdeviations.{ioModuleId}.{inputId}.limit |
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "InputLimitDeviationMessage",
"type": "object",
"additionalProperties": false,
"properties": {
"IncidentId": {
"type": "integer",
"format": "int32"
},
"InputId": {
"type": "integer",
"format": "int32"
},
"InputName": {
"type": "string"
},
"IoModuleId": {
"type": "integer",
"format": "int32"
},
"IoModuleName": {
"type": "string"
},
"IoModuleSerialNumber": {
"type": "string"
},
"InputLimitDeviationType": {
"type": "string"
},
"Limit": {
"type": "number",
"format": "double"
},
"Measurement": {
"type": "number",
"format": "double"
},
"UnitOfMeasurement": {
"type": "string"
},
"StartTimeUtc": {
"type": "string",
"format": "date-time"
},
"EndTimeUtc": {
"type": [
"null",
"string"
],
"format": "date-time"
},
"IsActive": {
"type": "boolean"
},
"ConfirmTime1Utc": {
"type": [
"null",
"string"
],
"format": "date-time"
},
"ConfirmTime2Utc": {
"type": [
"null",
"string"
],
"format": "date-time"
}
}
}
Name | Type | Format | Values | Description |
---|---|---|---|---|
IncidentId | integer | int32 |
| elproMONITOR assigned Id which identifies the deviation |
InputId | integer | int32 |
| elproMONITOR assigned Id of the Input (Sensor) |
InputName | string |
|
| elproMONITOR assigned Name of the Input (sensor) |
IoModuleId | integer | int32 |
| elproMONITOR assigned Id of the IoModule |
IoModuleName | string |
|
| elproMONITOR assigned Name of the IoModule |
IoModuleSerialNumber | string |
|
| elproMonitor assigned SerialNumber of the IoModule |
StartTimeUtc | string | date-time |
| Start of deviation in UTC |
EndTimeUtc | null | date-time |
| End of deviation in UTC |
InputLimitDeviationType | string |
| AlarmUpper, | Type of the deviation that occured based on the Limit Profile set in elproMONITOR |
Limit | number | double |
| The exceeded limit set in the Limit Profile inside elproMONITOR |
Measurement | number | double |
| The measurement that exceeded the given limit |
UnitOfMeasurement | string |
| °C, | The unit of the measurement |
IsActive | boolean |
|
| True if the deviation is active. Also indicated by EndTimeUtc being null. |
ConfirmTime1Utc | null string | date-time |
| UTC datetime of the first user confirmation of the deviation |
ConfirmTime2Utc | null string | date-time |
| UTC datetime of the second user confirmation of the deviation |
InputFailureDeviationMessage
MessageType | InputFailureDeviation |
Topic/Routing key: | v1.inputdeviations.{ioModuleId}.{inputId}.failure |
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "InputFailureDeviationMessage",
"type": "object",
"additionalProperties": false,
"properties": {
"IncidentId": {
"type": "integer",
"format": "int32"
},
"InputId": {
"type": "integer",
"format": "int32"
},
"InputName": {
"type": "string"
},
"IoModuleId": {
"type": "integer",
"format": "int32"
},
"IoModuleName": {
"type": "string"
},
"IoModuleSerialNumber": {
"type": "string"
},
"StartTimeUtc": {
"type": "string",
"format": "date-time"
},
"EndTimeUtc": {
"type": [
"null",
"string"
],
"format": "date-time"
},
"IsActive": {
"type": "boolean"
},
"ConfirmTime1Utc": {
"type": [
"null",
"string"
],
"format": "date-time"
},
"ConfirmTime2Utc": {
"type": [
"null",
"string"
],
"format": "date-time"
}
}
}
Name | Type | Format | Values | Description |
---|---|---|---|---|
IncidentId | integer | int32 |
| elproMONITOR assigned Id which identifies the deviation |
InputId | integer | int32 |
| elproMONITOR assigned Id of the Input (Sensor) |
InputName | string |
|
| elproMONITOR assigned Name of the Input (sensor) |
IoModuleId | integer | int32 |
| elproMONITOR assigned Id of the IoModule |
IoModuleName | string |
|
| elproMONITOR assigned Name of the IoModule |
IoModuleSerialNumber | string |
|
| elproMonitor assigned SerialNumber of the IoModule |
StartTimeUtc | string | date-time |
| Start of deviation in UTC |
EndTimeUtc | null | date-time |
| End of deviation in UTC |
IsActive | boolean |
|
| True if the deviation is active. Also indicated by EndTimeUtc being null. |
ConfirmTime1Utc | null string | date-time |
| UTC datetime of the first user confirmation of the deviation |
ConfirmTime2Utc | null string | date-time |
| UTC datetime of the first second confirmation of the deviation |
InputBatteryLowLevelDeviationMessage
MessageType | InputBatteryLowLevelDeviation |
Topic/Routing key: | v1.inputdeviations.{ioModuleId}.{inputId}.batterylowlevel |
Name | Type | Format | Values | Description |
---|---|---|---|---|
IncidentId | integer | int32 |
| elproMONITOR assigned Id which identifies the deviation |
InputId | integer | int32 |
| elproMONITOR assigned Id of the Input (Sensor) |
InputName | string |
|
| elproMONITOR assigned Name of the Input (sensor) |
IoModuleId | integer | int32 |
| elproMONITOR assigned Id of the IoModule |
IoModuleName | string |
|
| elproMONITOR assigned Name of the IoModule |
IoModuleSerialNumber | string |
|
| elproMonitor assigned SerialNumber of the IoModule |
StartTimeUtc | string | date-time |
| Start of deviation in UTC |
EndTimeUtc | null | date-time |
| End of deviation in UTC |
IsActive | boolean |
|
| True if the deviation is active. Also indicated by EndTimeUtc being null. |
ConfirmTime1Utc | null string | date-time |
| UTC datetime of the first user confirmation of the deviation |
ConfirmTime2Utc | null string | date-time |
| UTC datetime of the first second confirmation of the deviation |
InputRadioStrengthDeviationMessage
MessageType | InputRadioStrengthDeviation |
Topic/Routing key: | v1.inputdeviations.{ioModuleId}.{inputId}.radiostrength |
Name | Type | Format | Values | Description |
---|---|---|---|---|
IncidentId | integer | int32 |
| elproMONITOR assigned Id which identifies the deviation |
InputId | integer | int32 |
| elproMONITOR assigned Id of the Input (Sensor) |
InputName | string |
|
| elproMONITOR assigned Name of the Input (sensor) |
IoModuleId | integer | int32 |
| elproMONITOR assigned Id of the IoModule |
IoModuleName | string |
|
| elproMONITOR assigned Name of the IoModule |
IoModuleSerialNumber | string |
|
| elproMonitor assigned SerialNumber of the IoModule |
StartTimeUtc | string | date-time |
| Start of deviation in UTC |
EndTimeUtc | null | date-time |
| End of deviation in UTC |
IsActive | boolean |
|
| True if the deviation is active. Also indicated by EndTimeUtc being null. |
ConfirmTime1Utc | null string | date-time |
| UTC datetime of the first user confirmation of the deviation |
ConfirmTime2Utc | null string | date-time |
| UTC datetime of the first second confirmation of the deviation |
InputNoConnectionDeviationMessage
MessageType | InputNoConnectionDeviation |
Topic/Routing key: | v1.inputdeviations.{ioModuleId}.{inputId}.noconnection |
Name | Type | Format | Values | Description |
---|---|---|---|---|
IncidentId | integer | int32 |
| elproMONITOR assigned Id which identifies the deviation |
InputId | integer | int32 |
| elproMONITOR assigned Id of the Input (Sensor) |
InputName | string |
|
| elproMONITOR assigned Name of the Input (sensor) |
IoModuleId | integer | int32 |
| elproMONITOR assigned Id of the IoModule |
IoModuleName | string |
|
| elproMONITOR assigned Name of the IoModule |
IoModuleSerialNumber | string |
|
| elproMonitor assigned SerialNumber of the IoModule |
StartTimeUtc | string | date-time |
| Start of deviation in UTC |
EndTimeUtc | null | date-time |
| End of deviation in UTC |
IsActive | boolean |
|
| True if the deviation is active. Also indicated by EndTimeUtc being null. |
ConfirmTime1Utc | null string | date-time |
| UTC datetime of the first user confirmation of the deviation |
ConfirmTime2Utc | null string | date-time |
| UTC datetime of the first second confirmation of the deviation |
DigitalInputDeviationMessage
MessageType | DigitalInputDeviation |
Topic/Routing key: | v1.inputdeviations.{ioModuleId}.{inputId}.digitalinput |
Name | Type | Format | Values | Description |
---|---|---|---|---|
IncidentId | integer | int32 |
| elproMONITOR assigned Id which identifies the deviation |
InputId | integer | int32 |
| elproMONITOR assigned Id of the DigitalInput |
InputName | string |
|
| elproMONITOR assigned Name of the DigitalInput |
IoModuleId | integer | int32 |
| elproMONITOR assigned Id of the IoModule |
IoModuleName | string |
|
| elproMONITOR assigned Name of the IoModule |
StartTimeUtc | string | date-time |
| Start of deviation in UTC |
EndTimeUtc | null | date-time |
| End of deviation in UTC |
Limit | number | double |
| The exceeded limit set in the Limit Profile inside elproMONITOR |
Measurement | number | double |
| The measurement that exceeded the given limit |
Code Examples
MQTT protocol using MQTTnet and basic authentication
AMQP using RabbitMQ.Client and basic authentication