Skip to content

Commit 7e6c499

Browse files
committed
feat: add pin control and reading functionalities
1 parent f85c8e5 commit 7e6c499

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

src/wokwi_client/client.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
from .__version__ import get_version
99
from .constants import DEFAULT_WS_URL
10+
from .control import set_control
1011
from .event_queue import EventQueue
1112
from .file_ops import upload, upload_file
13+
from .pins import pin_listen, pin_read
1214
from .protocol_types import EventMessage, ResponseMessage
1315
from .serial import monitor_lines
1416
from .simulation import pause, restart, resume, start
@@ -181,3 +183,35 @@ async def serial_monitor_cat(self) -> None:
181183

182184
def _on_pause(self, event: EventMessage) -> None:
183185
self.last_pause_nanos = int(event["nanos"])
186+
187+
async def read_pin(self, part: str, pin: str) -> ResponseMessage:
188+
"""Read the current state of a pin.
189+
190+
Args:
191+
part: The part id (e.g. "uno").
192+
pin: The pin name (e.g. "A2").
193+
"""
194+
return await pin_read(self._transport, part=part, pin=pin)
195+
196+
async def listen_pin(self, part: str, pin: str, listen: bool = True) -> ResponseMessage:
197+
"""Start or stop listening for changes on a pin.
198+
199+
When enabled, "pin:change" events will be delivered via the transport's
200+
event mechanism.
201+
202+
Args:
203+
part: The part id.
204+
pin: The pin name.
205+
listen: True to start listening, False to stop.
206+
"""
207+
return await pin_listen(self._transport, part=part, pin=pin, listen=listen)
208+
209+
async def set_control(self, part: str, control: str, value: int | bool | float) -> ResponseMessage:
210+
"""Set a control value (e.g. simulate button press).
211+
212+
Args:
213+
part: Part id (e.g. "btn1").
214+
control: Control name (e.g. "pressed").
215+
value: Control value to set (float).
216+
"""
217+
return await set_control(self._transport, part=part, control=control, value=value)

src/wokwi_client/control.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Control command helpers for virtual parts.
2+
3+
Provides `set_control` to manipulate part controls (e.g. press a button).
4+
5+
Assumptions:
6+
* Underlying websocket command name: "control:set".
7+
* Parameter names expected by server: part, control, value.
8+
"""
9+
10+
# SPDX-FileCopyrightText: 2025-present CodeMagic LTD
11+
#
12+
# SPDX-License-Identifier: MIT
13+
14+
from .protocol_types import ResponseMessage
15+
from .transport import Transport
16+
17+
18+
async def set_control(
19+
transport: Transport, *, part: str, control: str, value: int | bool | float
20+
) -> ResponseMessage:
21+
"""Set a control value on a part (e.g. simulate button press/release).
22+
23+
Args:
24+
transport: Active Transport.
25+
part: Part identifier (e.g. "btn1").
26+
control: Control name (e.g. "pressed").
27+
value: Control value to set (float).
28+
"""
29+
return await transport.request(
30+
"control:set", {"part": part, "control": control, "value": float(value)}
31+
)

src/wokwi_client/pins.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Pin command helpers for the Wokwi Simulation API.
2+
3+
This module exposes helper coroutines for issuing pin-related commands:
4+
5+
* pin:read - Read the current state of a pin.
6+
* pin:listen - Start/stop listening for changes on a pin (emits pin:change
7+
events).
8+
"""
9+
10+
# SPDX-FileCopyrightText: 2025-present CodeMagic LTD
11+
#
12+
# SPDX-License-Identifier: MIT
13+
14+
from .protocol_types import ResponseMessage
15+
from .transport import Transport
16+
17+
18+
async def pin_read(
19+
transport: Transport, *, part: str, pin: str
20+
) -> ResponseMessage:
21+
"""Read the state of a pin.
22+
23+
Args:
24+
transport: The active Transport instance.
25+
part: Part identifier (e.g. "uno").
26+
pin: Pin name (e.g. "A2", "13").
27+
"""
28+
29+
return await transport.request("pin:read", {"part": part, "pin": pin})
30+
31+
32+
async def pin_listen(
33+
transport: Transport, *, part: str, pin: str, listen: bool = True
34+
) -> ResponseMessage:
35+
"""Enable or disable listening for changes on a pin.
36+
37+
When listening is enabled, "pin:change" events will be emitted with the
38+
pin state.
39+
40+
Args:
41+
transport: The active Transport instance.
42+
part: Part identifier.
43+
pin: Pin name.
44+
listen: True to start listening, False to stop.
45+
"""
46+
47+
return await transport.request(
48+
"pin:listen", {"part": part, "pin": pin, "listen": listen}
49+
)

0 commit comments

Comments
 (0)