Specifications¶
Specifications of the aedifion.io MQTT API.
Overview¶
Part of the aedifion.io platform is an MQTT broker which serves as the single logical point of data ingress to the aedifion.io, e.g., all data collected in the field through the aedifion Edge Devices is ingested to aedifion.io through this MQTT broker and, in turn, can also be subscribed to. The MQTT broker is clustered, i.e., distributed over multiple independent servers, to ensure seamless scalability and high availability.
MQTT Broker¶
aedifion currently maintains two MQTT brokers:
- Production
- Stable broker that receives updates and new features only after an intensive testing phase in our development environment.
- Host: mqtt2.aedifion.io
- Ports:
- 8884 - MQTT over TLS 1.2 (use in standalone clients)
- 9001 - MQTT over websockets over TLS 1.2 (use from within browsers)
- Development
- Semi-stable broker that receives updates and new features after a short internal testing phase.
- Host: mqtt-dev.aedifion.io
- Ports:
- 8884 - MQTT over TLS 1.2 (use in standalone clients)
- 9001 - MQTT over websockets over TLS 1.2 (use from within browsers)
Both brokers only accept TLS 1.2 encrypted connections, i.e., all plain TCP connections are rejected. The broker's certificates can be viewed, e.g., by connecting to https://mqtt2.aedifion.io or https://mqtt-dev.aedifion.io from any browser.

