Skip to main content

iobroker-python

Python SDK for ioBroker adapters. Speaks the Redis wire protocol of the states and objects databases directly — a Python process becomes a first-class adapter alongside any Node adapter, with no bridge in between.

Status: early draft. The wire layer is verified against a running installation (js-controller 7.2.3, jsonl databases). The API may still change.

Installation

pip install iobroker

An adapter in thirty lines

from iobroker import Adapter, State

class MyAdapter(Adapter):
    async def on_ready(self):
        await self.set_object_not_exists("temperature", {
            "type": "state",
            "common": {
                "name": "Temperature", "type": "number",
                "role": "value.temperature", "unit": "°C",
                "read": True, "write": False,
            },
        })
        await self.subscribe_states("*")
        await self.set_state("info.connection", True, ack=True)

    async def on_state_change(self, id: str, state: State | None):
        # ack=False means somebody wants something switched.
        if state and not state.ack:
            self.log.info(f"Command on {id}: {state.val}")

    async def on_message(self, msg):
        if msg.command == "ping":
            await self.reply(msg, {"pong": True})

MyAdapter("myadapter").run()

A runnable example lives in examples/minimal_adapter.py.

Connection settings

The adapter resolves them in this order:

  1. Environment variables IOB_STATES_HOST/PORT/DB/PASS/TYPE and IOB_OBJECTS_* — this is how py-controller will pass them in later.
  2. IOB_CONFIG holding the path to iobroker.json.
  3. The usual installation paths.

Instance number and log level come from --instance / --loglevel or from IOB_INSTANCE / IOB_LOGLEVEL — the same arguments js-controller already passes to Node adapters today.

How the built-in server differs from Redis

In a default setup you are not talking to real Redis but to the Redis protocol server built into js-controller (ports 9000 and 9001). It deviates in several places. Every point below was measured on the wire against a running installation rather than inferred from documentation — tools/probe.py verifies them for your own installation.

Deviation Consequence How the SDK handles it
Commands must be lowercase. The server dispatches without toLowerCase() (db-base/redisHandler.js) but registers its handlers in lowercase only. ioredis happens to send lowercase, redis-py sends uppercase. GET … → -Error GET NOT SUPPORTED, get … → 4. Without handling, the very first command fails. connection.py wraps redis-py's command packer. Synchronously via _command_packer, asynchronously via pack_command — redis-py takes a different route in each mode.
No HELLO. redis-py negotiates RESP3 on connect. The connection fails with HELLO NOT SUPPORTED. protocol=2, plus lib_name=None against CLIENT SETINFO.
No PING on the states database. Common connection checks fail. Connection test via get meta.states.protocolVersion — the version has to be checked anyway.
No SCAN on the states database. The objects database does support scan, sscan, sadd, eval. Keys have to be found with keys. DbConfig.is_builtin tells the two apart; against real Redis keys blocks and must be avoided.
Pub/sub delivers the channel without the io. prefix. Real Redis delivers it with. Blindly stripping the prefix mangles ids. The SDK tolerates both — exactly like the JS client.
Expired states report differently. No __keyevent@0__:expired; instead null arrives on the state channel itself. Against real Redis an extra subscription would be needed. null is reported to on_state_change as "state is gone".

One more property that is not a bug but matters: permission checks live in the JS client, not in the database server. Anything holding a Redis connection effectively has admin rights. That is equally true for Node adapters — the difference is that with Python, third-party code from PyPI shares the process.

Capability probe

python tools/probe.py

(from the repository, not shipped in the wheel)

Reports what both databases support in your installation, then performs a full round trip: create an object, write a state, receive the change. Cleans up again with --cleanup.

Lifecycle

alive, connected, uptime and memRss are written by the adapter itself through the states database — exactly like a Node adapter. Stopping goes through the sigKill state: when the controller sets it to -1, the adapter shuts down in an orderly fashion. That makes stopping work on Windows too, where there is no SIGTERM.

Development

python -m venv .venv && .venv/Scripts/activate   # Windows
pip install -e ".[dev]"
python examples/minimal_adapter.py --instance 0

The version number lives in src/iobroker/__init__.py only; pyproject.toml reads it from there through hatch, and the release workflow checks the git tag against it.

License

MIT

Release files for iobroker 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for iobroker 0.1.3
File Size Uploaded
iobroker-0.1.3.tar.gz 16.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for iobroker 0.1.3
File Interpreter ABI Platform
iobroker-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 31.3 kB

Release files / iobroker-0.1.3.tar.gz

Download URL iobroker-0.1.3.tar.gz
Size 16.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e01d4c3514b483d6429119ec0aea3ac84ffe04f092dddc7bc5f5eec0facec472
BLAKE2b-256 checksum
How to use checksums
d5519d8da709d46aed2a438c1f4132ad1c055140188a0e2ca5e0ce585f20dbec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release files / iobroker-0.1.3-py3-none-any.whl

Download URL iobroker-0.1.3-py3-none-any.whl
Size 14.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ef67a2f19eb0fc2d2098cba2974164f3897e37ceff188888bbe55cebe02f6d67
BLAKE2b-256 checksum
How to use checksums
a9dce883d13ac09d982f3dd21330af8b601b2458407e16159c727c4fe4fae16d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.

Transparency log

Release history Release notifications | RSS feed

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page