Async Client

AsyncClient is the asyncio counterpart of Client. It has the same PLC operations, and every method that talks to the PLC is a coroutine:

import asyncio
from s7 import AsyncClient

async def main() -> None:
    async with AsyncClient() as client:
        await client.connect("192.168.1.10", 0, 1)
        data = await client.db_read(1, 0, 4)
        await client.db_write(1, 0, bytearray([1, 2, 3, 4]))

asyncio.run(main())

Leaving the async with block disconnects the client.

Concurrency

An internal asyncio.Lock serialises each request and its reply, so several coroutines can share one client:

async def read_all(client: AsyncClient) -> list[bytearray]:
    return await asyncio.gather(
        client.db_read(1, 0, 4),
        client.db_read(1, 10, 4),
        client.db_read(2, 0, 8),
    )

The requests still go to the PLC one after the other; gather only lets the rest of the application run while they wait. One client belongs to one event loop. Do not call it from other threads.

Differences from Client

  • There is no heartbeat thread and no heartbeat_interval argument. is_alive reports the connection state seen by the last operation.

  • read_multi_vars and write_multi_vars accept only the dict form, and read_multi_vars and read_tags read the items one after the other. There is no read optimizer and no max_parallel. See Multi-Variable Read and Write.

s7.AsyncClient

Asynchronous client for the classic S7 protocol.

Uses asyncio streams for non-blocking I/O with an asyncio.Lock() to serialize send/receive cycles, ensuring safe concurrent use via asyncio.gather().

s7.AsyncClient and snap7.AsyncClient expose this same implementation.

class snap7.async_client.AsyncClient(*, max_requests_per_second: float = 0, rate_limit_algorithm: Literal['fixed', 'token_bucket'] = 'fixed', rate_limit_behavior: Literal['block', 'raise'] = 'block', rate_limit_burst: int | None = None, on_operation: Callable[[str, float, bool], None] | None = None)[source]

Asynchronous client for classic S7 communication.

Uses asyncio streams for non-blocking I/O. An internal asyncio.Lock serializes each send+receive cycle so that concurrent coroutines (e.g. via asyncio.gather) never interleave on the same TCP socket.

For new projects, use s7.AsyncClient instead.

Examples

>>> from s7 import AsyncClient
>>> async with AsyncClient() as client:
...     await client.connect("192.168.1.10", 0, 1)
...     data = await client.db_read(1, 0, 4)
async __aenter__() → AsyncClient[source]

Async context manager entry.

async __aexit__(exc_type: Any, exc_val: Any, exc_tb: Any) → None[source]

Async context manager exit.

async ab_read(start: int, size: int) → bytearray[source]

Read from process output area (PA).

async ab_write(start: int, data: bytearray) → int[source]

Write to process output area (PA).

async cancel_force(area: Area, byte_offset: int, bit: int) → None[source]

Cancel a forced I/O bit by clearing it in the process image.

Async equivalent of snap7.client.Client.cancel_force().

async clear_session_password() → int[source]

Clear the session password, returning to the default protection level.

Sends an S7 USERDATA request (function group 5, subfunction 2).

Returns:

0 on success.

Raises:
async compress(timeout: int) → int[source]

Compress PLC memory.

async connect(address: str, rack: int, slot: int, tcp_port: int = 102) → AsyncClient[source]

Connect to S7 PLC.

Parameters:
  • address – PLC IP address

  • rack – Rack number

  • slot – Slot number

  • tcp_port – TCP port (default 102)

Returns:

Self for method chaining

async connect_routed(host: str, router_rack: int, router_slot: int, subnet: int, dest_rack: int, dest_slot: int, port: int = 102, timeout: float = 5.0) → AsyncClient[source]

Connect to an S7 PLC via a routing gateway on another subnet.

Warning

This method is experimental and may change in future versions.

Parameters:
  • host – IP address of the routing gateway PLC

  • router_rack – Rack number of the gateway PLC

  • router_slot – Slot number of the gateway PLC

  • subnet – Subnet ID of the target network (0x0000-0xFFFF)

  • dest_rack – Rack number of the destination PLC

  • dest_slot – Slot number of the destination PLC

  • port – TCP port (default 102)

  • timeout – Connection timeout in seconds

Returns:

Self for method chaining

async copy_ram_to_rom(timeout: int = 0) → int[source]

Copy RAM to ROM.

async ct_read(start: int, size: int) → bytearray[source]

Read from counter area (CT).

async ct_write(start: int, size: int, data: bytearray) → int[source]

Write to counter area (CT).

async db_fill(db_number: int, filler: int, size: int = 0) → int[source]

Fill a DB with a filler byte.

Parameters:
  • db_number – DB number to fill

  • filler – Byte value to fill with

  • size – DB size in bytes. If 0, determined via get_block_info().

Returns:

0 on success

async db_get(db_number: int, size: int = 0) → bytearray[source]

Get entire DB.

Parameters:
  • db_number – DB number to read

  • size – DB size in bytes. If 0, determined via get_block_info().

Returns:

Entire DB contents

