DCDevicecamp
Menu

Run a sensor gateway with ordinary Python.

Choose dependency-free HTTPS for periodic readings or Paho MQTT for a long-running gateway. The generated version contains the exact credential for your device.

1. Choose the transport

HTTP uses only the Python standard library and is the shortest path for periodic jobs. MQTT adds a persistent TLS connection, QoS 1 publication, a last will and automatic reconnect delays.

2. HTTP without an SDK

Create a device, choose Raspberry Pi / Python and leave HTTP selected. Replace read_sensor() with GPIO, I2C, serial or USB reads.

#!/usr/bin/env python3
"""Devicecamp Raspberry Pi / Linux HTTP starter."""

import json
import time
import urllib.error
import urllib.request

DEVICECAMP_URL = "https://api.devicecamp.app/v1/devices/DEVICE_ID/telemetry"
DEVICECAMP_SECRET = "DEVICE_SECRET"
PUBLISH_INTERVAL_SECONDS = 60


def read_sensor() -> dict[str, float]:
    # Replace these values with reads from your GPIO, I2C, serial, or USB sensor.
    return {"temperature": 22.4, "humidity": 51.0}


def publish(reading: dict[str, float]) -> None:
    request = urllib.request.Request(
        DEVICECAMP_URL,
        data=json.dumps(reading).encode("utf-8"),
        headers={
            "Authorization": f"Bearer {DEVICECAMP_SECRET}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    with urllib.request.urlopen(request, timeout=15) as response:
        if response.status not in (200, 202):
            raise RuntimeError(f"Devicecamp returned HTTP {response.status}")


while True:
    try:
        reading = read_sensor()
        publish(reading)
        print(f"Published metric keys: {', '.join(reading)}")
    except (OSError, RuntimeError, urllib.error.HTTPError) as error:
        # Do not print credentials or the full telemetry payload.
        print(f"Publish failed: {error}")
    time.sleep(PUBLISH_INTERVAL_SECONDS)

3. MQTT for a gateway

Select MQTT and create the one-time credential. Install Paho with python3 -m pip install "paho-mqtt>=2,<3" before running the downloaded script.

#!/usr/bin/env python3
"""Devicecamp Raspberry Pi / Linux MQTT/TLS starter.

Install the only dependency with:
    python3 -m pip install "paho-mqtt>=2,<3"
"""

import json
import ssl
import time

import paho.mqtt.client as mqtt

MQTT_HOST = "mqtt.devicecamp.app"
MQTT_PORT = 8883
MQTT_CLIENT_ID = "MQTT_CLIENT_ID"
MQTT_USERNAME = "MQTT_USERNAME"
MQTT_PASSWORD = "MQTT_PASSWORD"
TELEMETRY_TOPIC = "v1/devices/DEVICE_ID/telemetry"
STATUS_TOPIC = "v1/devices/DEVICE_ID/status"
PUBLISH_INTERVAL_SECONDS = 60


def read_sensor() -> dict[str, float]:
    # Replace these values with reads from your GPIO, I2C, serial, or USB sensor.
    return {"temperature": 22.4, "humidity": 51.0}


client = mqtt.Client(
    callback_api_version=mqtt.CallbackAPIVersion.VERSION2,
    client_id=MQTT_CLIENT_ID,
    protocol=mqtt.MQTTv311,
)
client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
client.tls_set(tls_version=ssl.PROTOCOL_TLS_CLIENT)
client.reconnect_delay_set(min_delay=1, max_delay=60)
client.will_set(STATUS_TOPIC, '{"status":"offline"}', qos=1, retain=True)
client.connect(MQTT_HOST, MQTT_PORT, keepalive=30)
client.loop_start()
client.publish(STATUS_TOPIC, '{"status":"online"}', qos=1, retain=True)

try:
    while True:
        reading = read_sensor()
        result = client.publish(
            TELEMETRY_TOPIC,
            json.dumps(reading, separators=(",", ":")),
            qos=1,
        )
        result.wait_for_publish(timeout=15)
        if result.is_published():
            print(f"Published metric keys: {', '.join(reading)}")
        time.sleep(PUBLISH_INTERVAL_SECONDS)
finally:
    client.publish(STATUS_TOPIC, '{"status":"offline"}', qos=1, retain=True)
    client.disconnect()
    client.loop_stop()

4. Keep it running

After the first manual run, use a dedicated system user and systemd service. Keep the generated file readable only by that user because it contains a live device credential.

[Unit]
Description=Devicecamp sensor gateway
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=devicecamp
Group=devicecamp
WorkingDirectory=/opt/devicecamp
Environment=PYTHONDONTWRITEBYTECODE=1
ExecStart=/usr/bin/python3 /opt/devicecamp/devicecamp_sensor.py
Restart=on-failure
RestartSec=10
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict

[Install]
WantedBy=multi-user.target

5. Install the service

Save the unit above as devicecamp-sensor.service beside the downloaded script. The commands create a non-login account, restrict the credential-bearing file and stream service logs.

sudo useradd --system --home /opt/devicecamp \
  --shell /usr/sbin/nologin devicecamp
sudo install -d -o devicecamp -g devicecamp -m 750 /opt/devicecamp
sudo install -o devicecamp -g devicecamp -m 600 \
  devicecamp_raspberry_pi_http.py /opt/devicecamp/devicecamp_sensor.py
sudo install -m 644 devicecamp-sensor.service \
  /etc/systemd/system/devicecamp-sensor.service
sudo systemctl daemon-reload
sudo systemctl enable --now devicecamp-sensor.service
sudo journalctl -u devicecamp-sensor.service -f
Run a sensor gateway with ordinary Python.Start free