Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
gazoodle committed Mar 16, 2022
2 parents 8503e38 + 4bd08bf commit 776bac8
Show file tree
Hide file tree
Showing 11 changed files with 33 additions and 20 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,13 +317,11 @@ https://www.gnu.org/licenses/gpl-3.0.html

# Todo

- Reminders
- Spa state (errors)
- Error handling (ongoing)
- Pythonize where possible
- APIs to support integration into automation systems (Ongoing)
- Warnings/Errors
- Reminders
- Diagnostics
- More unit tests
- Handle other device types such as Waterfall
Expand All @@ -335,7 +333,6 @@ https://www.gnu.org/licenses/gpl-3.0.html
- List property for errors in pack classes
- Tidy up support files. One class per file
- Full sweep for typing hints - Ongoing
- Add sensor for reminders
- Add sensor for errors
- Add switch for winterizing
- Add sensor for RF signal strength
Expand All @@ -352,6 +349,12 @@ https://www.gnu.org/licenses/gpl-3.0.html
is busy and the CUI won't exit until the timeout has been reached (this can
be reproduced by making the simulator stop responding to watercare requests)

## Done/Fixed in 0.4.2

- Fixed processor getting pegged at 100% but not using asyncio.sleep(0)
- Fixed simulator to respect names compatible with Windows
- Renamed some snapshots

## Done/Fixed in 0.4.1

- Updated README with simple async example
Expand Down
3 changes: 2 additions & 1 deletion sample/abstract_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import asyncio
from abc import ABC, abstractmethod
from curses import ERR, KEY_RESIZE, curs_set
from context import GeckoConstants # type: ignore

import _curses

Expand Down Expand Up @@ -32,7 +33,7 @@ async def run(self) -> None:
while not self.done:
char = self.stdscr.getch()
if char == ERR:
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)
elif char == KEY_RESIZE:
self.make_display()
else:
Expand Down
3 changes: 2 additions & 1 deletion sample/complete.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

from cui import CUI
from curses import wrapper
from context import GeckoConstants # type: ignore


_LOGGER = logging.getLogger(__name__)
Expand All @@ -40,7 +41,7 @@ def install_logging():
async def async_main(stdscr):
"""Async main manages the console UI"""
async with CUI(stdscr):
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)


def main(stdscr):
Expand Down
2 changes: 1 addition & 1 deletion src/geckolib/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
""" Single module version """

VERSION = "0.4.1"
VERSION = "0.4.2"
4 changes: 2 additions & 2 deletions src/geckolib/async_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async def _broadcast_loop(self, hello_handler) -> None:
),
)
await asyncio.sleep(1)
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

async def discover(self) -> None:
loop = asyncio.get_running_loop()
Expand Down Expand Up @@ -149,7 +149,7 @@ async def discover(self) -> None:
break
if self._has_found_spa:
break
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

_LOGGER.debug("Discovery complete, close transport")
self._task_man.cancel_key_tasks("LOC")
Expand Down
6 changes: 3 additions & 3 deletions src/geckolib/async_spa_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,12 @@ async def async_set_spa_info(
async def wait_for_descriptors(self) -> None:
"""Wait for descriptors to be available"""
while self._spa_descriptors is None:
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

async def wait_for_facade(self) -> bool:
"""Wait for facade to be available"""
while self._facade is None:
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)
if self.spa_state == GeckoSpaState.ERROR_SPA_NOT_FOUND:
return False
return True
Expand Down Expand Up @@ -467,7 +467,7 @@ async def _sequence_pump(self) -> None:
):
await self.async_connect(self._spa_identifier, self._spa_address)

await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

except asyncio.CancelledError:
_LOGGER.debug("Spaman sequence pump cancelled")
Expand Down
2 changes: 1 addition & 1 deletion src/geckolib/automation/async_facade.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ async def _facade_update(self) -> None:

async def wait_for_one_update(self):
while not self._ready:
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

def _scan_outputs(self) -> None:
"""Scan the spa outputs to decide what user options are available"""
Expand Down
1 change: 1 addition & 0 deletions src/geckolib/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class GeckoConstants:
SPA_PACK_REFRESH_FREQUENCY_IN_SECONDS = 30
CONNECTION_STEP_PAUSE_IN_SECONDS = 0 # Time between connection steps
MAX_RF_ERRORS_BEFORE_HALT = 50
ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD = 0.001

BROADCAST_ADDRESS = "<broadcast>"
MESSAGE_ENCODING = "latin1"
Expand Down
6 changes: 4 additions & 2 deletions src/geckolib/driver/protocol/unhandled.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import asyncio
import logging

from geckolib.const import GeckoConstants
from ..udp_socket import GeckoUdpProtocolHandler


Expand All @@ -26,7 +28,7 @@ async def consume(self, protocol):
# First time we see this, we mark the queue
protocol.queue.mark()
# Allow the rest of the tasks to operate
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)
# If we get here then no one processed the datagram
# so we can remove it and moan about it
if protocol.queue.is_marked:
Expand All @@ -35,4 +37,4 @@ async def consume(self, protocol):
_LOGGER.warning(
"No handler for %s from %s found, message ignored", data, sender
)
await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)
6 changes: 4 additions & 2 deletions src/geckolib/driver/udp_protocol_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import asyncio
from typing import TYPE_CHECKING

from geckolib.const import GeckoConstants

if TYPE_CHECKING:
from .async_udp_protocol import GeckoAsyncUdpProtocol

Expand Down Expand Up @@ -138,7 +140,7 @@ async def wait_for_response(self, protocol: GeckoAsyncUdpProtocol) -> bool:
_LOGGER.debug("Handler %s timed out", self)
return False

await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

async def consume(self, protocol: GeckoAsyncUdpProtocol) -> None:
"""Async coroutine to handle datagram."""
Expand All @@ -152,7 +154,7 @@ async def consume(self, protocol: GeckoAsyncUdpProtocol) -> None:
await self.async_handle(data, sender)
await self.async_handled(sender)

await asyncio.sleep(0)
await asyncio.sleep(GeckoConstants.ASYNCIO_SLEEP_TIMEOUT_FOR_YIELD)

if self.should_remove_handler:
_LOGGER.debug("%s will be removed, consume loop terminating", self)
Expand Down
11 changes: 7 additions & 4 deletions src/geckolib/utils/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ def do_load(self, args):
f" `parse` command to break it apart"
)

def do_name(self, args):
"""Set the name of the spa : name <spaname>."""
self._hello_handler = GeckoHelloProtocolHandler.response(
b"SPA01:02:03:04:05:06", args, on_handled=self._on_hello
)

def complete_load(self, text, line, start_idx, end_idx):
return self._complete_path(text)

Expand Down Expand Up @@ -226,10 +232,7 @@ def _should_ignore(self, handler, sender, respect_rferr=True):
def _install_standard_handlers(self):
"""All simulators needs to have some basic functionality such
as discovery, error handling et al"""
self._hello_handler = GeckoHelloProtocolHandler.response(
b"SPA01:02:03:04:05:06", "Udp Test Spa", on_handled=self._on_hello
)

self.do_name("Udp Test Spa")
self._socket.add_receive_handler(self._hello_handler)
self._socket.add_receive_handler(
GeckoPacketProtocolHandler(socket=self._socket)
Expand Down

0 comments on commit 776bac8

Please sign in to comment.