Initial commit
This commit is contained in:
commit
80d22843cc
|
@ -0,0 +1,3 @@
|
||||||
|
*~
|
||||||
|
*%
|
||||||
|
*.py[co]
|
|
@ -0,0 +1,168 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import click
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class EufyRawIR:
|
||||||
|
""" Low level IR signal modulation """
|
||||||
|
|
||||||
|
_IR_PREAMBLE = (3000, 3000)
|
||||||
|
_IR_0 = (400, 600)
|
||||||
|
_IR_1 = (400, 1600)
|
||||||
|
_IR_TRAILER = (400, 20000)
|
||||||
|
|
||||||
|
def _modulate(self, message):
|
||||||
|
signal = list(self._IR_PREAMBLE)
|
||||||
|
for b in message:
|
||||||
|
for i in range(8):
|
||||||
|
if (b << i) & 0x80:
|
||||||
|
signal.extend(list(self._IR_1))
|
||||||
|
else:
|
||||||
|
signal.extend(list(self._IR_0))
|
||||||
|
signal.extend(list(self._IR_TRAILER))
|
||||||
|
return 3*signal
|
||||||
|
|
||||||
|
def sendRaw(self, message):
|
||||||
|
print(self._modulate(message))
|
||||||
|
|
||||||
|
|
||||||
|
class EufyIR(EufyRawIR):
|
||||||
|
""" High level Eufy commands """
|
||||||
|
|
||||||
|
_HEADER = 0x68
|
||||||
|
|
||||||
|
CLEAN_AUTO = 0x5d
|
||||||
|
CLEAN_SPOT = 0x8c
|
||||||
|
CLEAN_EDGE = 0x9c
|
||||||
|
CLEAN_ROOM = 0xad
|
||||||
|
STOP = 0x4f
|
||||||
|
POWER_MAX = 0x1c
|
||||||
|
POWER_BOOSTIQ = 0x1d
|
||||||
|
POWER_STANDARD = 0x1e
|
||||||
|
MOVE_FORWARD = 0x2f
|
||||||
|
MOVE_BACKWARD = 0x7f
|
||||||
|
MOVE_CCW = 0x3f
|
||||||
|
MOVE_CW = 0x6f
|
||||||
|
SET_TIME = 0xbf
|
||||||
|
SET_SCHEDULE = 0xcf
|
||||||
|
CANCEL_SCHEDULE = 0xdf
|
||||||
|
RETURN_BASE = 0xef
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._schedule = 0xff
|
||||||
|
|
||||||
|
def _message(self, code):
|
||||||
|
now = datetime.now()
|
||||||
|
msg = [self._HEADER, code, now.hour, now.minute, self._schedule]
|
||||||
|
checksum = sum(msg) & 0xff
|
||||||
|
msg.append(checksum)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def send(self, code):
|
||||||
|
self.sendRaw(self._message(code))
|
||||||
|
|
||||||
|
def cleanAuto(self):
|
||||||
|
self.send(self.CLEAN_AUTO)
|
||||||
|
|
||||||
|
def cleanSpot(self):
|
||||||
|
self.send(self.CLEAN_SPOT)
|
||||||
|
|
||||||
|
def cleanEdge(self):
|
||||||
|
self.send(self.CLEAN_EDGE)
|
||||||
|
|
||||||
|
def cleanRoom(self):
|
||||||
|
self.send(self.CLEAN_ROOM)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.cleanAuto()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.send(self.STOP)
|
||||||
|
|
||||||
|
def powerMax(self):
|
||||||
|
self.send(self.POWER_MAX)
|
||||||
|
|
||||||
|
def powerBoostIQ(self):
|
||||||
|
self.send(self.POWER_BOOSTIQ)
|
||||||
|
|
||||||
|
def powerStandard(self):
|
||||||
|
self.send(self.POWER_STANDARD)
|
||||||
|
|
||||||
|
def moveForward(self):
|
||||||
|
self.send(self.MOVE_FORWARD)
|
||||||
|
|
||||||
|
def moveBackward(self):
|
||||||
|
self.send(self.MOVE_BACKWARD)
|
||||||
|
|
||||||
|
def moveCCW(self):
|
||||||
|
self.send(self.MOVE_CCW)
|
||||||
|
|
||||||
|
def moveLeft(self):
|
||||||
|
self.moveCCW()
|
||||||
|
|
||||||
|
def moveCW(self):
|
||||||
|
self.send(self.MOVE_CW)
|
||||||
|
|
||||||
|
def moveRight(self):
|
||||||
|
self.moveCW()
|
||||||
|
|
||||||
|
def setTime(self):
|
||||||
|
self.send(self.SET_TIME)
|
||||||
|
|
||||||
|
def setSchedule(self, t):
|
||||||
|
# FIXME: properly store schedule
|
||||||
|
self.send(self.SET_SCHEDULE, t)
|
||||||
|
|
||||||
|
def cancelSchedule(self):
|
||||||
|
# FIXME: properly store schedule
|
||||||
|
self.send(self.CANCEL_SCHEDULE)
|
||||||
|
|
||||||
|
def returnBase(self):
|
||||||
|
self.send(self.RETURN_BASE)
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def cli():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument('mode', required=False,
|
||||||
|
type=click.Choice(['auto', 'spot', 'edge', 'room']))
|
||||||
|
def clean(mode):
|
||||||
|
eufy = EufyIR()
|
||||||
|
dict(
|
||||||
|
auto=eufy.cleanAuto,
|
||||||
|
spot=eufy.cleanSpot,
|
||||||
|
edge=eufy.cleanEdge,
|
||||||
|
room=eufy.cleanRoom
|
||||||
|
).get(mode, eufy.start)()
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument('mode', required=True,
|
||||||
|
type=click.Choice(['standard', 'boostiq', 'max']))
|
||||||
|
def power(mode):
|
||||||
|
eufy = EufyIR()
|
||||||
|
{
|
||||||
|
'standard': eufy.powerStandard,
|
||||||
|
'boostiq': eufy.powerBoostIQ,
|
||||||
|
'max': eufy.powerMax
|
||||||
|
}.get(mode)()
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument('mode', required=True,
|
||||||
|
type=click.Choice(['forward', 'backward', 'ccw', 'cw', 'left', 'right']))
|
||||||
|
def move(mode):
|
||||||
|
eufy = EufyIR()
|
||||||
|
dict(
|
||||||
|
forward=eufy.moveForward,
|
||||||
|
backward=eufy.moveBackward,
|
||||||
|
ccw=eufy.moveCCW,
|
||||||
|
cw=eufy.moveCW,
|
||||||
|
left=eufy.moveLeft,
|
||||||
|
right=eufy.moveRight
|
||||||
|
).get(mode)()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
cli()
|
|
@ -0,0 +1,115 @@
|
||||||
|
AGC: H:3ms L:3ms
|
||||||
|
0: H:400µs L:600µs
|
||||||
|
1: H:400µs L:1.6ms
|
||||||
|
|
||||||
|
Frame: (AGC+48bits+H:400µs+L:20ms)*3
|
||||||
|
|
||||||
|
Format: 68CCHHMMSSKK
|
||||||
|
|
||||||
|
CC: command
|
||||||
|
HH: hour
|
||||||
|
MM: minute
|
||||||
|
SS: schedule (in quarters of an hour from midnight, 0xff=off)
|
||||||
|
KK: checksum (sum of all bytes in the frame modulo 256)
|
||||||
|
|
||||||
|
Code | Command
|
||||||
|
------+---------
|
||||||
|
1c | Max power
|
||||||
|
1d | BoostIQ
|
||||||
|
1e | Standard power
|
||||||
|
2f | Forward
|
||||||
|
3f | Turn CCW
|
||||||
|
4f | Stop cleaning
|
||||||
|
5d | Auto cleaning
|
||||||
|
6f | Turn CW
|
||||||
|
7f | Backward
|
||||||
|
8c | Spot cleaning
|
||||||
|
9c | Edge cleaning
|
||||||
|
ad | Room cleaning
|
||||||
|
bf | Set time
|
||||||
|
cf | Set schedule
|
||||||
|
df | Clear schedule
|
||||||
|
ef | Return to base
|
||||||
|
|
||||||
|
0110 1000 0101 1101 0000 1111 0010 0111 0010 1000 0010 0011 Start
|
||||||
|
685d0f272823
|
||||||
|
|
||||||
|
0110 1000 0100 1111 0000 1111 0010 0111 0010 1000 0001 0101 Stop
|
||||||
|
684f0f272815
|
||||||
|
|
||||||
|
0110 1000 0101 1101 0001 0001 0000 0010 0010 1000 0000 0000 Start
|
||||||
|
685d11022800
|
||||||
|
|
||||||
|
0110 1000 0100 1111 0001 0001 0000 0010 0010 1000 1111 0010 Stop
|
||||||
|
684f110228f2
|
||||||
|
|
||||||
|
0110 1000 1011 1111 0001 0001 0010 0100 0010 1000 1000 0100 Time (5:36pm)
|
||||||
|
68bf11242884
|
||||||
|
|
||||||
|
0110 1000 1011 1111 0001 0001 0010 1011 0010 1000 1000 1011 Time (5:43pm)
|
||||||
|
68bf112b288b
|
||||||
|
|
||||||
|
0110 1000 1011 1111 0001 0001 0010 1011 0010 1000 1000 1011 Time (5:43pm +1.3s)
|
||||||
|
68bf112b288b
|
||||||
|
|
||||||
|
0110 1000 1011 1111 0001 0010 0000 0110 0010 1000 0110 0111 Time (T:6:06pm A:10:00am)
|
||||||
|
68bf12062867
|
||||||
|
HHMM
|
||||||
|
|
||||||
|
0110 1000 0101 1101 0001 0010 0000 0110 0010 1000 0000 0101 Start
|
||||||
|
685d12062805
|
||||||
|
|
||||||
|
0110 1000 0100 1111 0001 0010 0000 0110 0010 1000 1111 0111 Stop (start+0.9s)
|
||||||
|
684f120628f7
|
||||||
|
|
||||||
|
0110 1000 1100 1111 0001 0011 0010 0000 0010 1000 1001 0010 Schedule 10:00am
|
||||||
|
68cf13202892
|
||||||
|
|
||||||
|
0110 1000 1100 1111 0001 0011 0010 1011 0010 1001 1001 1110 Schedule 10:15am
|
||||||
|
68cf132b299e
|
||||||
|
|
||||||
|
0110 1000 1100 1111 0001 0011 0011 0000 0101 1111 1101 1001 Schedule 11:45pm
|
||||||
|
68cf13305fd9
|
||||||
|
|
||||||
|
0110 1000 1101 1111 0001 0011 0011 0110 1111 1111 1000 1111 Schedule off
|
||||||
|
68df1336ff8f
|
||||||
|
|
||||||
|
0110 1000 0101 1101 0001 0100 0000 0110 1111 1111 1101 1110 Start
|
||||||
|
685d1406ffde
|
||||||
|
|
||||||
|
0110 1000 0100 1111 0001 0100 0001 0010 1111 1111 1101 1100 Auto
|
||||||
|
684f1412ffdc
|
||||||
|
|
||||||
|
0110 1000 0001 1100 0001 0100 0001 1001 1111 1111 1011 0000 Power (BoostIQ->Max)
|
||||||
|
681c1419ffb0
|
||||||
|
|
||||||
|
0110 1000 0001 1110 0001 0100 0001 1110 1111 1111 1011 0111 Power (Max->Standard)
|
||||||
|
681e141effb7
|
||||||
|
|
||||||
|
0110 1000 0001 1101 0001 0100 0001 1110 1111 1111 1011 0110 Power (Standard->BoostIQ)
|
||||||
|
681d141effb6
|
||||||
|
|
||||||
|
0110 1000 0010 1111 0001 0100 0010 1110 1111 1111 1101 1000 Up
|
||||||
|
682f142effd8
|
||||||
|
|
||||||
|
0110 1000 0111 1111 0001 0100 0010 1110 1111 1111 0010 1000 Down
|
||||||
|
687f142eff28
|
||||||
|
|
||||||
|
0110 1000 0011 1111 0001 0100 0010 1110 1111 1111 1110 1000 Left
|
||||||
|
683f142effe8
|
||||||
|
|
||||||
|
0110 1000 0110 1111 0001 0100 0010 1110 1111 1111 0001 1000 Right
|
||||||
|
686f142eff18
|
||||||
|
|
||||||
|
0110 1000 1000 1100 0001 0101 0000 0100 1111 1111 0000 1100 Spot
|
||||||
|
688c1504ff0c
|
||||||
|
|
||||||
|
0110 1000 1001 1100 0001 0101 0000 1000 1111 1111 0010 0000 Edge
|
||||||
|
689c1508ff20
|
||||||
|
|
||||||
|
0110 1000 1010 1101 0001 0101 0000 1100 1111 1111 0011 0101 Room
|
||||||
|
68ad150cff35
|
||||||
|
|
||||||
|
0110 1000 1110 1111 0001 0101 0001 0000 1111 1111 0111 1011 Base
|
||||||
|
68ef1510ff7b
|
||||||
|
|
Loading…
Reference in New Issue