API

nessclient Core

class nessclient.ArmingMode(*values)
ARMED_AWAY = 'ARMED_AWAY'
ARMED_DAY = 'ARMED_DAY'
ARMED_HIGHEST = 'ARMED_HIGHEST'
ARMED_HOME = 'ARMED_HOME'
ARMED_NIGHT = 'ARMED_NIGHT'
ARMED_VACATION = 'ARMED_VACATION'
class nessclient.ArmingState(*values)
ARMED = 'ARMED'
ARMING = 'ARMING'
DISARMED = 'DISARMED'
ENTRY_DELAY = 'ENTRY_DELAY'
EXIT_DELAY = 'EXIT_DELAY'
TRIGGERED = 'TRIGGERED'
UNKNOWN = 'UNKNOWN'
class nessclient.Client(connection: Connection | None = None, host: str | None = None, port: int | None = None, serial_tty: str | None = None, update_interval: int = 60, infer_arming_state: bool = False, alarm: Alarm | None = None, decode_options: DecodeOptions | None = None)
Parameters:
  • update_interval – Frequency (in seconds) to trigger a full state refresh

  • infer_arming_state – Infer the DISARMED arming state only via system status events. This works around a bug with some panels (<v5.8) which emit update.status = [] when they are armed.

async arm_away(code: str | None = None) None
async arm_home(code: str | None = None) None
async aux(output_id: int, state: bool = True) None
async aux_output(output_id: int, state: bool = True) None
async close() None
async disarm(code: str) None
async get_panel_info() PanelInfo

Fetch and return panel information (model and version).

async keepalive() None
on_aux_output_change(f: Callable[[int, bool], None]) Callable[[int, bool], None]
on_event_received(f: Callable[[BaseEvent], None]) Callable[[BaseEvent], None]
on_state_change(f: Callable[[ArmingState, ArmingMode | None], None]) Callable[[ArmingState, ArmingMode | None], None]
on_zone_change(f: Callable[[int, bool], None]) Callable[[int, bool], None]
async panic(code: str) None
async send_command(command: str) None
async send_command_and_wait(command: str, timeout: float | None = 5.0) StatusUpdate

Send a command and await a matching USER_INTERFACE response.

  • Requires the command to be a status request (SXX). If not, raises a ValueError because those commands do not elicit a status response.

  • Resolves when a matching USER_INTERFACE response arrives, else times out.

stream_aux_output_changes() AsyncIterator[tuple[int, bool]]
stream_events() AsyncIterator[BaseEvent]
stream_state_changes() AsyncIterator[tuple[ArmingState, ArmingMode | None]]
stream_zone_changes() AsyncIterator[tuple[int, bool]]
async update() None

Force update of alarm status and zones

nessclient.event

class nessclient.event.ArmingUpdate(status: List[ArmingStatus], address: int | None, timestamp: datetime | None)
class ArmingStatus(*values)

Note: The ness provided documentation has the byte endianness incorrectly documented. For this reason, these enum values have reversed byte ordering compared to the ness provided documentation.

This only applies to some enums, and thus must be applied on a case-by-case basis

AREA_1_ARMED = 256
AREA_1_FULLY_ARMED = 1024
AREA_2_ARMED = 512
AREA_2_FULLY_ARMED = 2048
DAY_MODE_ARMED = 8192
DAY_ZONE_SELECT = 4
ENTRY_DELAY_1_ON = 16384
ENTRY_DELAY_2_ON = 32768
MANUAL_EXCLUDE_MODE = 1
MEMORY_MODE = 2
MONITOR_ARMED = 4096
classmethod decode(packet: Packet, options: DecodeOptions | None = None) ArmingUpdate
encode() Packet
class nessclient.event.AuxiliaryOutputsUpdate(outputs: List[OutputType], address: int | None, timestamp: datetime | None)
class OutputType(*values)
AUX_1 = 1
AUX_2 = 2
AUX_3 = 4
AUX_4 = 8
AUX_5 = 16
AUX_6 = 32
AUX_7 = 64
AUX_8 = 128
classmethod decode(packet: Packet, options: DecodeOptions | None = None) AuxiliaryOutputsUpdate
encode() Packet
class nessclient.event.BaseEvent(address: int | None, timestamp: datetime | None)
classmethod decode(packet: Packet, options: DecodeOptions | None = None) BaseEvent
encode() Packet
class nessclient.event.DecodeOptions(panel_version_update_model_mapper: Dict[int, Model] | None = None)

Options to be passed to all decoders to customise decoder behaviour.

panel_version_update_model_mapper: Dict[int, Model] | None = None
class nessclient.event.MiscellaneousAlarmsUpdate(included_alarms: List[AlarmType], address: int | None, timestamp: datetime | None)
class AlarmType(*values)

Note: The ness provided documentation has the byte endianness incorrectly documented. For this reason, these enum values have reversed byte ordering compared to the ness provided documentation.

This only applies to some enums, and thus must be applied on a case-by-case basis

