forked from github.com/eufy_robovac
Compare commits
7 Commits
v1.0
...
6622974610
| Author | SHA1 | Date | |
|---|---|---|---|
|
6622974610
|
|||
|
8323114faf
|
|||
|
7008746353
|
|||
|
214ddad915
|
|||
|
2c273b6aa8
|
|||
|
1c8e84862c
|
|||
|
08d0fdfc4b
|
10
CHANGELOG.md
Normal file
10
CHANGELOG.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# v1.1
|
||||
|
||||
- Fix bugs and improve code efficiency
|
||||
- remove `--debug` flag
|
||||
- `--pause` now works just fine.
|
||||
- script won't hang on erroneous go-home commands.
|
||||
|
||||
# v1.0 - Initial release
|
||||
|
||||
Initial release
|
||||
@@ -1,5 +1,5 @@
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:20.04
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt update && apt upgrade -y
|
||||
RUN apt-get -qq install python3.12-full pipenv -y
|
||||
RUN apt-get -qq install python3.9 python3.9-dev pipenv -y
|
||||
|
||||
|
||||
2
Pipfile
2
Pipfile
@@ -10,4 +10,4 @@ pyinstaller = "*"
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.12"
|
||||
python_version = "3.9"
|
||||
|
||||
162
README.md
Normal file
162
README.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Table of Contents <!-- omit in toc -->
|
||||
|
||||
- [Compiling](#compiling)
|
||||
- [Requirements](#requirements)
|
||||
- [Instructions](#instructions)
|
||||
- [Configuration](#configuration)
|
||||
- [Examples](#examples)
|
||||
- [Command-line](#command-line)
|
||||
- [Config file](#config-file)
|
||||
- [Usage](#usage)
|
||||
- [Obtaining device credentials](#obtaining-device-credentials)
|
||||
- [tl;dr](#tldr)
|
||||
- [Instructions:](#instructions-1)
|
||||
- [With docker](#with-docker)
|
||||
- [1. Enter a shell within an ubuntu docker container](#1-enter-a-shell-within-an-ubuntu-docker-container)
|
||||
- [2. Set up your environment](#2-set-up-your-environment)
|
||||
- [3. Clone the repo](#3-clone-the-repo)
|
||||
- [4. Install requirements](#4-install-requirements)
|
||||
- [5. Get your credentials](#5-get-your-credentials)
|
||||
|
||||
# eufy_robovac <!-- omit in toc -->
|
||||
|
||||
This is a cli script adapted from [Richard Mitchell's work](https://github.com/mitchellrj/eufy_robovac_). It abandons all the code for integrating with homeassistant in lieu of creating a portable binary to control the thing - either manually or with cron job.
|
||||
|
||||
# Compiling
|
||||
|
||||
This python script can be compiled to a single executable binary.
|
||||
|
||||
## Requirements
|
||||
|
||||
- linux machine
|
||||
- git
|
||||
- docker
|
||||
|
||||
## Instructions
|
||||
|
||||
```
|
||||
git clone https://gitea.raer.me/freyjagp/eufy_robovac.git
|
||||
cd eufy_robovac
|
||||
chmod +x compile
|
||||
./compile
|
||||
```
|
||||
|
||||
This will create a docker image then use it to compile an executable binary to `eufy_robovac/dist/vac`.
|
||||
|
||||
# Configuration
|
||||
|
||||
The device ID, ip address, and local code are required for this to work. They may be passed as arguments, or through a config file. The defalt path for the config file is `/etc/robovac.conf`. This can be altered with the `-c` or `--config` flags.
|
||||
|
||||
## Examples
|
||||
|
||||
### Command-line
|
||||
|
||||
Set config file to any arbitrary location:
|
||||
|
||||
```
|
||||
robovac --config=/home/user/robovac.conf
|
||||
```
|
||||
|
||||
Provide credentials inline:
|
||||
|
||||
```
|
||||
robovac --device_id=DEVICE_ID --ip=192.168.1.1 --local_code=LOCAL_CODE
|
||||
```
|
||||
|
||||
### Config file
|
||||
|
||||
```
|
||||
[robovac]
|
||||
device_id=DEVICE_ID
|
||||
ip=192.168.1.1
|
||||
local_code=LOCAL_CODE
|
||||
```
|
||||
|
||||
[see here](config/robovac.conf.example)
|
||||
|
||||
# Usage
|
||||
|
||||
```
|
||||
usage: vac [-h] [-c CONFIG] [--device_id DEVICE_ID] [--ip IP] [--local_code LOCAL_CODE] [--time TIME] [--pause] [--home] [--debug] [--verbose] [--quiet]
|
||||
|
||||
Control a Robovac device.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-c CONFIG, --config CONFIG
|
||||
Path to config file
|
||||
--device_id DEVICE_ID
|
||||
Device ID
|
||||
--ip IP Device IP address
|
||||
--local_code LOCAL_CODE
|
||||
Secret key obtained from eufy
|
||||
--time TIME, -t TIME Cleaning time in minutes
|
||||
--pause, -p Pause vacuum
|
||||
--home, -b Go home
|
||||
--debug, -d Enter debugging mode (won't send commands to vacuum)
|
||||
--verbose, -v Enable verbose logs
|
||||
--quiet, -q Quiet logs
|
||||
```
|
||||
|
||||
# Obtaining device credentials
|
||||
|
||||
## tl;dr
|
||||
|
||||
use [this](https://github.com/markbajaj/eufy-device-id-python) repo and follow the instructions.
|
||||
|
||||
## Instructions:
|
||||
|
||||
You'll need to install git, python3, build-essential, pipenv, libffi-dev, python3-dev, and libssl-dev with your package manager. Then you can do
|
||||
|
||||
```
|
||||
git clone https://github.com/markbajaj/eufy-device-id-python
|
||||
cd eufy-device-id-python
|
||||
pipenv install
|
||||
pipenv shell
|
||||
python -m eufy_local_id_grabber "YOUR_EUFY_EMAIL" "YOUR_EUFY_PASSWORD"
|
||||
```
|
||||
|
||||
This might not work and requires installing packages you may or may not want/need on your base os. We can do better.
|
||||
|
||||
### With docker
|
||||
|
||||
#### 1. Enter a shell within an ubuntu docker container
|
||||
|
||||
```
|
||||
docker run -it ubuntu:latest bash
|
||||
```
|
||||
|
||||
#### 2. Set up your environment
|
||||
|
||||
```
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt update
|
||||
apt install -y git python3 python3-venv python3-pip build-essential pipenv libffi-dev python3-dev libssl-dev
|
||||
```
|
||||
|
||||
#### 3. Clone the repo
|
||||
|
||||
```
|
||||
git clone https://github.com/markbajaj/eufy-device-id-python.git
|
||||
cd eufy-device-id-python
|
||||
```
|
||||
|
||||
#### 4. Install requirements
|
||||
|
||||
```
|
||||
pipenv install
|
||||
```
|
||||
|
||||
#### 5. Get your credentials
|
||||
|
||||
```
|
||||
pipenv shell
|
||||
python -m eufy_local_id_grabber "YOUR_EUFY_EMAIL" "YOUR_EUFY_PASSWORD"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Home: <home ID>
|
||||
Device: RoboVac, device ID <DEVICE_ID>, local key <LOCAL_KEY>
|
||||
```
|
||||
1
compile
1
compile
@@ -3,6 +3,5 @@
|
||||
|
||||
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"
|
||||
4
config/robovac.conf.example
Normal file
4
config/robovac.conf.example
Normal file
@@ -0,0 +1,4 @@
|
||||
[robovac]
|
||||
device_id=DEVICE_ID
|
||||
ip=192.168.1.1
|
||||
local_code=LOCAL_CODE
|
||||
70
src/vac.py
70
src/vac.py
@@ -12,6 +12,9 @@ import os
|
||||
from robovac.robovac import Robovac
|
||||
|
||||
|
||||
DEFAULT_TIME = 20
|
||||
|
||||
|
||||
stop_event = asyncio.Event()
|
||||
|
||||
|
||||
@@ -81,7 +84,14 @@ async def async_pause(r: Robovac):
|
||||
await r.async_pause(callback)
|
||||
|
||||
|
||||
async def async_main(device_id,ip,local_code,time,go_home,debug,pause):
|
||||
async def async_main(
|
||||
device_id,
|
||||
ip,
|
||||
local_code,
|
||||
time=DEFAULT_TIME,
|
||||
go_home=False,
|
||||
pause=False
|
||||
):
|
||||
asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, signal_handler)
|
||||
asyncio.get_event_loop().add_signal_handler(signal.SIGINT, signal_handler)
|
||||
r = Robovac(device_id,ip,local_code)
|
||||
@@ -89,29 +99,31 @@ async def async_main(device_id,ip,local_code,time,go_home,debug,pause):
|
||||
await asyncio.sleep(2)
|
||||
|
||||
|
||||
if debug:
|
||||
if not go_home and not pause:
|
||||
while not stop_event.is_set():
|
||||
if not go_home:
|
||||
print("Auto cleaning")
|
||||
await stepper(time)
|
||||
if go_home:
|
||||
print("Go home")
|
||||
if pause:
|
||||
print("Pause")
|
||||
else:
|
||||
while not stop_event.is_set():
|
||||
if not go_home:
|
||||
await async_auto_clean(r, time = int(time))
|
||||
await async_go_home(r)
|
||||
if go_home:
|
||||
await async_go_home(r)
|
||||
if pause:
|
||||
await async_pause(r)
|
||||
await async_auto_clean(r, time = int(time))
|
||||
await async_go_home(r)
|
||||
stop_event.set()
|
||||
|
||||
|
||||
if not debug:
|
||||
if stop_event.is_set() and not r.go_home and not pause: await async_go_home(r)
|
||||
if r._connected: await r.async_disconnect()
|
||||
if go_home and not pause:
|
||||
while not stop_event.is_set():
|
||||
await async_go_home(r)
|
||||
stop_event.set()
|
||||
|
||||
|
||||
if pause and not go_home:
|
||||
while not stop_event.is_set():
|
||||
await async_pause(r)
|
||||
stop_event.set()
|
||||
|
||||
|
||||
if not r.go_home and not pause:
|
||||
await async_go_home(r)
|
||||
|
||||
|
||||
if r._connected:
|
||||
await r.async_disconnect()
|
||||
|
||||
|
||||
def main(*args, **kwargs):
|
||||
@@ -141,19 +153,15 @@ def main(*args, **kwargs):
|
||||
defaults = {}
|
||||
|
||||
|
||||
if not use_config:
|
||||
print("Configuration skipped")
|
||||
|
||||
|
||||
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=20, help="Cleaning time in minutes")
|
||||
parser.add_argument('--pause','-p', action='store_true', dest="pause", default=False, help="Pause vacuum")
|
||||
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('--debug','-d', action='store_true', dest="debug", default=False, help="Enter debugging mode (won't send commands to vacuum)")
|
||||
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")
|
||||
args = parser.parse_args()
|
||||
@@ -165,17 +173,21 @@ def main(*args, **kwargs):
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
elif args.quiet:
|
||||
logging.basicConfig(level=logging.CRITICAL)
|
||||
sys.stdout = open(os.devnull, 'w')
|
||||
else:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
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.debug,args.pause))
|
||||
asyncio.run(async_main(args.device_id, args.ip, args.local_code, args.time, args.go_home,args.pause))
|
||||
except Exception as e:
|
||||
if args.debug or args.verbose:
|
||||
print(e)
|
||||
|
||||
Reference in New Issue
Block a user