Figure 1: Server MQTT certificate of the production MQTT broker
Your operating system (OS) will accept this certificate if the DST Root CA X3 certificate is installed as a trusted root certification authority (CA) in your OS [1]. Don't worry, this is probably the case and you don't have to do anything. You can test if the certificate is accepted by navigating to https://mqtt2.aedifion.io or https://mqtt-dev.aedifion.io - if your browser doesn't issue a warning, you're fine.
Both brokers accept connections on two ports: 8884 and 9001. Port 8884 accepts plain MQTT, i.e., connections that transport MQTT directly via TLS. This is the standard case and, if in doubt, this port is the right choice. Port 9001 accepts websockets connections, i.e., connections that transport the MQTT protocol within the websockets protocol which in turn is transported via TLS. MQTT via websockets is the right choice when you want to send/receive MQTT data directly from a web browser [2,3].
Summary:
- Two MQTT brokers available: production and development
- Test the connection:
- Point a browser to https://mqtt2.aedifion.io or https://mqtt-dev.aedifion.io
- No warnings should occur.
- If you have openssl installed, open a command line and execute
openssl s_client -connect mqtt2.aedifion.io:8884 -servername mqtt2.aedifion.io
Check that the TLS handshake is ok
- There will be a warning
verify error:num=20:unable to get local issuer certificate
at the top, which can be fixed by providing option-CAfile
or-CApath
and pointing to the right locations depending on your OS, e.g.,-CAfile /etc/ssl/cert.pem
on Mac OS.
Sources and further resources:
[1] Let's encrypt's chain of trust: https://letsencrypt.org/certificates/
[2] MQTT over websockets: https://www.hivemq.com/blog/mqtt-essentials-special-mqtt-over-websockets/
[3] MQTT over websockets: http://www.steves-internet-guide.com/mqtt-websockets/
Authentication¶
The MQTT brokers only accept connections from authenticated clients.
After having established a TLS connection, the MQTT client has to present login credentials (username
and password
) to the MQTT broker. Client credentials can be obtained with limited and unlimited validity.
Credentials with unlimited validity are provided only on request by the aedifion staff.
Please email us at support@aedifion.io.
Credentials with limited validity can be created through the aedifion.io HTTP API using the POST /v2/project/{project_id}/mqttuser
endpoint. This endpoint requires the following parameters:
Parameter | Datatype | Type | Required | Description | Example |
---|---|---|---|---|---|
project_id | integer | path | yes | The numeric id of the project for which to add a new MQTT user account. | 1 |
username | string | body (JSON) | yes | The username of the new MQTT user. If that username exists, the request is rejected. | my_mqtt_user |
password | string | body (JSON) | yes | The password for the new MQTT user. | mys3cr3tp4ssw0rd |
rights | string | body (JSON) | no | Grant read or write permissions to this account. Note that write permission imply read permissions. Defaults to read. | read |
validity | integer | body (JSON) | no | This user account will expire after this many seconds. Maximum validity is 2 hours = 7200 seconds. | 3600 |
description | string | body (JSON) | no | Human readable description what this account is about. | A new test account just for reading. |
Explore our HTTP API tutorials or the HTTP API developer articles to learn how to build, authenticate, and post a corresponding HTTP request to the POST /v2/project/{project_id}/mqttuser
endpoint. A successful response looks likes this:
{
"operation": "create",
"resource": {
"description": "A new test account just for reading.",
"id": 42,
"topics": [
{
"id": 123,
"rights": "read",
"topic": "lbg01/mybuilding/#"
}
],
"username": "my_mqtt_user",
"valid_until": "2019-01-18T16:23:01.707344Z"
},
"success": true
}
The response is in JSON format, which can be easily parsed in any programming language. The resource field contains the details of the newly created user (not the password, of course, for security reasons). Note that this request was posted at 16:23h CET and with a requested validity of 1 hour, i.e., exactly 16:23h UTC since CET = UTC + 1.
After the MQTT account expires it will be automatically removed. You can either create a new account with the same username afterwards or renew the existing account before it expires using the PUT /v2/project/{project_id}/mqttuser/{mqttuser_id}
endpoint. This endpoint generally allows you to modify the MQTT user account. It accepts the following parameters:
Parameter | Datatype | Type | Required | Description | Example |
---|---|---|---|---|---|
project_id | integer | path | yes | The numeric id of the project for which to edit an MQTT user account. | 1 |
mqttuser_id | integer | path | yes | The id of the existing MQTT user account to apply changes to. | 42 |
password | string | body (JSON) | no | The changed password for the given MQTT user account. | ch4ng3dp4ssw0rd |
rights | string | body (JSON) | no | The changed read or write permissions to this account. Note that write permission imply read permissions. | read |
validity | integer | body (JSON) | no | The expiry of the given MQTT user account will be extended by this many seconds into the future from the time of the update. Maximum validity is 2 hours = 7200 seconds. | 7200 |
description | string | body (JSON) | no | The changed human readable description what this account is about. | A new test account just for reading with a new password. |
A successful response looks like this:
{
"operation": "",
"resource": {
"description": "A new test account just for reading with a new password.",
"id": 42,
"topics": [
{
"id": 123,
"rights": "read",
"topic": "lbg01/mybuilding/#"
}
],
"username": "my_mqtt_user",
"valid_until": "2019-01-18T17:28:39.392003Z"
},
"success": true
}
As you can see, the expiry date of the MQTT user account was extended by 7200 seconds = 2 hours from the time of the update (in this example, the update was sent roughly five minutes after the initial creation of the account).
Client Identifiers¶
Clients are identified by a unique client_id
.
As per MQTT 3.1.1 specification (Section 3.1.3.1), client identifiers are between 1 and 23 alphanumeric characters (0-9, a-z, A-Z). Most MQTT brokers support longer client identifiers from the the full range of UTF-8 characters except characters /
, +
, and #
which have a special meaning in MQTT and are disallowed for security reasons.
There can only be one connection per client_id
per Broker. If two clients connect with the same client_id
the older connection is terminated in favor of the newer. This restriction does not extend to your login credentials. You can open multiple connections using the same login credentials as long as you use a different client_id for each concurrent connection.
Choose a client_id
and avoid special characters. Postfix the client_id
with a random string or integer to ensure it is unique across concurrent connections.
Authorization¶
The MQTT broker authorizes clients to subscribe and publish based on topics.
Once connected and authenticated, the client can publish or subscribe to one or multiple topics [1,2] - but not without authorization. To subscribe, the client needs read access to that topic. To publish, the client needs write access. Note that write access implies read access.
Authorization is specified through a list of topics (following exactly MQTT's topic syntax and semantics [1,2]) where for each topic it is specified whether the user has read or read/write access. Make sure to familiarize yourself with MQTT's topic structure, especially with hierarchy levels and the #
wildcard [1,2].
Topic hierarchy¶
All MQTT topics on aedifion.io have a hierarchy that consists of two main parts, i.e., a fixed prefix and a variable postfix.
The prefix has two hierarchies and is assigned by aedifion:
load-balancing-group/project-handle
- The top level hierarchy, the
load-balancing-group
, is fixed and assigned by aedifion. It serves to separate different customers and projects and ensures that each customer and project is guaranteed separate and sufficient processing and communication resources. - The second level hierarchy, the
project-handle
, is a fixed (human-readable) string assigned by aedifion that uniquely identifies your project. This hierarchy separates different projects on the same load balancing group.
As an aedifion.io customer, you receive authorization to this prefix, i.e., to the topic load-balancing-group/project-handle/#
, i.e., you can publish and subscribe to "anything below" the project level of the topic hierarchy.
The postfix matching the #
can generally have arbitrary length or structure as long as they are UTF-8 strings.
-
If you've purchased an aedifion Edge Device, e.g., this device collects data from different datapoints on your building network and publishes them to the postfixes
datapoint_1
, ...,datapoint_n
. Via MQTT, you thus have datapoint-level publish/subscribe access to the datapoints of your building. For efficiency reasons, the Edge Device uses short 4 to 12 characters long identifiers generated from the full datapoint names, for example:load-balancing-group/project-handle/0OHgK8nP
.aedifion's hash identifiers creation
- Build a SHA1 hash out of the UTF-8 encoded datapoint id.
- Cut the first
hash_id_length
characters wherehash_id_length
is configured individually per project (default = 8). - base62-encode the shortened hash.
Here's a sample implementation in Python using the pybase62 module.
import base62 def base62id(s: str, hash_id_length: int = 8): return base62.encodebytes(hashlib.sha1(s.encode('utf-8')).digest())[:hash_id_length]