CBUS_FAIL = 16
DURESS = 256
EXT_TAMPER = 8192
FIRE = 2048
INSTALL_END = 4096
KEYPAD_TAMPER = 32768
MAINS_FAIL = 8
MEDICAL = 1024
PANEL_BATTERY_LOW = 2
PANEL_BATTERY_LOW2 = 4
PANEL_TAMPER = 16384
PANIC = 512
PENDANT_PANIC = 1
classmethod decode(packet: Packet, options: DecodeOptions | None = None) MiscellaneousAlarmsUpdate
class nessclient.event.OutputsUpdate(outputs: List[OutputType], address: int | None, timestamp: datetime | None)
class OutputType(*values)

Note: The ness provided documentation has the byte endianness incorrectly documented. For this reason, these enum values have reversed byte ordering compared to the ness provided documentation.

This only applies to some enums, and thus must be applied on a case-by-case basis

AUX1 = 1
AUX2 = 2
AUX3 = 4
AUX4 = 8
KEYPAD_DISPLAY_ENABLE = 32768
MONITOR_OUT = 16
PANEL_BATT_FAIL = 64
POWER_FAIL = 32
RESET = 8192
SIREN_LOUD = 256
SIREN_SOFT = 512
SIREN_SOFT_FIRE = 2048
SIREN_SOFT_MONITOR = 1024
SONALART = 16384
STROBE = 4096
TAMPER_XPAND = 128
classmethod decode(packet: Packet, options: DecodeOptions | None = None) OutputsUpdate
class nessclient.event.PanelVersionUpdate(model: Model, major_version: int, minor_version: int, address: int | None, timestamp: datetime | None, _model_mapper: Dict[int, Model] | None = None)
class Model(*values)
D16X = 'D16X'
D16X_CEL_3G = 'D16X_CEL_3G'
D16X_CEL_4G = 'D16X_CEL_4G'
D32X = 'D32X'
D8X = 'D8X'
D8X_CEL_3G = 'D8X_CEL_3G'
D8X_CEL_4G = 'D8X_CEL_4G'
DPLUS8 = 'DPLUS8'
ModelLegacyMapper = {0: Model.D16X, 4: Model.D16X_CEL_3G, 20: Model.D16X_CEL_3G}

Panel model and modem combinations in documentation revision 16.

mmxy mm – model D16X - 00h D16X 3G - 04h D16X 4G - 05h D32X - 06h

1. 8200036017000004 0000 Prior to V7.8 2. 820003601700788c 0078 00 = D8x 78 = Version 7.8 3. 8200036017008084 0080 00 = D8x 80 = Version 8.0 4. 820003601714a848 . 14a8 14 = D16xcel 3G (04 = D8xCel 3G) a8 =Version 10.8 (a = 10) 5. 820003601700877d 00 = D8x (D16x is 10) 87 = Version 8.7 ie current product. 6. 820003601715b048 . 15b0 15 = D16xcel 4G (05 = D8xCel 4G) b0 =Version 11.0 (b = 11)