async db_read(db_number: int, start: int, size: int) → bytearray[source]

Read data from DB.

Parameters:
  • db_number – DB number to read from

  • start – Start byte offset

  • size – Number of bytes to read

Returns:

Data read from DB

async db_read_array(db_number: int, start: int, count: int, fmt: str = '>f') → list[Any][source]

Read count consecutive values of struct format fmt from a DB.

async db_read_bool(db_number: int, byte_offset: int, bit_offset: int) → bool[source]

Read a single bit from a DB.

async db_read_byte(db_number: int, offset: int) → int[source]

Read a BYTE (8-bit unsigned) from a DB.

async db_read_dint(db_number: int, offset: int) → int[source]

Read a DINT (32-bit signed) from a DB.

async db_read_dword(db_number: int, offset: int) → int[source]

Read a DWORD (32-bit unsigned) from a DB.

async db_read_int(db_number: int, offset: int) → int[source]

Read an INT (16-bit signed) from a DB.

async db_read_lreal(db_number: int, offset: int) → float[source]

Read a LREAL (64-bit float) from a DB.

async db_read_real(db_number: int, offset: int) → float[source]

Read a REAL (32-bit float) from a DB.

async db_read_string(db_number: int, offset: int) → str[source]

Read an S7 STRING from a DB (header first to learn the max length).

async db_read_udint(db_number: int, offset: int) → int[source]

Read a UDINT (32-bit unsigned) from a DB.

async db_read_uint(db_number: int, offset: int) → int[source]

Read a UINT (16-bit unsigned) from a DB.

async db_read_word(db_number: int, offset: int) → int[source]

Read a WORD (16-bit unsigned) from a DB.

async db_read_wstring(db_number: int, offset: int) → str[source]

Read an S7 WSTRING from a DB (header first to learn the max length).

async db_write(db_number: int, start: int, data: bytearray) → int[source]

Write data to DB.

Parameters:
  • db_number – DB number to write to

  • start – Start byte offset

  • data – Data to write

Returns:

0 on success

async db_write_array(db_number: int, start: int, values: list[Any], fmt: str = '>f') → int[source]

Write values packed with struct format fmt to a DB. Returns 0 on success.

async db_write_bool(db_number: int, byte_offset: int, bit_offset: int, value: bool) → None[source]

Write a single bit to a DB, preserving the other bits in the byte.

async db_write_byte(db_number: int, offset: int, value: int) → None[source]

Write a BYTE (8-bit unsigned) to a DB.

async db_write_dint(db_number: int, offset: int, value: int) → None[source]

Write a DINT (32-bit signed) to a DB.

async db_write_dword(db_number: int, offset: int, value: int) → None[source]

Write a DWORD (32-bit unsigned) to a DB.

async db_write_int(db_number: int, offset: int, value: int) → None[source]

Write an INT (16-bit signed) to a DB.

async db_write_lreal(db_number: int, offset: int, value: float) → None[source]

Write a LREAL (64-bit float) to a DB.

async db_write_real(db_number: int, offset: int, value: float) → None[source]

Write a REAL (32-bit float) to a DB.

async db_write_string(db_number: int, offset: int, value: str, max_length: int = 254) → None[source]

Write an S7 STRING with the given maximum length to a DB.

async db_write_udint(db_number: int, offset: int, value: int) → None[source]

Write a UDINT (32-bit unsigned) to a DB.

async db_write_uint(db_number: int, offset: int, value: int) → None[source]

Write a UINT (16-bit unsigned) to a DB.

async db_write_word(db_number: int, offset: int, value: int) → None[source]

Write a WORD (16-bit unsigned) to a DB.

async db_write_wstring(db_number: int, offset: int, value: str, max_length: int = 254) → None[source]

Write an S7 WSTRING with the given maximum length (in characters) to a DB.

async delete(block_type: Block, block_num: int) → int[source]

Delete a block from PLC.

async disconnect() → int[source]

Disconnect from S7 PLC.

Returns:

0 on success

async download(data: bytearray, block_num: int = -1) → int[source]

Download block to PLC.

async eb_read(start: int, size: int) → bytearray[source]

Read from process input area (PE).

async eb_write(start: int, size: int, data: bytearray) → int[source]

Write to process input area (PE).

error_text(error_code: int) → str

Get error text for error code.

Parameters:

error_code – Error code to look up

Returns:

Human-readable error text

async force_bit(area: Area, byte_offset: int, bit: int, value: bool) → None[source]

Force a single I/O bit in the process image.

Async equivalent of snap7.client.Client.force_bit().

async full_upload(block_type: Block, block_num: int) → Tuple[bytearray, int][source]

Upload a block from PLC with header and footer info.

async get_block_info(block_type: Block, db_number: int) → TS7BlockInfo[source]

Get block information.

get_connected() → bool[source]

Check if client is connected.

async get_cp_info() → S7CpInfo[source]

Get communication processor info (SZL 0x0131).

async get_cpu_info() → S7CpuInfo[source]

Get CPU component identification (SZL 0x001C).

async get_cpu_state() → str[source]

