From e53512b273c1a693f7980f0bf9965f856f4582e8 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Tue, 10 Jan 2023 22:56:27 -0800 Subject: [PATCH] Add SetDate/Time support --- examples/rainbird_tool.py | 52 ++++++++++++++++++++------- pyrainbird/async_client.py | 20 +++++++++++ pyrainbird/resources/sipcommands.yaml | 28 +++++++++++++-- tests/test_async_client.py | 20 +++++++++++ tests/testdata/date_time.yaml | 18 +++++++++- 5 files changed, 122 insertions(+), 16 deletions(-) diff --git a/examples/rainbird_tool.py b/examples/rainbird_tool.py index c2c0226..a57793d 100755 --- a/examples/rainbird_tool.py +++ b/examples/rainbird_tool.py @@ -12,26 +12,33 @@ ``` """ +import argparse import asyncio -import aiohttp -import sys +import datetime import inspect -import argparse -import logging - -from pyrainbird import async_client import logging import os +from typing import Any +import aiohttp + +from pyrainbird import async_client _LOGGER = logging.getLogger(__name__) def parse_args(): parser = argparse.ArgumentParser() - parser.add_argument('--log-level', default='warning', choices=['debug', 'info', 'warning', 'error', 'critical'], help='The log level') - - subcommand_parsers = parser.add_subparsers(title='Commands', dest='command', required=True) + parser.add_argument( + "--log-level", + default="warning", + choices=["debug", "info", "warning", "error", "critical"], + help="The log level", + ) + + subcommand_parsers = parser.add_subparsers( + title="Commands", dest="command", required=True + ) for method_name in dir(async_client.AsyncRainbirdController): if method_name.startswith("_"): continue @@ -47,7 +54,9 @@ def parse_args(): continue # Create a parser for the method - method_parser = subcommand_parsers.add_parser(method_name, help=f'Call the {method_name} method') + method_parser = subcommand_parsers.add_parser( + method_name, help=f"Call the {method_name} method" + ) method_parser.set_defaults(func=method) # Get the arguments of the method @@ -60,9 +69,21 @@ def parse_args(): return parser.parse_args() +def parse_value(value: Any) -> Any: + """Parse the command line arg into a value.""" + try: + return datetime.date.fromisoformat(value) + except ValueError: + pass + try: + return datetime.time.fromisoformat(value) + except ValueError: + pass + return int(value, 16) + + async def main(): args = parse_args() - print(getattr(logging, args.log_level.upper())) logging.basicConfig(level=getattr(logging, args.log_level.upper())) host = os.environ["RAINBIRD_SERVER"] @@ -70,10 +91,15 @@ async def main(): async with aiohttp.ClientSession() as session: client = async_client.CreateController(session, host, password) - method_args = {k: v for k, v in vars(args).items() if k != 'func' and k != 'command' and k != 'log_level'} + method_args = { + k: parse_value(v) + for k, v in vars(args).items() + if k != "func" and k != "command" and k != "log_level" + } result = await args.func(client, **method_args) print(result) + # Run the main function if this script is run -if __name__ == '__main__': +if __name__ == "__main__": asyncio.run(main()) diff --git a/pyrainbird/async_client.py b/pyrainbird/async_client.py index 770f291..9339903 100644 --- a/pyrainbird/async_client.py +++ b/pyrainbird/async_client.py @@ -153,6 +153,16 @@ async def get_current_time(self) -> datetime.time: "CurrentTimeRequest", ) + async def set_current_time(self, value: datetime.time) -> None: + """Set the device current time.""" + await self._process_command( + lambda resp: True, + "SetCurrentTimeRequest", + value.hour, + value.minute, + value.second, + ) + async def get_current_date(self) -> datetime.date: """Get the device current date.""" return await self._process_command( @@ -160,6 +170,16 @@ async def get_current_date(self) -> datetime.date: "CurrentDateRequest", ) + async def set_current_date(self, value: datetime.date) -> None: + """Set the device current date.""" + await self._process_command( + lambda resp: True, + "SetCurrentDateRequest", + value.day, + value.month, + value.year, + ) + async def get_wifi_params(self) -> WifiParams: """Return wifi parameters and other settings.""" result = await self._local_client.request("getWifiParams") diff --git a/pyrainbird/resources/sipcommands.yaml b/pyrainbird/resources/sipcommands.yaml index dad159a..b72c8e1 100644 --- a/pyrainbird/resources/sipcommands.yaml +++ b/pyrainbird/resources/sipcommands.yaml @@ -29,12 +29,36 @@ ControllerCommands: command: '10' response: '90' length: 1 - # SetTimeRequest: 11 + SetCurrentTimeRequest: + command: '11' + response: '01' + length: 4 + hour: + position: 2 + length: 2 + minute: + position: 4 + length: 2 + second: + position: 6 + length: 2 CurrentDateRequest: command: '12' response: '92' length: 1 - # SetDateRequest: 13 + SetCurrentDateRequest: + command: '13' + response: '01' + length: 4 + day: + position: 2 + length: 2 + month: + position: 4 + length: 1 + year: + position: 5 + length: 3 # currentTimeZone: FC # SetTimeZoneRequest: 2B RetrieveScheduleRequest: diff --git a/tests/test_async_client.py b/tests/test_async_client.py index 49de1b2..933d4a0 100644 --- a/tests/test_async_client.py +++ b/tests/test_async_client.py @@ -115,6 +115,26 @@ async def test_get_current_date( assert await controller.get_current_date() == date +async def test_set_current_time( + rainbird_controller: Callable[[], Awaitable[AsyncRainbirdController]], + api_response: Callable[[...], Awaitable[None]], +) -> None: + """Test for setting the current time.""" + controller = await rainbird_controller() + api_response("01", commandEcho="11") + await controller.set_current_time(datetime.datetime.now().time()) + + +async def test_set_current_date( + rainbird_controller: Callable[[], Awaitable[AsyncRainbirdController]], + api_response: Callable[[...], Awaitable[None]], +) -> None: + """Test for setting the current date.""" + controller = await rainbird_controller() + api_response("01", commandEcho="13") + await controller.set_current_date(datetime.date.today()) + + async def test_get_water_budget( rainbird_controller: Callable[[], Awaitable[AsyncRainbirdController]], api_response: Callable[[...], Awaitable[None]], diff --git a/tests/testdata/date_time.yaml b/tests/testdata/date_time.yaml index 5343910..655ab71 100644 --- a/tests/testdata/date_time.yaml +++ b/tests/testdata/date_time.yaml @@ -1,13 +1,29 @@ data: + - "10" - "900C3623" + - "12" - "9212B7E2" + - "11162F13" + - "130917E7" + - "0111" decoded_data: + - type: CurrentTimeRequest - type: CurrentTimeResponse hour: 12 minute: 54 second: 35 + - type: CurrentDateRequest - type: CurrentDateResponse year: 2018 month: 11 day: 18 - + - type: SetCurrentTimeRequest + hour: 22 + minute: 47 + second: 19 + - type: SetCurrentDateRequest + day: 9 + month: 1 + year: 2023 + - type: AcknowledgeResponse + commandEcho: 17