From eaf1fbc811d83f528049b057126e7efff83049ce Mon Sep 17 00:00:00 2001 From: Freyja Odinthrir Date: Thu, 11 Sep 2025 15:09:34 -0700 Subject: [PATCH] Add mode selection to script. --- .gitignore | 2 +- CHANGELOG.md | 4 ++ build | 8 ++++ compile | 7 --- src/vac.py | 119 +++++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 115 insertions(+), 25 deletions(-) create mode 100755 build delete mode 100755 compile diff --git a/.gitignore b/.gitignore index cd52c5d..4832bbf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -build +build/ dist __pycache__ *.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index b96169a..ac4f99b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v1.2 + +- Add mode selection + # v1.1 - Fix bugs and improve code efficiency diff --git a/build b/build new file mode 100755 index 0000000..f41985d --- /dev/null +++ b/build @@ -0,0 +1,8 @@ +#!/bin/bash + + +NAME="robovac-build" + + +docker buildx build . -t $NAME +docker run -v $PWD:/opt/build --rm -w "/opt/build" $NAME bash -c "pipenv install;pipenv run pyinstaller -F src/vac.py" \ No newline at end of file diff --git a/compile b/compile deleted file mode 100755 index ed31389..0000000 --- a/compile +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - - -NAME="compile" - -docker buildx build . -t $NAME -docker run -v $PWD:/opt/compile --rm -w "/opt/compile" $NAME bash -c "pipenv install;pipenv run pyinstaller -F src/vac.py" \ No newline at end of file diff --git a/src/vac.py b/src/vac.py index 32dc90b..2590edc 100755 --- a/src/vac.py +++ b/src/vac.py @@ -9,7 +9,8 @@ from enum import Enum import os -from robovac.robovac import Robovac +from robovac.robovac import Robovac, CleanSpeed, WorkMode +from robovac.property import StringEnum DEFAULT_TIME = 20 @@ -18,6 +19,13 @@ DEFAULT_TIME = 20 stop_event = asyncio.Event() +class Modes(StringEnum): + DEFAULT = CleanSpeed.BOOST_IQ, WorkMode.AUTO + MAX = CleanSpeed.MAX, WorkMode.AUTO + EDGE = CleanSpeed.MAX, WorkMode.EDGE + SPOT = CleanSpeed.MAX, WorkMode.SPOT + + def signal_handler(): print(f'\nExiting...') stop_event.set() @@ -70,7 +78,10 @@ async def stepper(time): return True -async def async_auto_clean(r: Robovac,time): +async def async_clean(r: Robovac, time: int, mode: Modes): + if mode: + await r.async_set_clean_speed(mode[0]) + await r.async_set_work_mode(mode[1]) await r.async_start_cleaning(callback) await stepper(time) await r.async_pause() @@ -90,7 +101,8 @@ async def async_main( local_code, time=DEFAULT_TIME, go_home=False, - pause=False + pause=False, + mode=Modes.DEFAULT ): asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, signal_handler) asyncio.get_event_loop().add_signal_handler(signal.SIGINT, signal_handler) @@ -99,9 +111,9 @@ async def async_main( await asyncio.sleep(2) - if not go_home and not pause: + if mode and not go_home and not pause: while not stop_event.is_set(): - await async_auto_clean(r, time = int(time)) + await async_clean(r, time, mode) await async_go_home(r) stop_event.set() @@ -154,16 +166,73 @@ def main(*args, **kwargs): parser = argparse.ArgumentParser(description="Control a Robovac device.") - parser.add_argument('-c', '--config', help="Path to config file", default=early_args.config) - parser.add_argument('--device_id', help="Device ID", default=None if early_args.device_id else defaults.get('device_id')) - parser.add_argument('--ip', help="Device IP address", default=None if early_args.ip else defaults.get('ip')) - parser.add_argument('--local_code', help="Secret key obtained from eufy", default=None if early_args.local_code else defaults.get('local_code')) - parser.add_argument('--time', '-t', type=int, default=DEFAULT_TIME, help="Cleaning time in minutes") - parser.add_argument('--home', '-b', action='store_true', dest="go_home", default=False, help="Go home") - parser.add_argument('--pause','-p', action='store_true', dest="pause", default=False, help="Pause vacuum") - # parser.add_argument('--debug','-d', action='store_true', dest="debug", default=False, help="Enter debugging mode (won't send commands to vacuum)") - parser.add_argument('--verbose','-v', action='store_true', dest="verbose", default=False, help="Enable verbose logs") - parser.add_argument('--quiet','-q', action='store_true', dest="quiet", default=False, help="Quiet logs") + parser.add_argument( + '-c', '--config', + help="Path to config file", + default=early_args.config + ) + parser.add_argument( + '--device_id', + help="Device ID", + default=None if early_args.device_id else defaults.get('device_id') + ) + parser.add_argument( + '--ip', + help="Device IP address", + default=None if early_args.ip else defaults.get('ip') + ) + parser.add_argument( + '--local_code', + help="Secret key obtained from eufy", + default=None if early_args.local_code else defaults.get('local_code') + ) + parser.add_argument( + '--time', '-t', + type=int, + help="Cleaning time in minutes", + default=DEFAULT_TIME + ) + parser.add_argument( + '--home', '-b', + action='store_true', + help="Go home" + default=False, + dest="go_home", + ) + parser.add_argument( + '--pause','-p', + action='store_true', + help="Pause vacuum", + default=False, + dest="pause", + ) + parser.add_argument( + '--mode', '-m', + dest="mode", + default="default", + help = '''Options: default, max, edge, spot \n + default: Automatic work mode, medium suction \n + max: Automatic work mode, max suction \n + edge: Clean edges of room, max suction \n + spot: Spot clean, max suction \n + ''' + ) + parser.add_argument( + '--verbose','-v', + action='store_true', + dest="verbose", + default=False, + help="Enable verbose logs" + ) + parser.add_argument( + '--quiet','-q', + action='store_true', + dest="quiet", + default=False, + help="Quiet logs" + ) + + args = parser.parse_args() @@ -178,16 +247,32 @@ def main(*args, **kwargs): logging.basicConfig(level=logging.INFO) - if not use_config: print("Configuration skipped") + if args.mode.lower() and (args.pause or args.home): + print("Mode will be overridden.") + args.mode = None + elif args.mode.lower() == "default": + args.mode = Modes.DEFAULT + elif args.mode.lower() == "max": + args.mode = Modes.MAX + elif args.mode.lower() == "spot": + args.mode = Modes.SPOT + elif args.mode.lower() == "edge": + args.mode = Modes.EDGE + + + if not use_config: + print("Configuration skipped") missing = [key for key in ['device_id', 'ip', 'local_code'] if getattr(args, key) is None] + + if missing: parser.error(f"Missing required argument(s): {', '.join(missing)}") try: - asyncio.run(async_main(args.device_id, args.ip, args.local_code, args.time, args.go_home,args.pause)) + asyncio.run(async_main(args.device_id, args.ip, args.local_code, args.time, args.go_home,args.pause, args.mode)) except Exception as e: if args.debug or args.verbose: print(e)