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.target5. 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