Skip to content

Devices and actuators

enocean.devices

Known devices and the profile (EEP) each one speaks, so received telegrams can be decoded automatically.

registry = DeviceRegistry.from_config(
    {
        '00:37:7E:06': {'eep': 'F6-02-02', 'name': 'Office wall switch', 'room': 'office'},
        '05:99:77:AF': {'eep': 'D2-01-12', 'name': 'Office light'},
    },
    defaults={RORG.RPS: 'F6-02-02'},
    ignored=['FF:E8:06:02'],
)
communicator = SerialCommunicator(port, devices=registry)  # received packets come decoded

Or decode packets yourself with registry.decode(packet).

Device dataclass

Device(
    id: str,
    eep: EEPId,
    name: str = '',
    metadata: Mapping[str, Any] = dict(),
)

A known device: its ID, the profile it speaks, and free-form information (room, owner...).

to_dict

to_dict() -> dict[str, Any]

JSON-serializable view of the device.

DeviceRegistry

DeviceRegistry(
    devices: Iterable[Device] = (),
    defaults: Mapping[int, EEPId | str] | None = None,
    ignored: Iterable[str | Iterable[int]] = (),
)

Known devices by ID, with the profiles to decode their telegrams with.

Parameters:

Name Type Description Default
devices Iterable[Device]

The known devices.

()
defaults Mapping[int, EEPId | str] | None

Profile to try for telegrams of unknown devices, by RORG (e.g. {RORG.RPS: 'F6-02-02'}).

None
ignored Iterable[str | Iterable[int]]

IDs of devices whose telegrams communicators using this registry drop.

()

from_config classmethod

from_config(
    config: Mapping[str, Mapping[str, Any]],
    defaults: Mapping[int, EEPId | str] | None = None,
    ignored: Iterable[str | Iterable[int]] = (),
) -> DeviceRegistry

Build a registry from a mapping, e.g. loaded from JSON, YAML or TOML.

Parameters:

Name Type Description Default
config Mapping[str, Mapping[str, Any]]

{id: {'eep': 'D2-01-12', 'name': ..., other keys}}: other keys go to the device's metadata; {'rorg': ..., 'func': ..., 'type': ...} is accepted instead of 'eep'.

required
defaults Mapping[int, EEPId | str] | None

See DeviceRegistry.

None
ignored Iterable[str | Iterable[int]]

See DeviceRegistry.

()

Returns:

Type Description
DeviceRegistry

The registry.

add

add(device: Device) -> None

Add a device, replacing any with the same ID.

remove

remove(id: str | Iterable[int]) -> None

Remove a device, if known.

get

get(id: str | Iterable[int]) -> Device | None

The device with this ID ('05:99:77:AF' or bytes), or None.

ignore

ignore(id: str | Iterable[int]) -> None

Ignore a device: communicators using this registry drop its telegrams.

is_ignored

is_ignored(id: str | Iterable[int]) -> bool

Whether the device is ignored.

eep_for

eep_for(packet: RadioPacket) -> EEPId | None

The profile to decode a telegram with: its device's, else the default for its RORG, if any.

decode

decode(packet: Packet) -> Device | None

Decode a radio telegram with its device's profile, or the default one for its RORG.

Fills packet.parsed and sets packet.device. Teach-in (UTE) and non-radio packets are left as they are.

Returns:

Type Description
Device | None

The device, or None if the sender is unknown.

device_id

device_id(value: str | Iterable[int]) -> str

Normalize a device ID: '05:99:77:af' or [0x05, 0x99, 0x77, 0xAF] -> '05:99:77:AF'.

enocean.actuators

Commands for actuators, sent through a communicator whose module is taught in to them.

light = SwitchActuator(communicator, '05:99:77:AF')     # D2-01 switch/dimmer
light.turn_on(channel=1)
light.query_status()                                    # the actuator answers with a status telegram (command 4)

cover = BlindActuator(communicator, '05:97:BA:73')      # D2-05 blinds/shutters
cover.go_to(position=50)
cover.stop()

The sender is the module's base ID unless another ID of its range is given. Replies arrive like any other telegram (decoded automatically when the actuators are in the communicator's DeviceRegistry).

Actuator

Actuator(
    communicator: Communicator,
    id: str | Iterable[int],
    eep: EEPId | str,
    sender: list[int] | None = None,
)

Base class: sends VLD commands of the actuator's profile to it.

Bind an actuator to the communicator that reaches it.

Parameters:

Name Type Description Default
communicator Communicator

The communicator (started) whose module is taught in to the actuator.

required
id str | Iterable[int]

The actuator's ID, '05:99:77:AF' or bytes.

required
eep EEPId | str

Its profile.

required
sender list[int] | None

The ID to send from: one of the module's range (base ID to base ID + 127) the actuator was taught in with. Defaults to the module's base ID.

None

destination property

destination: list[int]

The actuator's ID as bytes.

send_command

send_command(command: int, **fields: Any) -> RadioPacket

Build and send a command of the actuator's profile.

Parameters:

Name Type Description Default
command int

The command number (e.g. 1 for D2-01 Actuator Set Output).

required
**fields Any

The command's field values, e.g. IO=0, OV=100 (see EEP().describe()).

{}

Returns:

Type Description
RadioPacket

The packet sent.

Raises:

Type Description
RuntimeError

The module's base ID is unknown and no sender was given.

SwitchActuator

SwitchActuator(
    communicator: Communicator,
    id: str | Iterable[int],
    eep: EEPId | str = 'D2-01-12',
    sender: list[int] | None = None,
)

Bases: Actuator

D2-01 electronic switches and dimmers (e.g. NodOn SIN-2-2-01: D2-01-12). Channels are 0-based.

set_output

set_output(
    value: int, channel: int = ALL_CHANNELS
) -> RadioPacket

Command 1, Actuator Set Output.

Parameters:

Name Type Description Default
value int

0 (off) to 100 (on, or 100 % for dimmers).

required
channel int

The output channel (0-based), or ALL_CHANNELS.

ALL_CHANNELS

Returns:

Type Description
RadioPacket

The packet sent.

Raises:

Type Description
ValueError

value is out of 0..100.

turn_on

turn_on(channel: int = ALL_CHANNELS) -> RadioPacket

Switch a channel (or all) on: set_output(100).

turn_off

turn_off(channel: int = ALL_CHANNELS) -> RadioPacket

Switch a channel (or all) off: set_output(0).

query_status

query_status(channel: int = ALL_CHANNELS) -> RadioPacket

Command 3, Actuator Status Query: the actuator answers with Actuator Status Response (command 4).

BlindActuator

BlindActuator(
    communicator: Communicator,
    id: str | Iterable[int],
    eep: EEPId | str = 'D2-05-00',
    sender: list[int] | None = None,
)

Bases: Actuator

D2-05 blinds control (e.g. NodOn SIN-2-RS-01: D2-05-00). Positions and angles in % (0: open/up).

go_to

go_to(
    position: int | None = None,
    angle: int | None = None,
    channel: int = 0,
) -> RadioPacket

Command 1, Go to Position and Angle.

Parameters:

Name Type Description Default
position int | None

Vertical position in % (0: fully open/up), None to leave it unchanged.

None
angle int | None

Slat rotation angle in %, None to leave it unchanged.

None
channel int

The channel.

0

Returns:

Type Description
RadioPacket

The packet sent.

Raises:

Type Description
ValueError

position or angle is out of 0..100.

stop

stop(channel: int = 0) -> RadioPacket

Command 2, Stop.

query_position

query_position(channel: int = 0) -> RadioPacket

Command 3, Query Position and Angle: the actuator answers with Reply Position and Angle (command 4).