Communication protocol
The pypalmsens.CommProtocol class provides an interface to exchange messages with your device using the communication protocol. You can use the Communication Protocol to directly query/manipulate the state of your device, e.g. setting registers, file operations, and sending scripts. It supports various connection types, such as serial ports, USB, and Bluetooth.
The Communication Protocol is supported by all MethodSCRIPT-capable instruments:
Connecting to the device
To communicate with a PalmSens instrument you need an active connection. CommProtocol supports the context manager protocol, so you can pass a pypalmsens.Instrument instance. In this case, it opens and manages the connection:
>>> import pypalmsens as ps
>>> instrument, *_ = ps.discover()
>>> with ps.CommProtocol(instrument) as comm:
... print(comm.query('t'))
es4_lr1500#Mar 12 2026 14:28:01
R*
Alternatively, you can manage the connection yourself. The repr shows the state of the connection:
>>> comm = ps.CommProtocol(instrument)
>>> comm.open()
>>> comm
CommProtocol('EmStat4 LR [1]', connected=True)
>>> comm.close()
>>> comm
CommProtocol('EmStat4 LR [1]', connected=False)
Sending commands
The primary method for interactive communication is .query. It sends a command to the device, waits for completion, reads the full response, strips the prefix, and returns it as a string:
>>> comm.query('i') # Serial number
'ES4LR20B0008'
>>> comm.query('v') # MethodSCRIPT version
'01.09.00'
>>> comm.query('t') # Firmware version
'es4_lr1500#Mar 12 2026 14:28:01\nR*'
For commands that run for a long time (e.g., scripts), this method will block until the script completes or times out. For more commands, see the Communication Protocol documentation for your device.
Running MethodSCRIPTs
.run_methodscript is a helper method that loads and executes a MethodSCRIPT on the instrument:
>>> script = 'send_string "Hello world!"'
>>> comm.run_methodscript(script)
'THello world!\n'
This returns the string prepended by a T, which is the text packet identifier.
Capabilities
You can query which features are available on the connected instrument through capability detection:
.get_methodscript_capabilities: Returns a set of MethodSCRIPT command names that are licensed and supported by the device's hardware and firmware..get_communication_capabilities: Returns a set of communication protocol commands supported by the device's firmware.
>>> comm.get_methodscript_capabilities()
('abort', 'add_var', ..., 'var', 'wait')
>>> comm.get_communication_capabilities()
('CC', 'CM', ..., 't', 'v')
These are helper functions that parse the hexadecimal bit fields returned by the underlying commands CC and CM:
>>> comm.query('CC')
'000000000000000000000000000000000000002F0000003FFFFF98FF00000002'
>>> comm.query('CM')
'000000000000000000000000000003FFFFBFE8FFFFFFFFFFFFFFFFFFFFBFFFFE'
Configuration
The interface exposes configuration attributes for controlling timeouts and read delays:
- CommProtocol.timeout: Maximum time (in seconds) to wait for a response before timing out. Defaults to 10s.
- CommProtocol.delay: Pause (in seconds) between writing a command and reading subsequent responses. Adjust based on your specific hardware and connection type.
>>> comm.timeout = 30.0 #(1)!
>>> comm.delay = 0.5 #(2)!
- extend timeout for slow measurements
- increase delay for slower connections
Error handling
Communication errors raise [MethodScriptRuntimeError][pypalmsens.MethodScriptRuntimeError] (a subclass of ConnectionError) when the device returns an error response. The error includes an error code that can be looked up in the MethodSCRIPT manual:
>>> comm.run_methodscript('invalid_command\n')
Traceback (most recent call last):
...
pypalmsens._instruments.comm_protocol.CommProtocolError: [4001] The script command is unknown (Line 1, Col 16)
Aborting measurements
Use .abort to abort any currently running script or measurement and wait for completion. Note that this could take a while, depending on the measurement that was running:
>>> comm.abort()
Low-level communication
For more control over individual reads and writes, use the following methods:
.write: Write a command or data to the instrument. To submit a command for execution, append a newline character ('\n') to the end of the string..read: Read the next available chunk from the buffer without blocking. Returns an empty string ('') if no data are available..lines: Generator that yields response chunks as they arrive, stopping when a timeout occurs between responses..wait_until: Wait until a response line starting with a given prefix arrives (useful for waiting on command echoes)..read_until: Read lines from the device until a termination sequence is found.
Response history
The interface maintains a history of recent responses for debugging and inspection via CommProtocol.history. By default, it stores the last 100 responses:
>>> comm.history
deque(['iES4LR20B0008\n', 'v01.09.00\n', ...], maxlen=100)
Async Comm protocol
For async workflows, use pypalmsens.DeviceFileSystemAsync:
>>> import asyncio
>>> import pypalmsens as ps
>>> async def main():
... instrument, *_ = await ps.discover_async()
... comm = ps.CommProtocolAsync(instrument)
... await comm.open()
...
... print(repr(await comm.query('i')))
... print(repr(await comm.query('v')))
... print(repr(await comm.query('t')))
...
... script = 'send_string "Hello world!"'
... output = await comm.run_methodscript(script)
... print(repr(output))
>>> asyncio.run(main())
'ES4LR20B0008'
'01.09.00'
'es4_lr1500#Mar 12 2026 14:28:01\nR*'
'THello world!\n'