ModelRev16Mapper = {0: Model.D8X, 4: Model.D8X_CEL_3G, 5: Model.D8X_CEL_4G, 6: Model.D32X, 16: Model.D16X, 20: Model.D16X_CEL_3G, 21: Model.D16X_CEL_4G, 22: Model.DPLUS8}
classmethod decode(packet: Packet, options: DecodeOptions | None = None) PanelVersionUpdate
encode() Packet
property version: str
class nessclient.event.StatusUpdate(request_id: RequestID, address: int | None, timestamp: datetime | None)
class RequestID(*values)
ARMING = 20
AUXILIARY_OUTPUTS = 24
MISCELLANEOUS_ALARMS = 19
OUTPUTS = 21
PANEL_VERSION = 23
VIEW_STATE = 22
ZONE_17_32_AUTO_EXCLUDED = 39
ZONE_17_32_CBUS_UNSEALED = 34
ZONE_17_32_DETECTOR_LOW_BATTERY = 49
ZONE_17_32_DETECTOR_TAMPER = 50
ZONE_17_32_DOORS_OPEN = 48
ZONE_17_32_EXCLUDED = 38
ZONE_17_32_EXCLUDED_PLUS_AUTO_EXCLUDED = 51
ZONE_17_32_INPUT_UNSEALED = 32
ZONE_17_32_IN_ALARM = 37
ZONE_17_32_IN_DELAY = 35
ZONE_17_32_IN_DOUBLE_TRIGGER = 36
ZONE_17_32_RADIO_UNSEALED = 33
ZONE_17_32_SUPERVISION_FAIL = 41
ZONE_17_32_SUPERVISION_FAIL_PENDING = 40
ZONE_1_16_AUTO_EXCLUDED = 7
ZONE_1_16_CBUS_UNSEALED = 2
ZONE_1_16_DETECTOR_LOW_BATTERY = 17
ZONE_1_16_DETECTOR_TAMPER = 18
ZONE_1_16_DOORS_OPEN = 16
ZONE_1_16_EXCLUDED = 6
ZONE_1_16_EXCLUDED_PLUS_AUTO_EXCLUDED = 25
ZONE_1_16_INPUT_UNSEALED = 0
ZONE_1_16_IN_ALARM = 5
ZONE_1_16_IN_DELAY = 3
ZONE_1_16_IN_DOUBLE_TRIGGER = 4
ZONE_1_16_RADIO_UNSEALED = 1
ZONE_1_16_SUPERVISION_FAIL = 9
ZONE_1_16_SUPERVISION_FAIL_PENDING = 8
classmethod decode(packet: Packet, options: DecodeOptions | None = None) StatusUpdate
class nessclient.event.SystemStatusEvent(type: EventType, zone: int, area: int, address: int | None, timestamp: datetime | None)
class EventType(*values)
ALARM = 2
ALARM_RESTORE = 3
ARMED_AWAY = 36
ARMED_DAY = 38
ARMED_HIGHEST = 46
ARMED_HOME = 37
ARMED_NIGHT = 39
ARMED_VACATION = 40
ARMING_DELAYED = 48
AUTO_EXCLUDE = 6
AUTO_INCLUDE = 7
BATTERY_FAILURE = 18
BATTERY_NORMAL = 19
DISARMED = 47
ENTRY_DELAY_END = 33
ENTRY_DELAY_START = 32
EXIT_DELAY_END = 35
EXIT_DELAY_START = 34
MANUAL_EXCLUDE = 4
MANUAL_INCLUDE = 5
OUTPUT_OFF = 50
OUTPUT_ON = 49
POWER_FAILURE = 16
POWER_NORMAL = 17
REAL_TIME_CLOCK = 25
REPORT_FAILURE = 20
REPORT_NORMAL = 21
SEALED = 1
SUPERVISION_FAILURE = 22
SUPERVISION_NORMAL = 23
TAMPER_NORMAL = 9
TAMPER_UNSEALED = 8
UNSEALED = 0
classmethod decode(packet: Packet, options: DecodeOptions | None = None) SystemStatusEvent
encode() Packet
class nessclient.event.ViewStateUpdate(state: State, address: int | None, timestamp: datetime | None)
class State(*values)
BRIEF_DAY_CHIME = 57344
BRIEF_DAY_ZONE_SELECT = 45056
EXCLUDE_SELECT = 40960
HOME = 53248
INSTALLER_PROGRAM = 32768
MEMORY = 49152
NORMAL = 61440
USER_PROGRAM = 36864
classmethod decode(packet: Packet, options: DecodeOptions | None = None) ViewStateUpdate
class nessclient.event.ZoneUpdate_17_32(included_zones: List[Zone], request_id: RequestID, address: int | None, timestamp: datetime | None)
class Zone(*values)
ZONE_17 = 256
ZONE_18 = 512
ZONE_19 = 1024
ZONE_20 = 2048
ZONE_21 = 4096
ZONE_22 = 8192
ZONE_23 = 16384
ZONE_24 = 32768
ZONE_25 = 1
ZONE_26 = 2
ZONE_27 = 4
ZONE_28 = 8
ZONE_29 = 16
ZONE_30 = 32
ZONE_31 = 64
ZONE_32 = 128
classmethod decode(packet: Packet, options: DecodeOptions | None = None) ZoneUpdate_17_32
encode() Packet
class nessclient.event.ZoneUpdate_1_16(included_zones: List[Zone], request_id: RequestID, address: int | None, timestamp: datetime | None)
class Zone(*values)
ZONE_1 = 256
ZONE_10 = 2
ZONE_11 = 4
ZONE_12 = 8
ZONE_13 = 16
ZONE_14 = 32
ZONE_15 = 64
ZONE_16 = 128
ZONE_2 = 512
ZONE_3 = 1024
ZONE_4 = 2048
ZONE_5 = 4096
ZONE_6 = 8192
ZONE_7 = 16384
ZONE_8 = 32768
ZONE_9 = 1
classmethod decode(packet: Packet, options: DecodeOptions | None = None) ZoneUpdate_1_16
encode() Packet
nessclient.event.pack_unsigned_short_data_enum(items: List[T]) str
nessclient.event.unpack_unsigned_short_data_enum(packet: Packet, enum_type: Type[T]) List[T]

nessclient.connection

class nessclient.connection.AsyncIoConnection

A connection via IP232 with a Ness D8X/D16X server

async close() None
property connected: bool
async read() bytes | None
async write(data: bytes) None
class nessclient.connection.Connection

Represents a connection to a Ness D8X/D16X server

abstractmethod async close() None
abstractmethod async connect() bool
abstract property connected: bool
abstractmethod async read() bytes | None
abstractmethod async write(data: bytes) None
class nessclient.connection.IP232Connection(host: str, port: int)

A connection via IP232 with a Ness D8X/D16X server

async connect() bool
class nessclient.connection.Serial232Connection(tty_path: str)

A connection via Serial RS232 with a Ness D8X/D16X device or server

async connect() bool
property connected: bool