Skip to content

Commit f595d01

Browse files
committed
Add WLANHandler
1 parent 0605386 commit f595d01

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

pslab/connection/__init__.py

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from .connection import ConnectionHandler
66
from ._serial import SerialHandler
7+
from .wlan import WLANHandler
78

89

910
def detect() -> list[ConnectionHandler]:
@@ -36,6 +37,16 @@ def detect() -> list[ConnectionHandler]:
3637
finally:
3738
device.disconnect()
3839

40+
try:
41+
device = WLANHandler()
42+
device.connect()
43+
except Exception:
44+
pass # nosec
45+
else:
46+
pslab_devices.append(device)
47+
finally:
48+
device.disconnect()
49+
3950
return pslab_devices
4051

4152

pslab/connection/wlan.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""Wireless interface for communicating with PSLab devices equiped with ESP8266."""
2+
3+
import socket
4+
5+
from pslab.connection.connection import ConnectionHandler
6+
7+
8+
class WLANHandler(ConnectionHandler):
9+
"""Interface for controlling a PSLab over WLAN.
10+
11+
Paramaters
12+
----------
13+
host : str, default 192.168.4.1
14+
Network address of the PSLab.
15+
port : int, default 80
16+
timeout : float, default 1 s
17+
"""
18+
19+
def __init__(
20+
self,
21+
host: str = "192.168.4.1",
22+
port: int = 80,
23+
timeout: float = 1.0,
24+
) -> None:
25+
self._host = host
26+
self._port = port
27+
self._timeout = timeout
28+
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
29+
self._sock.settimeout(timeout)
30+
31+
@property
32+
def host(self) -> int:
33+
"""Network address of the PSLab."""
34+
return self._host
35+
36+
@property
37+
def port(self) -> int:
38+
"""TCP port number."""
39+
return self._port
40+
41+
@property
42+
def timeout(self) -> float:
43+
"""Timeout in seconds."""
44+
return self._timeout
45+
46+
@timeout.setter
47+
def timeout(self, value: float) -> None:
48+
self._sock.settimeout(value)
49+
50+
def connect(self) -> None:
51+
"""Connect to PSLab."""
52+
if self._sock.fileno() == -1:
53+
# Socket has been closed.
54+
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
55+
self._sock.settimeout(self.timeout)
56+
57+
self._sock.connect((self.host, self.port))
58+
59+
try:
60+
self.get_version()
61+
except Exception:
62+
self._sock.close()
63+
raise
64+
65+
def disconnect(self) -> None:
66+
"""Disconnect from PSLab."""
67+
self._sock.close()
68+
69+
def read(self, numbytes: int) -> bytes:
70+
"""Read data over WLAN.
71+
72+
Parameters
73+
----------
74+
numbytes : int
75+
Number of bytes to read.
76+
77+
Returns
78+
-------
79+
data : bytes
80+
"""
81+
received = b""
82+
buf_size = 4096
83+
remaining = numbytes
84+
85+
while remaining > 0:
86+
chunk = self._sock.recv(min(remaining, buf_size))
87+
received += chunk
88+
remaining -= len(chunk)
89+
90+
return received
91+
92+
def write(self, data: bytes) -> int:
93+
"""Write data over WLAN.
94+
95+
Parameters
96+
----------
97+
data : bytes
98+
99+
Returns
100+
-------
101+
numbytes : int
102+
Number of bytes written.
103+
"""
104+
return self._sock.sendall(data)
105+
106+
def __repr__(self) -> str: # noqa
107+
return (
108+
f"{self.__class__.__name__}"
109+
"["
110+
f"{self.host}:{self.port}, "
111+
f"timeout {self.timeout} s"
112+
"]"
113+
)

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ commands = coverage run --source pslab -m pytest
1212
[testenv:lint]
1313
deps = -rlint-requirements.txt
1414
setenv =
15-
INCLUDE_PSL_FILES = pslab/bus/ pslab/instrument/ pslab/serial_handler.py pslab/cli.py pslab/external/motor.py pslab/external/gas_sensor.py pslab/external/hcsr04.py
15+
INCLUDE_PSL_FILES = pslab/bus/ pslab/connection pslab/instrument/ pslab/serial_handler.py pslab/cli.py pslab/external/motor.py pslab/external/gas_sensor.py pslab/external/hcsr04.py
1616
commands =
1717
black --check {env:INCLUDE_PSL_FILES}
1818
flake8 --show-source {env:INCLUDE_PSL_FILES}

0 commit comments

Comments
 (0)