Skip to content

Instantly share code, notes, and snippets.

@waylonflinn
Forked from prefiks/lh.py
Last active December 20, 2020 21:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waylonflinn/d525e08674ec3abb5c98cd41d1fd2f24 to your computer and use it in GitHub Desktop.
Save waylonflinn/d525e08674ec3abb5c98cd41d1fd2f24 to your computer and use it in GitHub Desktop.
Valve Index Lighthouse Control Script for Linux (Might Work on Windows Too)
#!/usr/bin/python3
# Usage:
#lh.py on
#lh.py off
# with no arguments, state will be toggled (off -> on, on -> off)
#lh.py
from bluepy import btle
import sys
class DiscoLH(btle.DefaultDelegate):
def __init__(self):
self.devices = []
btle.DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
if not isNewDev:
return
isLH = False
name = ""
v = dev.getValue(btle.ScanEntry.MANUFACTURER)
if v is not None and v[0:4] == b'\x5d\x05\x00\x02':
print('Found LightHouse %s: address = %s' %
(dev.getValue(btle.ScanEntry.COMPLETE_LOCAL_NAME), dev.addr))
self.devices.append(dev.addr)
if __name__ == '__main__':
scanner = btle.Scanner()
delegate = DiscoLH()
scanner.withDelegate(delegate)
scanner.scan(2)
current = None
for device in delegate.devices:
lh = btle.Peripheral()
print("Connecting to %s" % (device))
lh.connect(device, addrType = btle.ADDR_TYPE_RANDOM)
if len(sys.argv) > 1 and sys.argv[1] == 'on':
lh.writeCharacteristic(0x12, b'\x01')
elif len(sys.argv) > 1 and sys.argv[1] == 'off':
lh.writeCharacteristic(0x12, b'\x00')
else:
# toggle
if current == None:
# only query one device state, to sync devices
current = lh.readCharacteristic(0x12)
if(current) == b'\x00':
# turn on
lh.writeCharacteristic(0x12, b'\x01')
else:
# turn off
lh.writeCharacteristic(0x12, b'\x00')
lh.disconnect()
@waylonflinn
Copy link
Author

waylonflinn commented Aug 29, 2020

Modifies @prefiks original code to toggle the lighthouse state, when no argument is specified.
That is, this change will turn the lighthouse off when it's already on, and on when it's already off.

In Ubuntu, I also put the following in a file named lighthouse.desktop on my desktop and click it when I want to turn them on or off. Make sure to edit the line Exec=/path/to/lh.py with the actual path.

[Desktop Entry]
Version=1.0
Name=LightHouse
Comment=Turn Index Lighthouses On/Off
Exec=/path/to/lh.py
Icon=scanner
Terminal=false
Type=Application
Categories=Utility;Application;

Also, make sure to set chmod u+x on both the .desktop file and lh.py.

To set permissions correctly I also had to do the following:

sudo setcap cap_net_raw+e /home/waylonflinn/.local/lib/python3.8/site-packages/bluepy/bluepy-helper
sudo setcap cap_net_admin+eip /home/waylonflinn/.local/lib/python3.8/site-packages/bluepy/bluepy-helper

modify the path above to point to your installation of bluepy-helper

Fix is from here: IanHarvey/bluepy#313

@MartnIV
Copy link

MartnIV commented Dec 2, 2020

Hi Waylonfinn,

Is there any way to act only on one or multiple lighthouses instead all of them?
i have two zones here and I would like to toggle one of the other zone but not both at same time.

@waylonflinn
Copy link
Author

@MartnIV

If you know python, you should be able to play around with the code and identify which bluetooth addresses correspond to devices in each zone. Line 37 loops over all the found addresses. After you know which address corresponds to which physical device, make two lists of addresses, one for each zone. Then, rewrite the script so that it only includes devices if they have an address from the zone you want to activate. You can do that by modifying the loop on Line 37. Rather than looping over all delegate.devices on Line 37 you would loop over the list of addresses for the zone you want to control. You probably want to add a command line argument for selecting the zone as well.

Making physical changes to the devices in your space will require that you manually change the addresses, since they will be hard coded.

Hope that helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment