--- a/basestation_interface.py 2021-01-17 22:49:44.000000000 +0100 +++ b/basestation_interface.py 2021-01-18 11:32:09.028425343 +0100 @@ -1,15 +1,21 @@ import enum import time - +import subprocess +import os +import sys # sudo apt install pip3 libglib2.0-dev # sudo pip3 install bluepy import bluepy - +import signal import log - +import psutil # based on: https://gist.github.com/waylonflinn/d525e08674ec3abb5c98cd41d1fd2f24 - +STATIONVER="1.0" +BMAC = "40:4E:36:BD:A8:45" #address of the station (b) +BID = "62F5DDD9" #id found on the rear of the base station (b) +CMAC = "40:4E:36:BD:A1:38" #address of the station (c) +CID = "0E97C927" #id found on the rear of the base station (c) class BasestationPowerInterface: class Action(enum.Enum): @@ -19,8 +25,10 @@ def __init__(self, config): self.config = config - + self.vivesub = None self.devices = [] + self.active = False + self.count = 0 def scan(self): class Delegate(bluepy.btle.DefaultDelegate): @@ -63,14 +71,53 @@ raise e self.devices = delegate.devices - if len(self.devices) == 0: - raise RuntimeError('Bluetooth scan found no Base Stations. ' - 'If there are powered Base Stations near you, ' - 'this is probably a problem with your Bluetooth device.') def action(self, action): address = 0x12 # location of the byte which sets the power state + if STATIONVER=="1.0": + if action == self.Action.TOGGLE: + if self.active: + action = self.action.OFF + else: + action = self.action.ON + + if action == self.Action.ON: + proc = [] + for p in psutil.process_iter(): + for j in p.cmdline(): + if 'lhctrl.py' in j: + proc.append(p) + + if len(proc) >= 1: + self.active = True + return + + if not self.active: + self.vivesub = subprocess.Popen([sys.executable,os.path.join(sys.path[0],"lhctrl.py"),"-b " + BID, "--lh_b_mac",BMAC,"-c " + CID, "--lh_c_mac",CMAC]) + self.active = True + + if action == self.Action.OFF: + #if self.active: #lhctrl.py works by pinging the base stations every couple of seconds, so by opening a process with the script + # if self.vivesub.poll() != None: #the base stations will turn on, and will stay on unless lhctrl.py is closed. + # self.vivesub.send_signal(signal.SIGINT) #if lhctrl crashes (Which could happen if doesn't find one of the stations) the lighthouse which got turned on will + # #shut off auomatically. + # self.active = False #if lhctrl receives a SIGINT signal (equivalent to ctrl+c) it will ping the stations once more setting their ping timeout to 0 + #else: #and will shutdown instantly. + self.active = False + proc = [] + for p in psutil.process_iter(): + for j in p.cmdline(): + if 'lhctrl.py' in j: + proc.append(p) + + for p in proc: + print("Terminating") + p.send_signal(signal.SIGINT) + time.sleep(10) + return + + for device in self.devices: basestation = bluepy.btle.Peripheral() log.i('Connecting to {}'.format(device)) @@ -88,13 +135,17 @@ if action == self.Action.ON: if not self.config.dry_run(): - basestation.writeCharacteristic(address, b'\x01') + + basestation.writeCharacteristic(address, b'\x01') else: log.w('Skipping because of dry run:') log.i('Turning on') elif action == self.Action.OFF: if not self.config.dry_run(): - basestation.writeCharacteristic(address, b'\x00') + if STATIONVER=="1.0": + self.vivesub.kill() + else: + basestation.writeCharacteristic(address, b'\x00') else: log.w('Skipping because of dry run:') log.i('Turning off') @@ -106,6 +157,8 @@ attempt_count = 0 success_count = 0 last_error = None + if STATIONVER=="1.0": + max_attempts = 1 while attempt_count < max_attempts: try: if try_all: @@ -116,7 +169,7 @@ log.i('Success of attempt {} of {}'.format(attempt_count + 1, max_attempts)) except Exception as e: last_error = e - log.e('Failure of attempt {} of {}: {}'.format(attempt_count + 1, max_attempts, e)) + log.e('Failure of attempt {} of {}'.format(attempt_count + 1, max_attempts)) attempt_count += 1 time.sleep(0.5) # to increase robustness @@ -124,8 +177,8 @@ if success_count == 0: log.e('No successful attempt in any of the {} attempts. Last error:'.format(max_attempts)) raise last_error - - log.i("Scanning for Base Stations:") - attempt_loop(lambda: self.scan(), self.config.basestation_attempt_count_scan()) - log.i("Changing power state of Base Stations:") + + if STATIONVER != "1.0": + attempt_loop(lambda: self.scan(), self.config.basestation_attempt_count_scan()) + attempt_loop(lambda: self.action(action), self.config.basestation_attempt_count_set(), try_all=True)