HTTP access plugin for ThingsPanel. Devices report telemetry through HTTP; ThingsPanel sends commands or control messages through MQTT; the plugin supports both direct HTTP downlink and device long polling.
| Config | Default | Purpose |
|---|---|---|
server.port |
19090 |
Device-facing API: uplink, poll, ack |
server.http_port |
19091 |
ThingsPanel callbacks and health checks |
| Device downlink port | 8080 |
Device-owned HTTP server for direct downlink, default paths /api/v1/control and /api/v1/command |
Device uplink, long polling, and ack requests use 19090. Platform callbacks use 19091.
go mod tidy
go run .\cmdDefault config: configs/config.yaml
server:
port: 19090
http_port: 19091
http_api_key: "aaaabbbb"
platform:
url: "http://127.0.0.1:9999"
mqtt_broker: "tcp://127.0.0.1:1883"
service_identifier: "HTTP"Devices identify themselves with device_number, for example D001. The platform's internal device_id is used by ThingsPanel after the plugin resolves the device configuration. Device payloads and long-poll URLs should use device_number, not device_id.
POST http://plugin-host:19090/api/v1/uplink
curl.exe -X POST http://127.0.0.1:19090/api/v1/uplink `
-H "Content-Type: application/json" `
-H "Access-Token: aaaabbbb" `
-d "{\"device_number\":\"D001\",\"temp\":25.5,\"hum\":60.2,\"status\":\"active\"}"Use this when the device or middleware has a public/reachable HTTP endpoint.
Set optional downlinkHost in the device voucher. The plugin posts directly to:
POST http://downlinkHost:8080/api/v1/control
POST http://downlinkHost:8080/api/v1/command
Command path defaults to /api/v1/command; control path defaults to /api/v1/control; port defaults to 8080.
Use this when the device is behind NAT or otherwise not reachable by the plugin.
If downlinkHost is empty, downlink messages are queued for the device to fetch. If direct mode is configured but the direct request fails, the plugin also falls back to the long-poll queue.
GET http://plugin-host:19090/api/v1/devices/{device_number}/poll
The poll request waits up to 30 seconds.
No pending message:
{
"commands": []
}Pending command:
{
"commands": [
{
"type": "command",
"device_number": "D001",
"message_id": "msg-001",
"method": "set",
"params": {}
}
]
}After executing a command from poll, the device reports the result:
POST http://plugin-host:19090/api/v1/devices/{device_number}/commands/{message_id}/ack
{
"ok": true,
"data": {}
}Authentication uses the device accessToken from the voucher. Send it as X-Api-Key, Access-Token, or Authorization: Bearer <token>.
FormType=CFG returns internal/form_json/form_config.json:
commandUrl: default/api/v1/command.controlUrl: default/api/v1/control.port: default8080.
FormType=VCR returns internal/form_json/form_voucher.json:
accessToken: device credential.downlinkHost: optional direct downlink host. Leave empty for long polling mode.
http://plugin-host:19091
Health check:
curl.exe http://127.0.0.1:19091/healthzLong polling test:
go run .\cmd\virtual_device -server http://127.0.0.1:19090/api/v1/uplink -device D001 -token aaaabbbbDirect downlink test:
go run .\cmd\virtual_device -server http://127.0.0.1:19090/api/v1/uplink -device D001 -token aaaabbbb -poll=false -listen :8080For direct mode, set the device voucher downlinkHost to 127.0.0.1 and keep the default port 8080.
- Device not found: confirm the ThingsPanel device exists and its device number matches the
device_numberin payloads and URLs. - SDK log shows empty
deviceIDwhile querying: the plugin queries bydevice_numberfor device uplink. The SDK log only printsdeviceID, so an empty value there does not mean the plugin useddevice_id. - Uplink 401: check
Access-TokenorX-Api-Keyagainst the device credential. - Direct downlink connection refused: the device is not listening on
downlinkHost:port/controlUrlorcommandUrl. - Long polling returns empty commands: check that the platform sent the downlink to the expected
device_numberand that the device credential leavesdownlinkHostempty or direct mode failed.
cmd/ entrypoints and virtual device
configs/ configuration
internal/bootstrap/ startup and platform client wiring
internal/protocol/ device-facing HTTP server
internal/platform/ ThingsPanel API/MQTT client
internal/downlink/ direct HTTP downlink and long-poll queues
internal/handler/ platform callback handlers
internal/form_json/ frontend form definitions