|
1 | 1 | """"Driver" for http://prologix.biz/gpib-usb-controller.html GPIB controller""" |
2 | 2 | import asyncio |
| 3 | +import logging |
| 4 | +import threading |
3 | 5 |
|
4 | 6 | import serial |
5 | 7 | import serial.threaded |
6 | | -from async_timeout import timeout |
7 | 8 |
|
8 | 9 | from ..rs232 import RS232SerialProtocol |
9 | 10 | from .base import GPIBTransport |
10 | 11 |
|
11 | 12 | SCAN_DEVICE_TIMEOUT = 0.5 |
12 | 13 | READ_TIMEOUT = 1.0 |
| 14 | +LOGGER = logging.getLogger(__name__) |
13 | 15 |
|
14 | 16 |
|
15 | 17 | class PrologixRS232SerialProtocol(RS232SerialProtocol): |
@@ -61,30 +63,35 @@ async def get_response(self): |
61 | 63 | async def send_and_read(self, send): |
62 | 64 | """Send a line, read the response. NOTE: This is for talking with the controller, device responses |
63 | 65 | need to use get_response as usual""" |
64 | | - with timeout(READ_TIMEOUT): |
| 66 | + |
| 67 | + async def _send_and_read(send) -> str: |
| 68 | + """Wrap the actual work""" |
65 | 69 | async with self.lock: |
66 | 70 | response = None |
67 | 71 |
|
68 | 72 | def set_response(message): |
69 | 73 | """Callback for setting the response""" |
70 | | - nonlocal response |
| 74 | + nonlocal response, self |
71 | 75 | response = message |
| 76 | + self.blevent.set() |
72 | 77 |
|
| 78 | + self.blevent.clear() |
73 | 79 | self.message_callback = set_response |
74 | 80 | self.serialhandler.protocol.write_line(send) |
75 | | - while response is None: |
76 | | - await asyncio.sleep(0) |
| 81 | + await asyncio.get_event_loop().run_in_executor(None, self.blevent.wait) |
77 | 82 | return response |
78 | 83 |
|
| 84 | + return await asyncio.wait_for(_send_and_read(send), timeout=READ_TIMEOUT) |
| 85 | + |
79 | 86 | async def set_address(self, address, secondary=None): |
80 | 87 | """Set the address we want to talk to""" |
81 | 88 | if secondary is None: |
82 | 89 | await self.send_command("++addr %d" % address) |
83 | 90 | else: |
84 | 91 | await self.send_command("++addr %d %d" % (address, secondary)) |
85 | | - # Wait for the address to actually be set |
| 92 | + |
86 | 93 | while True: |
87 | | - await asyncio.sleep(0) |
| 94 | + await asyncio.sleep(0.001) |
88 | 95 | resp = await self.query_address() |
89 | 96 | if resp == (address, secondary): |
90 | 97 | break |
@@ -144,13 +151,18 @@ async def scan_devices(self): |
144 | 151 | prev_read_tmo_ms = await self.send_and_read("++read_tmo_ms") |
145 | 152 | self.serialhandler.protocol.write_line("++read_tmo_ms %d" % int((SCAN_DEVICE_TIMEOUT / 2) * 1000)) |
146 | 153 | for addr in range(0, 31): # 0-30 inclusive |
147 | | - with timeout(SCAN_DEVICE_TIMEOUT): |
148 | | - try: |
149 | | - await self.set_address(addr) |
150 | | - await self.poll() |
151 | | - found_addresses.append(addr) |
152 | | - except (asyncio.TimeoutError, asyncio.CancelledError): |
153 | | - pass |
| 154 | + |
| 155 | + async def _scan_addr(addr) -> None: |
| 156 | + """Sacn single address""" |
| 157 | + nonlocal found_addresses |
| 158 | + await self.set_address(addr) |
| 159 | + await self.poll() |
| 160 | + found_addresses.append(addr) |
| 161 | + |
| 162 | + try: |
| 163 | + await asyncio.wait_for(_scan_addr(addr), timeout=SCAN_DEVICE_TIMEOUT) |
| 164 | + except (asyncio.TimeoutError, asyncio.CancelledError): |
| 165 | + pass |
154 | 166 | self.serialhandler.protocol.write_line("++read_tmo_ms " + prev_read_tmo_ms) |
155 | 167 | # Wait a moment for things to settle |
156 | 168 | await asyncio.sleep(float(prev_read_tmo_ms) / 1000) |
|
0 commit comments