Skip to main content
Version: Next

User-defined mappers

Proposal

This section details a proposal which is not yet implemented. The proposal is made public under the 'next' version to encourage feedback for upcoming features.

If you want to provide feedback, please reach out to us on GitHub or Discord.

Overview

In addition to the built-in cloud mappers (Cumulocity, Azure, AWS), thin-edge supports user-defined mappers that can bridge a device to any IoT cloud platform with an MQTT interface.

A user-defined mapper is a directory under /etc/tedge/mappers/ that contains a mapper.toml configuration file. Starting the mapper with tedge-mapper <name> will look for this directory and run the mapper using the flows engine and/or MQTT bridge configured within it.

Directory layout

Each mapper lives in its own directory under /etc/tedge/mappers/:

/etc/tedge/mappers/
└── thingsboard/ ← mapper name
├── mapper.toml ← required: mapper configuration
├── bridge/ ← optional: MQTT bridge rules
│ └── rules.toml
└── flows/ ← optional: message transformation flows
└── telemetry.toml

The mapper name must:

  • start with a lowercase ASCII letter (az)
  • contain only lowercase letters, digits, and hyphens (-)
  • not contain underscores or uppercase letters

Valid names: thingsboard, my-cloud, edge-platform

Invalid names: ThingsBoard, my_cloud, 1cloud

mapper.toml

The mapper.toml file in the mapper directory configures the cloud broker connection. It is required for user-defined mappers but optional if the mapper only uses the flows engine without an MQTT bridge.

A minimal mapper.toml that connects to a ThingsBoard broker using certificate auth:

url = "mqtt.thingsboard.io:8883"

[device]
cert_path = "cert.pem" # relative paths resolved to mapper dir
key_path = "key.pem"

A full example with all supported fields:

# Cloud broker URL — required for MQTT bridge
url = "mqtt.example.com:8883"

# Authentication: auto (default), certificate, or password
auth_method = "auto"

# Path to a credentials file for username/password auth
# credentials_path = "credentials.toml"

[device]
# MQTT client ID (defaults to the certificate CN if not set)
# id = "my-device"

# Client certificate for mutual TLS.
# Relative paths are resolved relative to the mapper directory.
# Falls back to tedge.toml device.cert_path / device.key_path when absent.
cert_path = "cert.pem"
key_path = "key.pem"

# CA certificate for verifying the cloud broker's TLS certificate.
# Defaults to the system trust store when absent.
# root_cert_path = "/usr/share/ca-certificates/my-cloud-ca.pem"

[bridge]
# Whether to use a clean MQTT session (default: false)
clean_session = false

# MQTT keepalive interval (e.g. "60s", "2m")
# keepalive_interval = "60s"

# Any additional fields you add here are available as ${mapper.*} in bridge rules.
# For example, this field is accessible as ${mapper.bridge.topic_prefix}.
topic_prefix = "v1/devices/me"

Template variables (${mapper.*})

The entire mapper.toml is available for template expansion in bridge rule files via the ${mapper.*} namespace. This means you can reference any field — including user-defined ones — directly in your bridge rules without repeating values:

# bridge/rules.toml — uses ${mapper.bridge.topic_prefix} from mapper.toml
remote_prefix = "${mapper.bridge.topic_prefix}/"

[[rule]]
topic = "telemetry"
direction = "outbound"

See Configurable bridge: ${mapper.*} for details.

Relative paths

All path fields in mapper.toml (device.cert_path, device.key_path, device.root_cert_path, credentials_path) support relative paths. Relative paths are resolved relative to the mapper directory, not the process working directory. For example, cert_path = "cert.pem" in /etc/tedge/mappers/thingsboard/mapper.toml resolves to /etc/tedge/mappers/thingsboard/cert.pem.

Absolute paths are returned unchanged.

Certificate fallback

When device.cert_path and device.key_path are absent from mapper.toml, the mapper falls back to device.cert_path and device.key_path from the root tedge.toml. Explicit mapper.toml values always take precedence.

cloud_type field

The cloud_type field identifies which built-in cloud integration this mapper belongs to. Valid values are: c8y, az, aws.

For custom cloud platforms (e.g. ThingsBoard), you should not set this field.

cloud_type = "c8y"           # opt into Cumulocity built-in integration
# INVALID: cloud_type = "thingsboard" - non built-in mappers should not specify this field

Starting a user-defined mapper

sudo tedge-mapper thingsboard

Or with systemd (after creating a service file for tedge-mapper-thingsboard):

sudo systemctl start tedge-mapper-thingsboard

The corresponding service name is tedge-mapper-<name>.

tedge mapper commands

The tedge mapper subcommand of the tedge CLI provides utilities for inspecting user-defined mappers configured on the device. This is distinct from tedge-mapper, which is the mapper daemon binary that actually runs a mapper process.

tedge mapper list

Lists all configured mappers under /etc/tedge/mappers/ (directories that contain a mapper.toml), along with their cloud_type if set.

tedge mapper list
Example output
c8y       cloud_type=c8y
thingsboard

tedge mapper config get

Reads a configuration value from a mapper's mapper.toml using a dotted key path:

tedge mapper config get thingsboard.url
Example output
mqtt.thingsboard.io:8883

Nested keys use dot notation:

tedge mapper config get thingsboard.device.cert_path
Example output
/etc/tedge/mappers/thingsboard/cert.pem

Example: ThingsBoard

The following example illustrates how to structure a ThingsBoard mapper. It is intended to show how the pieces fit together, not as a ready-to-run ThingsBoard integration. For a maintained, working example see the tedge-flows-examples repository.

1. Create the mapper directory

sudo mkdir -p /etc/tedge/mappers/thingsboard

2. Create mapper.toml

sudo tee /etc/tedge/mappers/thingsboard/mapper.toml <<'EOF'
url = "mqtt.thingsboard.io:8883"

[device]
cert_path = "cert.pem" # relative to /etc/tedge/mappers/thingsboard/
key_path = "key.pem"

[bridge]
# Custom field — available as ${mapper.bridge.topic_prefix} in bridge rules
topic_prefix = "v1/devices/me"
EOF

3. Add bridge rules

sudo mkdir -p /etc/tedge/mappers/thingsboard/bridge
sudo tee /etc/tedge/mappers/thingsboard/bridge/telemetry.toml <<'EOF'
remote_prefix = "${mapper.bridge.topic_prefix}/"

[[rule]]
local_prefix = "tb/"
topic = "telemetry"
direction = "outbound"

[[rule]]
local_prefix = "tb/"
topic = "rpc/request/#"
direction = "inbound"
EOF

See Configurable bridge for the full bridge rule syntax, and tedge-flows-examples for complete, maintained flows examples.

4. Create a service file and start the mapper

Create a systemd service file for the mapper (or the equivalent for your init system):

sudo tee /etc/systemd/system/tedge-mapper-thingsboard.service <<'EOF'
[Unit]
Description=thin-edge.io user-defined mapper thingsboard
After=syslog.target network.target mosquitto.service

[Service]
User=tedge
ExecStart=/usr/bin/tedge-mapper thingsboard
Restart=on-failure
RestartPreventExitStatus=255
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now tedge-mapper-thingsboard