A minimal device service built with the Python Device Service SDK. It simulates a device
(fake) with two commands:
Get(read): returns a random integer (random-numberresource, 0-100, changes every call)Set(write): toggles a simulated switch (switchresource)
This example demonstrates the core SDK capabilities: REST API, device/profile provisioning, read/write commands, event publishing to the EdgeX MessageBus, and Core Metadata registration.
-
Docker and Docker Compose
-
An EdgeX stack already running on the
edgex_edgex-networknetwork with:edgex-core-metadata(port 59881)edgex-core-data(port 59880)edgex-core-command(port 59882)edgex-mqtt-broker(port 1883)edgex-core-keeper(port 59890)
If you don't have one, get it from edgex-compose and start it first.
From the examples/simple directory:
make docker-build # builds device-simple:latest from the repository root
make docker-run # starts the service via docker composeOr the equivalent explicit commands, run from the repository root:
docker build -f examples/simple/Dockerfile --build-context root=. -t device-simple:latest ./examples/simple
cd examples/simple
docker compose up -dStop the service with make docker-stop.
Note (China mainland users): the Dockerfile does not pin a pip mirror by default. If pulls are slow, uncomment/set the
pip config set global.index-urlline in theDockerfileto your preferred mirror before building.
Check that the service is healthy (takes ~30s):
docker inspect --format '{{.State.Health.Status}}' edgex-device-simple
# healthypip install -e . # from the repository root
cd examples/simple
python -m device_service # requires a local MQTT broker, see mosquitto.confcurl http://localhost:59990/api/v3/ping{"apiVersion": "v3", "serviceName": "device-simple", "timestamp": "..."}curl http://localhost:59990/api/v3/device/name/fake/Get{
"apiVersion": "v3",
"statusCode": 200,
"event": {
"deviceName": "fake",
"profileName": "fake-profile",
"sourceName": "random-number",
"readings": [
{
"resourceName": "random-number",
"valueType": "Int32",
"value": "92"
}
]
}
}Call it a few times — value changes on every read (it is a random 0-100 integer).
curl -X PUT http://localhost:59990/api/v3/device/name/fake/Set \
-H "Content-Type: application/json" \
-d '{"switch": "true"}'{"apiVersion": "v3", "statusCode": 200}curl http://localhost:59990/api/v3/config | jq .config.Service
curl http://localhost:59990/api/v3/config | jq .config.Registry # Type: core-keepercurl http://localhost:59990/api/v3/versionThe service registers itself with Core Metadata at startup. Query via core-command:
curl http://localhost:59882/api/v3/device/name/fake | jq .And confirm events arrive in core-data (after a read with ds-pushevent):
curl -s "http://localhost:59990/api/v3/device/name/fake/Get?ds-pushevent=true" >/dev/null
sleep 1
curl "http://localhost:59880/api/v3/event/device/name/fake?limit=1" | jq .events[0].readingsdocker exec -it edgex-mqtt-broker mosquitto_sub -t 'edgex/events/device/#' -vThen trigger a read from another terminal — you should see JSON envelopes being published.
Read commands support the standard device-service query params:
| Param | Effect |
|---|---|
ds-pushevent=true |
Push the resulting Event to the MessageBus / core-data |
ds-returnevent=false |
Do not return the Event in the HTTP response |
ds-regexcommand=true |
Treat the command name as a regular expression |
Example:
curl "http://localhost:59990/api/v3/device/name/fake/Get?ds-pushevent=true&ds-returnevent=false"| Symptom | Fix |
|---|---|
Container unhealthy |
docker logs edgex-device-simple; usually the EdgeX stack or MQTT broker is unreachable |
device "fake" not found |
The fake device comes from res/devices/*.yaml; check startup logs for provisioning errors |
Build fails at pip install /repo |
Build from the repository root with --build-context root=. as shown above |
| Port conflict on 59990 | Stop the conflicting service or change SERVICE_PORT + the ports: mapping in docker-compose.yaml |
examples/simple/
├── device_service.py # SimpleDriver + Configuration + bootstrap entry
├── Dockerfile
├── docker-compose.yaml
├── mosquitto.conf # local MQTT broker config (non-Docker runs)
└── res/
├── configuration.yaml # SDK configuration (Service/MessageBus/Device/...)
├── profiles/ # device profile: fake-profile (random-number, switch)
├── devices/ # static device: fake
└── provisionwatchers/ # (optional) auto-registration rules