HostLink Python API reference
This reference covers the recommended high-level helper API.
It intentionally excludes raw protocol methods and low-level client operations.
Imports
from hostlink import (
HostLinkConnectionOptions,
TimerCounterValue,
available_plc_profiles,
device_range_catalog_for_plc_profile,
open_and_connect,
parse_address,
try_parse_address,
format_address,
normalize_address,
read_typed,
read_timer_counter,
read_timer,
read_counter,
write_typed,
write_bit_in_word,
read_named,
poll,
read_words_single_request,
read_dwords_single_request,
read_words_chunked,
read_dwords_chunked,
read_expansion_unit_buffer,
write_expansion_unit_buffer,
)
from hostlink.errors import (
HostLinkBaseError,
HostLinkConnectionError,
HostLinkError,
HostLinkProtocolError,
)
Exceptions
HostLinkBaseError: base type for library exceptionsHostLinkError: PLC returned an error response such asE0,E1, orE6HostLinkProtocolError: invalid address, invalid dtype, malformed response, or local validation failureHostLinkConnectionError: connect, disconnect, socket, or timeout failure
Profile catalog
available_plc_profiles()
Return the exact canonical profile strings accepted by the embedded range catalog.
Example:
for profile in available_plc_profiles():
print(profile)
device_range_catalog_for_plc_profile(plc_profile)
Resolve one canonical profile string to the profile-specific range catalog.
Example:
catalog = device_range_catalog_for_plc_profile("keyence:kv-7000")
print(catalog.plc_profile)
Connection helper
await open_and_connect(options) or await open_and_connect(host, ...)
Create and connect a client for use with the helper functions.
Parameters:
options:HostLinkConnectionOptions(host, port=8501, transport="tcp", timeout=3.0, append_lf_on_send=False)host: PLC IP address or hostnameport: Host Link port, default8501transport:"tcp"or"udp"timeout: socket timeout in secondsappend_lf_on_send: appendLFafter the protocolCR
Returns:
- A connected async client object for use with the helpers below
Example:
options = HostLinkConnectionOptions(host="192.168.250.100", port=8501)
async with await open_and_connect(options) as client:
...
normalize_address(address, default_suffix="")
Normalize a user-supplied device string into canonical Host Link form.
Examples:
normalize_address("dm100") # DM100
normalize_address("dm100.a") # DM100.A
normalize_address("dm100", default_suffix="U") # DM100:U
parse_address, try_parse_address, and format_address
Use the public address helpers when UI or adapter code needs validated address metadata instead of private parser copies.
Examples:
parsed = parse_address("dm100.a")
parsed.text # DM100.A
parsed.base_device # DM100
parsed.dtype # BIT_IN_WORD
parsed.bit_index # 10
try_parse_address("DM1A") is None
format_address(parsed) # DM100.A
Typed helpers
Supported dtype codes:
| dtype | Meaning | Width |
|---|---|---|
U |
unsigned 16-bit | 1 word |
S |
signed 16-bit | 1 word |
D |
unsigned 32-bit | 2 words |
L |
signed 32-bit | 2 words |
F |
IEEE 754 float32 | 2 words |
await read_typed(client, device, dtype)
Read one typed value.
Parameters:
client: connected client fromopen_and_connectdevice: base word device such as"DM100"dtype: one ofU,S,D,L,F
Returns:
intforU,S,D,LfloatforF
Example:
value = await read_typed(client, "DM100", "F")
For T and C devices, read_typed(client, "T10", "D") returns the preset
value for compatibility with earlier helper behavior. Use
read_timer_counter when the contact/status and current value are also needed.
await read_timer_counter(client, device)
Read a timer or counter as the Host Link composite response:
status: contact state,0or1current: current timer/counter valuepreset: preset/set value
Parameters:
client: connected client fromopen_and_connectdevice: timer or counter base device such as"T10"or"C10"
Returns:
TimerCounterValue(status: int, current: int, preset: int)
Example:
tc = await read_timer_counter(client, "T10")
print(tc.status, tc.current, tc.preset)
read_timer(client, "T10") and read_counter(client, "C10") are stricter
aliases that validate the expected device family before reading.
await write_typed(client, device, dtype, value)
Write one typed value.
Parameters:
client: connected client fromopen_and_connectdevice: base word device such as"DM100"dtype: one ofU,S,D,L,Fvalue:intorfloat
Example:
await write_typed(client, "DM100", "D", 123456)
Contiguous block helpers
await read_words_single_request(client, device, count)
Read contiguous unsigned 16-bit words using exactly one PLC request.
Parameters:
device: start address such as"DM200"count: number of words
Returns:
list[int]
If the request does not fit in one PLC operation, this helper returns an error.
await read_dwords_single_request(client, device, count)
Read contiguous unsigned 32-bit values from adjacent words using exactly one PLC request.
Parameters:
device: start address such as"DM300"count: number of 32-bit values
Returns:
list[int]
Example:
words = await read_words_single_request(client, "DM200", 8)
dwords = await read_dwords_single_request(client, "DM300", 4)
await read_words_chunked(client, device, count, max_per_request=...)
Read a large contiguous word range using explicit multi-request chunking.
await read_dwords_chunked(client, device, count, max_dwords_per_request=...)
Read a large contiguous dword range using explicit multi-request chunking.
*_chunked is the opt-in surface for protocol-defined chunk boundaries.
It must not be confused with *_single_request.
Expansion unit buffer helpers
await read_expansion_unit_buffer(client, unit_no, address, count, data_format="")
Read buffer memory in an expansion unit through the high-level helper surface.
This sends one URD request; it does not split the operation.
Parameters:
unit_no: expansion unit number,0to48address: buffer memory address,0to59999count: number of values to readdata_format: optional suffix such asU,S,D,L, orH
Returns:
list[int | str]
await write_expansion_unit_buffer(client, unit_no, address, values, data_format="")
Write buffer memory in an expansion unit through one UWR request.
Example:
values = await read_expansion_unit_buffer(client, 1, 100, 2, data_format="U")
await write_expansion_unit_buffer(client, 1, 200, values, data_format="U")
Bit in word
await write_bit_in_word(client, device, bit_index, value)
Update a single bit inside a word device by read-modify-write.
Parameters:
device: word device such as"DM500"bit_index: integer bit position0to15(.0through.Fin address notation)value:TrueorFalse
Example:
await write_bit_in_word(client, "DM500", 3, True)
Mixed snapshots
await read_named(client, addresses)
Read mixed values in one call.
Supported address notation:
| Format | Meaning |
|---|---|
"DM100" |
unsigned 16-bit |
"DM100:S" |
signed 16-bit |
"DM100:D" |
unsigned 32-bit |
"DM100:L" |
signed 32-bit |
"DM100:F" |
float32 |
"DM100.3" |
bit 3 inside the word |
"DM100.A" |
bit 10 inside the word |
Parameters:
addresses:list[str]
Returns:
dict[str, int | float | bool]
Example:
snapshot = await read_named(client, ["DM100", "DM101:S", "DM102:F", "DM200.3"])
Polling
poll(client, addresses, interval)
Async generator that repeatedly yields snapshot dictionaries using the same
address notation as read_named.
Parameters:
addresses:list[str]interval: polling interval in seconds
Yields:
dict[str, int | float | bool]
Example:
async for snapshot in poll(client, ["DM100", "DM101:L", "DM200.3"], interval=1.0):
print(snapshot)
Notes
- User-facing docs intentionally stop at the helper layer.
- Hex/token-oriented reads and raw protocol commands are outside the recommended helper workflow.
- See
samples/README.mdfor runnable example scripts.