Skip to content

Commit 45a23d1

Browse files
committed
enhancement #380: PIN code based on the serial number is required before sending a command
1 parent c7c2695 commit 45a23d1

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

src/reachy_mini/daemon/app/services/bluetooth/bluetooth_service.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,11 @@ def GetManagedObjects(self):
292292
class BluetoothCommandService:
293293
"""Bluetooth Command Service."""
294294

295-
def __init__(self, device_name="ReachyMini"):
295+
def __init__(self, device_name="ReachyMini", pin_code="00000"):
296296
"""Initialize the Bluetooth Command Service."""
297297
self.device_name = device_name
298+
self.pin_code = pin_code
299+
self.connected = False
298300
self.bus = None
299301
self.app = None
300302
self.adv = None
@@ -314,9 +316,18 @@ def _handle_command(self, value: bytes) -> str:
314316
except Exception as e:
315317
logger.error(f"Error executing command: {e}")
316318
return "OK: System running"
319+
elif command_str.startswith("PIN_"):
320+
pin = command_str[4:].strip()
321+
if pin == self.pin_code:
322+
self.connected = True
323+
return "OK: Connected"
324+
else:
325+
return "ERROR: Incorrect PIN"
317326

318327
# else if command starts with "CMD_xxxxx" check if commands directory contains the said named script command xxxx.sh and run its, show output or/and send to read
319328
elif command_str.startswith("CMD_"):
329+
if not self.connected:
330+
return "ERROR: Not connected. Please authenticate first."
320331
try:
321332
script_name = command_str[4:].strip() + ".sh"
322333
script_path = os.path.join("commands", script_name)
@@ -333,6 +344,8 @@ def _handle_command(self, value: bytes) -> str:
333344
except Exception as e:
334345
logger.error(f"Error processing command: {e}")
335346
return "ERROR: Command execution failed"
347+
finally:
348+
self.connected = False # reset connection after command
336349
else:
337350
return f"ECHO: {command_str}"
338351

@@ -408,12 +421,32 @@ def run(self):
408421
self.mainloop.quit()
409422

410423

424+
def get_pin() -> str:
425+
"""Extract the last 5 digits of the serial number from dfu-util -l output."""
426+
default_pin = "46879"
427+
try:
428+
result = subprocess.run(["dfu-util", "-l"], capture_output=True, text=True)
429+
lines = result.stdout.splitlines()
430+
for line in lines:
431+
if "serial=" in line:
432+
# Extract serial number
433+
serial_part = line.split("serial=")[-1].strip().strip('"')
434+
if len(serial_part) >= 5:
435+
return serial_part[-5:]
436+
return default_pin # fallback if not found
437+
except Exception as e:
438+
logger.error(f"Error getting pin from serial: {e}")
439+
return default_pin
440+
441+
411442
# =======================
412443
# Main
413444
# =======================
414445
def main():
415446
"""Run the Bluetooth Command Service."""
416-
bt_service = BluetoothCommandService(device_name="ReachyMini")
447+
pin = get_pin()
448+
449+
bt_service = BluetoothCommandService(device_name="ReachyMini", pin_code=pin)
417450
bt_service.run()
418451

419452

0 commit comments

Comments
 (0)