Get the CPU operating state by reading SZL 0x0424.

Returns "S7CpuStatusRun", "S7CpuStatusStop" or "S7CpuStatusUnknown". Startup, HOLD and DEFECT are reported as "S7CpuStatusStop", as native Snap7 does.

Raises:
get_exec_time() → int

Get last operation execution time.

Returns:

Execution time in milliseconds

get_last_error() → int

Get last error code.

Returns:

Last error code

async get_order_code() → S7OrderCode[source]

Get module order code and firmware version (SZL 0x0011).

get_param(param: Parameter) → int

Get client parameter.

Parameters:

param – Parameter number

Returns:

Parameter value

get_pdu_length() → int

Get negotiated PDU length.

Returns:

PDU length in bytes

get_pg_block_info(data: bytearray) → TS7BlockInfo

Get block info from raw block data.

Parameters:

data – Raw block data

Returns:

Block information structure

async get_plc_datetime() → datetime[source]

Get PLC date/time.

async get_protection() → S7Protection[source]

Get protection settings (SZL 0x0232).

property is_alive: bool

Whether the client is connected.

Unlike the synchronous client there is no background heartbeat, so this reflects the connection state seen by the last operation.

async iso_exchange_buffer(data: bytearray) → bytearray[source]

Exchange raw ISO PDU.

async list_blocks() → BlocksList[source]

List blocks available in PLC.

async list_blocks_of_type(block_type: Block, max_count: int) → List[int][source]

List blocks of a specific type.

Supports multi-packet responses.

async mb_read(start: int, size: int) → bytearray[source]

Read from marker/flag area (MK).

async mb_write(start: int, size: int, data: bytearray) → int[source]

Write to marker/flag area (MK).

async plc_cold_start() → int[source]

Cold start PLC CPU.

async plc_hot_start() → int[source]

Hot start PLC CPU.

async plc_stop() → int[source]

Stop PLC CPU.

async read_area(area: Area, db_number: int, start: int, size: int) → bytearray[source]

Read data from memory area.

Automatically splits into multiple requests if size exceeds PDU capacity.

async read_diagnostic_buffer() → list[dict[str, Any]][source]

Read the PLC diagnostic buffer (experimental), newest first.

Each entry is a dict with keys event_id, timestamp and info.

async read_force_table() → list[ForceEntry][source]

Read the PLC force table via SZL 0x0025.

Async equivalent of snap7.client.Client.read_force_table().

async read_multi_vars(items: List[dict[str, Any]]) → Tuple[int, list[bytearray]][source]

Read multiple variables (sequentially, one read_area per item).

Parameters:

items – List of item dicts with keys: area, db_number, start, size. Any number of items is accepted.

Returns:

Tuple of (result_code, list_of_bytearrays)

async read_szl(ssl_id: int, index: int = 0) → S7SZL[source]

Read SZL (System Status List).

Supports multi-packet responses.

async read_szl_list() → bytes[source]

Read list of available SZL IDs.

async read_tag(tag: Tag | str, encoding: str = 'latin-1') → Any[source]

Read a typed value by Tag or PLC4X-style address string.

async read_tags(tags: Sequence[Tag | str], encoding: str = 'latin-1') → list[Any][source]

Read any number of tags, returning the values in input order.

set_connection_params(address: str, local_tsap: int, remote_tsap: int) → None

Set connection parameters.

Parameters:
  • address – PLC IP address

  • local_tsap – Local TSAP

  • remote_tsap – Remote TSAP

set_connection_type(connection_type: int) → None

Set connection type.

Parameters:

connection_type – Connection type (1=PG, 2=OP, 3=S7Basic)

set_param(param: Parameter, value: int) → int

Set client parameter.

Parameters:
  • param – Parameter number

  • value – Parameter value

Returns:

0 on success

async set_plc_datetime(dt: datetime) → int[source]

Set PLC date/time.

async set_plc_system_datetime() → int[source]

Set PLC time to system time.

async set_session_password(password: str) → int[source]

Set the session password to unlock a password-protected PLC.

Sends an S7 USERDATA request (function group 5, subfunction 1) with the encoded password.

Parameters:

password – Plaintext password (max 8 ASCII characters).

Returns:

0 on success.

Raises:
async tm_read(start: int, size: int) → bytearray[source]

Read from timer area (TM).

async tm_write(start: int, size: int, data: bytearray) → int[source]

Write to timer area (TM).

async upload(block_num: int) → bytearray[source]

Upload block from PLC (3-step: START_UPLOAD, UPLOAD, END_UPLOAD).

async write_area(area: Area, db_number: int, start: int, data: bytearray) → int[source]

Write data to memory area.

Automatically splits into multiple requests if data exceeds PDU capacity.

async write_multi_vars(items: List[dict[str, Any]]) → int[source]

Write multiple variables (sequentially, one write_area per item).

Parameters:

items – List of item dicts with keys: area, db_number, start, data

Returns:

0 on success

async write_tag(tag: Tag | str, value: Any, encoding: str = 'latin-1') → int[source]

Write a typed value by Tag or address string. Returns 0 on success.