From 87f9d0ec6af3f5a226490bdcf97353545f3d6981 Mon Sep 17 00:00:00 2001 From: Nathan Gardiner Date: Wed, 18 Dec 2024 18:02:59 +1100 Subject: [PATCH] BLE local control: Stability updates - use file instead of pipe to avoid blocking, add timeout for commands --- lib/TWCManager/Vehicle/TeslaBLE.py | 52 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/TWCManager/Vehicle/TeslaBLE.py b/lib/TWCManager/Vehicle/TeslaBLE.py index be2d2862..23aeab88 100644 --- a/lib/TWCManager/Vehicle/TeslaBLE.py +++ b/lib/TWCManager/Vehicle/TeslaBLE.py @@ -6,6 +6,7 @@ import logging import os import subprocess +from threading import Timer import time logger = logging.getLogger("\U0001F697 TeslaBLE") @@ -13,10 +14,11 @@ class TeslaBLE: binaryPath = "/home/twcmanager/gobin/tesla-control" + commandTimeout = 10 config = None master = None pipe = None - pipeName = "/tmp/ble_pipe" + pipeName = "/tmp/ble_data" def __init__(self, master): self.master = master @@ -49,6 +51,7 @@ def parseCommandOutput(self, output): return success def peerWithVehicle(self, vin): + self.sendPublicKey(vin) result = subprocess.run( [ self.binaryPath, @@ -63,7 +66,7 @@ def peerWithVehicle(self, vin): ], stdout=subprocess.PIPE, ) - self.sendPublicKey(vin) + self.closeFile() return self.parseCommandOutput(ret) def pingVehicle(self, vin): @@ -71,6 +74,7 @@ def pingVehicle(self, vin): return self.parseCommandOutput(ret) def sendCommand(self, vin, command, args=None): + self.sendPrivateKey(vin) command_string = [ self.binaryPath, "-debug", @@ -84,13 +88,20 @@ def sendCommand(self, vin, command, args=None): if args: command_string.append(args) - result = subprocess.run( + result = subprocess.Popen( command_string, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) - self.sendPrivateKey(vin) - return result.stderr.decode("utf-8") + timer = Timer(self.commandTimeout, result.kill) + try: + timer.start() + stdout, stderr = result.communicate() + finally: + timer.cancel() + + self.closeFile() + return stderr.decode("utf-8") def setChargeRate(self, charge_rate, vehicle=None, set_again=False): ret = self.sendCommand(vehicle, "charging-set-amps", charge_rate) @@ -155,36 +166,25 @@ def scanForVehicles(self): def wakeVehicle(self, vin): self.sendCommand(vin, "wake") - def closeFIFO(self): - os.close(self.pipe) - - def openFIFO(self): - # Open FIFO pipe for passing data to tesla-control - try: - os.mkfifo(self.pipeName) - except FileExistsError: - pass - except OSError as oe: - if oe.errno != errno.EEXIST: - raise + def closeFile(self): + self.pipe.close() + os.unlink(self.pipeName) - self.pipe = os.open(self.pipeName, os.O_WRONLY) + def openFile(self): + # Open output file for passing data to tesla-control + self.pipe = open(self.pipeName, "wb", 0) def sendPublicKey(self, vin): - self.openFIFO() - os.write( - self.pipe, + self.openFile() + self.pipe.write( base64.b64decode(self.master.settings["Vehicles"][vin]["pubKeyPEM"]), ) - self.closeFIFO() def sendPrivateKey(self, vin): - self.openFIFO() - os.write( - self.pipe, + self.openFile() + self.pipe.write( base64.b64decode(self.master.settings["Vehicles"][vin]["privKey"]), ) - self.closeFIFO() def updateSettings(self): # Called by TWCMaster when settings are read/updated