Skip to content

http

tested on simulator

Tier Tier 1
Protocol HTTP/1.1 JSON APIs, HTTP/1.1 plain text APIs, OpenAPI 3 described APIs
Covers smart plugs and relays, networked sensors, lab and bench gadgets with REST APIs, DIY ESP32 and Pico W web servers
Hazard default medium
Conformance control
Tested with httpx.MockTransport with a simulated smart plug

Estimated reach. At least tens of thousands of models. Any device with a documented local HTTP API can be described in a device file without new code. Shelly alone documents a local HTTP API for its whole Gen1 and Gen2 range, Tasmota exposes an HTTP command endpoint on every flashed device, and most microcontroller web server sketches serve JSON over HTTP. The count is limited only by devices that need a protocol other than HTTP or a login flow the driver does not support.

The http driver connects to devices with a local HTTP API through httpx, and every request comes from the device file. Read maps name a request and where the value sits in the reply. Write maps and actions name a request with a body or query template.

Supports

  • Number, bool, string, enum and image reads from JSON through a JSON path, or from plain text.
  • Number, bool, string and enum writes as a JSON body, query string or path segment, read back through a state request or else the last value sent.
  • A bearer token or API key from an environment variable.

Setup

uv tool install --compile-bytecode "halkit[http] @ git+https://github.com/sohan-bhat/OpenHAL"
ParameterDefaultMeaning
base_urlrequiredhttp:// or https:// device URL. http: "http://192.168.1.50" is shorthand
timeout5 sHard deadline per request
headersnoneExtra headers. Names that look like credentials fail validation
token_envnoneVariable holding a token
auth_headerAuthorizationHeader carrying the token
auth_schemeBearerToken prefix. "" for a bare API key
verify_tlstrueCheck HTTPS certificates
health/GET path for connect and heartbeat. Any HTTP response counts as alive
identifynoneGET path for identify(). Scalar JSON fields become identity fields
openapinoneOpenAPI 3 JSON path for describe()
max_response_bytes1048576Larger responses raise DriverError

Channel maps

read:
  power: { unit: W, map: { path: /api/status, json: $.power.w } }
  mode: { type: enum, values: [auto, eco], map: { path: /api/mode } }   # text body
  snapshot: { type: image, map: { path: /snapshot.jpg } }
Read keyDefaultMeaning
pathrequiredRequest path, starting with /
methodGETGET or POST
querynoneQuery parameters
bodynoneJSON body for POST reads such as JSON-RPC
jsonnoneJSON path, an RFC 9535 subset with keys and list indexes such as $.relays[0].on
formatjson with a path, else textBody format
on, offcommon wordsTrue and false words for bools
scale, offset1, 0value = device value × scale + offset
write:
  relay:
    type: bool
    map: { path: /api/relay, body: { on: "{value}" }, state: { path: /api/status, json: relay.on } }
  level:
    unit: percent
    min: 0
    max: 100
    map: { path: /api/dimmer, method: PUT, body: { level: "{value}" }, scale: 0.392157 }
Write keyDefaultMeaning
pathrequiredRequest path. {value} in the path is URL-encoded
methodPOSTGET, POST, PUT, PATCH or DELETE
query, bodynoneTemplates. A string of exactly "{value}" keeps the JSON type
on, offthe booleanWhat to send for true and false
scale, offset1, 0device value = (value - offset) / scale, whole results sent as integers
statenoneRead map for read-back

Actions take path, method, query and body with {arg} per argument, and an optional json path for the result.

Example

openhal/drivers/http/examples/smart-plug.hal.yaml drives a Shelly Plus Plug S through the Gen2 RPC API, which switches the relay with GET /rpc/Switch.Set?id=0&on=true.

Describe from OpenAPI

With openapi: /openapi.json, describe() suggests reads for scalar GET reply fields one level deep, writes for scalar body fields whose numbers carry minimum and maximum, and actions for POST operations without a body. Units come from x-unit, else dimensionless. Writes and actions are marked suggested: true, so high risk entries stay read-only until a person confirms the limits, and lower risk entries run within the document's ranges. Paths with parameters, remote $ref pointers and YAML documents are skipped.

Errors

TimeoutError past timeout. DriverError with the request and what to check for connection failures, HTTP 400 and above, bad or missing JSON, non-numbers and enum values outside the list.

Limitations

  • No login flows such as session cookies, digest auth or OAuth.
  • No streaming or server-sent events. Poll with every.
  • No discovery.
  • Each read channel sends a separate request, even on a shared endpoint.

Hazard default and safe state

Medium. safe_state_support is file, applied through ordinary writes while the device responds.

Sources