bug fix; enhanced script

This commit is contained in:
HappyZ 2019-05-05 14:54:31 -05:00
parent e921ae3481
commit 1d44d75a29
2 changed files with 91 additions and 49 deletions

View File

@ -13,8 +13,8 @@ echo "Create folder on vacuum.."
${REMOTE_CMD} mkdir -p ${EXP_FP}/libs ${REMOTE_CMD} mkdir -p ${EXP_FP}/libs
echo "Push files to vacuum to run.." echo "Push files to vacuum to run.."
scp ./libs/__init__.py ${REMOTE_EXP_FP} scp ./libs/__init__.py ${REMOTE_EXP_FP}/libs/
scp ./libs/parser.py ${REMOTE_EXP_FP} scp ./libs/parser.py ${REMOTE_EXP_FP}/libs/
scp ./get_loc_est.py ${REMOTE_EXP_FP} scp ./get_loc_est.py ${REMOTE_EXP_FP}
echo "Install necessary packages" echo "Install necessary packages"

View File

@ -4,6 +4,7 @@ import json
import miio import miio
import codecs import codecs
import socket import socket
import binascii
import subprocess import subprocess
from libs.env import set_env_var from libs.env import set_env_var
@ -20,21 +21,22 @@ def config_help():
def control_help(): def control_help():
print('Control Command Menu') print('Control Command Menu')
print('help - this message') print('help - this message')
print('home - move vacuum to dock location') print('home - move vacuum to dock location')
print('move auto/pause/stop. - auto scanning movement (no data parsing)') print('move auto/pause/stop/home. - auto scanning movement (no data parsing)')
print('move rotate speed time - move (-180, 180)deg at (-0.3,0.3)m/s for `time`ms') print('move rotate speed time - move (-180, 180)deg at (-0.3,0.3)m/s for `time`ms')
print('goto x_coor y_coor - move to x,y location on map') print('fanspeed integer - set fan speed to be [1-99]')
print('trace on/off - manually start/stop collecting trace') print('goto x_coor y_coor - move to x,y location on map')
print('download trace/map - download the trace or map on vacuum') print('trace on/off - manually start/stop collecting trace')
print('config <cmds> - configuration') print('download trace/map - download the trace or map on vacuum')
print('quit/exit - exit controller (Ctrl + D does the same)') print('config <cmds> - configuration')
print('quit/exit - exit controller (Ctrl + D does the same)')
def run_ssh_command(cmd): def run_ssh_command(cmd):
try: try:
output = subprocess.check_output( output = subprocess.check_output(
"ssh -o ConnectTimeout=10 -t root@${{MIROBO_IP}} '{}'" "ssh -o ConnectTimeout=10 root@${{MIROBO_IP}} '{}'"
.format(cmd), .format(cmd),
shell=True shell=True
).decode() ).decode()
@ -83,18 +85,13 @@ class VacuumController():
if token: if token:
self.set_token(token) self.set_token(token)
# if we still don't have an IP address, or asked to scan anyways
if forceScan or self.get_ip() is None:
self.finding_ip()
self.vacuum = miio.Vacuum( self.vacuum = miio.Vacuum(
ip=self.get_ip(), ip=self.get_ip(),
token=self.get_token() token=self.get_token()
) )
# now if we still don't have a valid token, or asked to scan anyways if forceScan or self.get_ip() is None or self.get_token() is None:
if forceScan or self.get_token() is None: self.discover()
self.fetching_token()
export_ip_token(self.get_ip(), self.get_token()) export_ip_token(self.get_ip(), self.get_token())
@ -116,45 +113,65 @@ class VacuumController():
def set_config(self, key, val): def set_config(self, key, val):
self.config[key] = val self.config[key] = val
def _discover_devices(self, timeout=5): def _discover(self, timeout=5):
ips = [] seen_devices = []
magic = '21310020ffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
# broadcast magic handshake to find devices # broadcast magic handshake to find devices
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(timeout) s.settimeout(timeout)
s.sendto( s.sendto(bytes.fromhex(magic), ('<broadcast>', 54321))
bytes.fromhex('21310020ffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
('<broadcast>', 54321)
)
while 1: while 1:
try: try:
__, addr = s.recvfrom(1024) data, addr = s.recvfrom(1024)
if addr[0] not in ips: m = miio.protocol.Message.parse(data)
ips.append(addr[0]) if addr[0] not in seen_devices:
seen_device = (
addr[0],
binascii.hexlify(m.header.value.device_id).decode(),
m.checksum
)
print(
"IP {} (ID: {}) - token: {}"
.format(
seen_device[0],
seen_device[1],
codecs.encode(seen_device[2], 'hex').decode()
)
)
seen_devices.append(seen_device)
except socket.timeout: except socket.timeout:
print("Discover done!")
break # ignore timeouts on discover break # ignore timeouts on discover
except Exception as e: except Exception as e:
print('Error while reading discover results: {}'.format(e)) print('Error while reading discover results: {}'.format(e))
break break
return ips return seen_devices
def finding_ip(self): def discover(self):
''' '''
getting ip of vacuum getting ip and token of device, e.g., vacuum
''' '''
ips = self._discover_devices() seen_devices = self._discover()
if not ips: if not seen_devices:
print('Err: cannot find any vacuum IP') print('Err: cannot find any devices')
exit(-1) exit(-1)
if len(ips) == 1: if len(seen_devices) == 1:
self.set_ip(ips[0]) self.set_ip(seen_devices[0][0])
self.vacuum.token = seen_devices[0][2]
self.set_token(codecs.encode(seen_devices[0][2], 'hex').decode())
return return
print('Found multiple IPs:') print('Found multiple IPs:')
for i, ip in enumerate(ips): for i, seen_device in enumerate(seen_devices):
print(' {0}. {1}'.format(i+1, ip)) print(
' {0}. {1} - {2} - {3}'
.format(i+1, seen_device[0], seen_device[1], seen_device[2])
)
try: try:
selected = input('Please select one by typing number (1-{}): '.format(len(ips))) selected = input('Please select one by typing number (1-{}): '.format(len(ips)))
self.set_ip(ips[int(selected)-1]) self.set_ip(seen_devices[int(selected)-1][0])
self.vacuum.token = seen_devices[int(selected)-1][2]
self.set_token(codecs.encode(seen_devices[int(selected)-1][2], 'hex').decode())
except KeyboardInterrupt: except KeyboardInterrupt:
print('User requested to exit') print('User requested to exit')
exit(0) exit(0)
@ -175,7 +192,7 @@ class VacuumController():
print('Sending handshake to get token') print('Sending handshake to get token')
m = self.vacuum.do_discover() m = self.vacuum.do_discover()
self.vacuum.token = m.checksum self.vacuum.token = m.checksum
self.set_token(codecs.encode(m.checksum, 'hex')) self.set_token(codecs.encode(m.checksum, 'hex').decode())
def test_connection(self): def test_connection(self):
''' '''
@ -255,10 +272,15 @@ class VacuumController():
print("Insufficient command") print("Insufficient command")
return False return False
if cmd[1] == 'on' or cmd[1] == 'start' or cmd[1] == 'enable': if cmd[1] == 'on' or cmd[1] == 'start' or cmd[1] == 'enable':
print("Cleaning old data on device..")
if run_ssh_command(
"rm {0}/*.ppm && rm {0}/*.csv".format(self.get_remote_folder())
) is None:
return False
print("Running script on vacuum..") print("Running script on vacuum..")
if run_ssh_command( if run_ssh_command(
"python3 {0}/get_loc_est.py {1} &" "nohup /usr/bin/python3 {0}/get_loc_est.py {0}/{1} > /dev/null 2>&1 &"
.format(self.get_remote_folder, "tmp.csv") .format(self.get_remote_folder(), "tmp.csv")
) is None: ) is None:
return False return False
elif cmd[1] == 'off' or cmd[1] == 'stop' or cmd[1] == 'disable': elif cmd[1] == 'off' or cmd[1] == 'stop' or cmd[1] == 'disable':
@ -287,7 +309,8 @@ class VacuumController():
elif cmd[1] == 'map': elif cmd[1] == 'map':
# find file first # find file first
content = run_ssh_command( content = run_ssh_command(
"ls /run/shm/*.ppm" "cp /run/shm/*.ppm {0} && ls {0}/*.ppm"
.format(self.get_remote_folder())
) )
if not content: if not content:
return False return False
@ -295,7 +318,8 @@ class VacuumController():
if len(files) == 0: if len(files) == 0:
print("Cannot find map file!") print("Cannot find map file!")
return False return False
# download only the last ppm file print("Found maps: {}".format(files))
# download only the latest ppm file
if not fetch_file_from_vacuum( if not fetch_file_from_vacuum(
files[-1], files[-1],
"./{}_map.ppm".format(cmd[2] if len(cmd) > 2 else prefix) "./{}_map.ppm".format(cmd[2] if len(cmd) > 2 else prefix)
@ -322,12 +346,30 @@ class VacuumController():
elif cmd[1] == 'stop': elif cmd[1] == 'stop':
print("Stopping..") print("Stopping..")
self.vacuum.stop() self.vacuum.stop()
elif cmd[1] == 'home':
print("Returning Home..")
self.vacuum.home()
elif len(cmd) > 2: elif len(cmd) > 2:
try: try:
duration = int(cmd[3]) if len(cmd) > 3 else 1500 duration = int(cmd[3]) if len(cmd) > 3 else 1500
self.vacuum.manual_control(int(cmd[1]), float(cmd[2]), duration) self.vacuum.manual_control(int(cmd[1]), float(cmd[2]), duration)
except ValueError: except ValueError:
print("Err: rotation in (-180, 180), speed in (-0.3, 0.3), duration as ms in integer (default 1500)") print("Err: rotation in (-180, 180), speed in (-0.3, 0.3), duration as ms in integer (default 1500)")
return False
except BaseException as e:
print("Err: {}".format(e))
return False
elif cmd[0] == 'fanspeed':
if len(cmd) == 1:
print("Insufficient command")
return False
try:
self.vacuum.set_fan_speed(int(cmd[1]))
except ValueError:
print("Err: speed must be integer")
return False
except BaseException as e:
print("Err: {}".format(e))
return False return False
elif cmd[0] == 'goto': elif cmd[0] == 'goto':
if len(cmd) < 3: if len(cmd) < 3:
@ -364,10 +406,10 @@ class VacuumController():
def init_controller(ip, token): def init_controller(ip, token):
c = VacuumController(ip=ip, token=token, forceScan=False) c = VacuumController(ip=ip, token=token, forceScan=False)
# if not c.test_connection(): if not c.test_connection():
# c = VacuumController(forceScan=True) c = VacuumController(forceScan=True)
# if not c.test_connection(): if not c.test_connection():
# print("Cannot connect to vacuum!") print("Cannot connect to vacuum!")
# exit(-1) exit(-1)
return c return c