HOWTO: Turning on and switching off lighthouses with a simple script
Page: 1/2»
  Go to:
scaine Oct 5, 2020
So for the past couple of months, whenever I feel like playing VR, I do a trek around the room, turning on my HMD, then both lighthouses. While I'll still have to manually switch on my HMD, it turns out there's a simple script that takes care of the lighthouses, via bluetooth, it's awesome!

Now, I'm on Manjaro, but I think this will work pretty seamlessly on just about any distro, because it's all installed using pip/python, and in just two simple commands, which we'll later turn into a launcher.

The script we'll be using is this one:
https://gist.github.com/prefiks

But we'll modify it slightly according to one of the comments, so that we can create that launcher for it. One click = lighthouses turn on, click again = lighthouses turn off. Honestly, I've hardly had to use my legs this whole weekend!

Here's the steps for Manjaro, and also Mint, wherever Mint is different.

Step One
If you haven't already, install Python's PIP manager.

Manjaro - pacman -S python-pip
Mint - sudo apt-get install python3-pip libglib2.0-dev

Step Two
Open a terminal and install the dependency for this script
Manjaro - pip install bluepy
Mint - pip3 install bluepy

Step Three
Give yourself rights to run bluepy without sudo:
sudo setcap 'cap_net_raw,cap_net_admin+eip' ~/.local/lib/python3.8/site-packages/bluepy/bluepy-helper
(note that you might have a different path here, for example if you're only on Python 3.7. Just backspace and tab it out to the correct bluepy-helper executable)

Step Four
Download this script, save it somewhere safe, then execute with python:

#!/usr/bin/python3

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)
    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
            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()


I called mine vr.py and I ran it with

Manjaro
python vr.py

Mint
python3 vr.py

You can also force an option with
python3 vr.py on
or
python3 vr.py off
but if you run it without arguments, it's just a toggle.

That's pretty much it. I created a simple launcher, pinned it to my toolbar, and now whenever I click on it, my lighthouses toggle between powered up and powered down.

Hope this helps someone!

Last edited by scaine on 20 October 2020 at 11:03 pm UTC
Corben Oct 5, 2020
I got linked to this gist last week, which is a fork of prefiks lh.py script. But looks like the toggle option got already added in the original.

Haven't tried it myself yet, as when I have to prepare the greenscreen, I can also turn the lighthouses on. And turn them off, when I stow it away again ;)
Julius Oct 5, 2020
One would think (if it is that easy) this function could be added to the SteamVR client... /s

Does it work both with Lighthouse 1.0 and 2.0?
scaine Oct 5, 2020
One would think (if it is that easy) this function could be added to the SteamVR client... /s

Does it work both with Lighthouse 1.0 and 2.0?

I only have the latest lighthouses, so I can't say for certain. But the project is over a year old so... maybe? Hopefully someone can test and report back.
Julius Oct 5, 2020
Ah, I still have the Lighthouse 1.0 so I will try it later today I guess.

Edit: sorry didn't get around doing it, and are now on a longer work related travel. Maybe next month.

Last edited by Julius on 9 October 2020 at 7:17 pm UTC
scaine Oct 5, 2020
I got linked to this gist last week, which is a fork of prefiks lh.py script. But looks like the toggle option got already added in the original.
Yep, but I like the comment-version above, because it gives you both explicit "on" and "off" options!

Haven't tried it myself yet, as when I have to prepare the greenscreen, I can also turn the lighthouses on. And turn them off, when I stow it away again ;)

Pfff. You're not being anywhere near lazy enough.
Ehvis Oct 5, 2020
Nice! It's something I meant to look into, but never bothered with. Now I won't have to . Should hook the script up to auto detect SteamVR so it won't need manual intervention. There are a few other thing I'd want to add to it like setting some Nvidia settings and maybe forcing the sound output (switching is better these days, but it won't always switch back).
scaine Oct 5, 2020
Nice! It's something I meant to look into, but never bothered with. Now I won't have to . Should hook the script up to auto detect SteamVR so it won't need manual intervention. There are a few other thing I'd want to add to it like setting some Nvidia settings and maybe forcing the sound output (switching is better these days, but it won't always switch back).

I have no idea how you'd auto-detect SteamVR starting... but I love the idea of use a pavucontrol command or similar to set/unset the sound sink. I'll have a look into that, definitely.

I wouldn't bother much if Pulseaudio was intelligent enough to choose my previous sound card when I exit SteamVR... but oh no... it choose my Yeti Microsoft "speaker" every goddam time. Pulseaudio really sucks pretty hard, given how old it is now. Nothing is simple and I STILL have to edit a configuration file just to get it to choose my primary sound card on start up!

Switching sound outputs shouldn't be this hard.
Ehvis Oct 5, 2020
I have no idea how you'd auto-detect SteamVR starting... but I love the idea of use a pavucontrol command or similar to set/unset the sound sink. I'll have a look into that, definitely.

SteamVR starts a few processes (vrcompositor and such) that can be detected. Don't have a suggestion right now, but I'm sure there are a few options for detecting when certain processes appear and disappear so you can trigger a script.
scaine Oct 5, 2020
Actually, thinking about it, it's probably easier just to modify the Steam properties launch script to something like

python /path/to/vr.py ; %command%

That works a treat, but of course you still need to execute your vr.py again after closing SteamVR, in order to shutdown the lighthouses again. So a script that detects this stuff would still be pretty cool.

I did try
python /path/to/vr.py ; %command% ; python /path/to/vr.py
but it doesn't work, even with a wait in there, the whole line is executed immediately, because it appears that Steam is forking its games off as a separate process, without waiting for their exit codes.
Blu3ye Oct 9, 2020
Hi there!

I just came here from Twitter and tried that script.
I get no error messages but it doesn't do anything either. Whether I am running SteamVR or not.

HTC Vive on Manjaro Linux.
scaine Oct 10, 2020
Hi Blu3ye. Do you see any output at all? You should see the script finding your lighthouse addresses, then connecting to each in turn:

[scaine@Groovy Misc]$ python vr.py on
Found LightHouse LHB-8EC485F4: address = eb:d5:71:cb:29:0e
Found LightHouse LHB-A3646DA1: address = e4:b7:92:e0:d4:50
Connecting to eb:d5:71:cb:29:0e
Connecting to e4:b7:92:e0:d4:50


If you don't get anything, at all, I can't imagine what the problem might be...

Last edited by scaine on 10 October 2020 at 8:42 am UTC
jens Oct 10, 2020
  • Supporter
I did try
python /path/to/vr.py ; %command% ; python /path/to/vr.py
but it doesn't work, even with a wait in there, the whole line is executed immediately, because it appears that Steam is forking its games off as a separate process, without waiting for their exit codes.

I haven't tested this, but you could try this:
python /path/to/vr.py && %command% && python /path/to/vr.py
scaine Oct 10, 2020
I did try
python /path/to/vr.py ; %command% ; python /path/to/vr.py
but it doesn't work, even with a wait in there, the whole line is executed immediately, because it appears that Steam is forking its games off as a separate process, without waiting for their exit codes.

I haven't tested this, but you could try this:
python /path/to/vr.py && %command% && python /path/to/vr.py

Thanks jens. I'd already tried that, and tried using the `wait` command. But thanks to the way Steam forks off the new game, the whole command is run immediately. It's unfortunate, because this would have been pretty slick otherwise.
jens Oct 10, 2020
  • Supporter
I did try
python /path/to/vr.py ; %command% ; python /path/to/vr.py
but it doesn't work, even with a wait in there, the whole line is executed immediately, because it appears that Steam is forking its games off as a separate process, without waiting for their exit codes.

I haven't tested this, but you could try this:
python /path/to/vr.py && %command% && python /path/to/vr.py

Thanks jens. I'd already tried that, and tried using the `wait` command. But thanks to the way Steam forks off the new game, the whole command is run immediately. It's unfortunate, because this would have been pretty slick otherwise.

mmh, strange, I needed to do something similar with Ferals Tom Raider and ended up with:
nvidia-settings -a AllowFlipping=0 && gamemoderun %command% && nvidia-settings -a AllowFlipping=1
I'm pretty certain that it had worked here. Though I guess you are correct that it has to do with forking a new process, I guess Tomb Raider does not do this.

Did you edited the launch option for a certain game or for SteamVR itself? May be trying one or the other would make a difference.

PS: You could also wrap steam completely into this. I haven't looked, but I guess steam knows command line arguments to start an application (SteamVR) on launch, which would make this somewhat acceptable imho.

Last edited by jens on 10 October 2020 at 2:17 pm UTC
Blu3ye Oct 10, 2020
Hi Blu3ye. Do you see any output at all? You should see the script finding your lighthouse addresses, then connecting to each in turn:

[scaine@Groovy Misc]$ python vr.py on
Found LightHouse LHB-8EC485F4: address = eb:d5:71:cb:29:0e
Found LightHouse LHB-A3646DA1: address = e4:b7:92:e0:d4:50
Connecting to eb:d5:71:cb:29:0e
Connecting to e4:b7:92:e0:d4:50


If you don't get anything, at all, I can't imagine what the problem might be...
No. I don't get any output from the script. It takes appr. 2,5 seconds and while it runs I can see more devices beeing shown in the bluetooth system window. I guess that are just other devices appearing while scanning. I also did connect the base stations just right now but that did not help, either.


Wait... I got one output after repeating the script several times:
Traceback (most recent call last):
  File "/home/marco/vr-lighthouse.py", line 30, in <module>
    scanner.scan(2)
  File "/home/marco/.local/lib/python3.8/site-packages/bluepy/btle.py", line 853, in scan
    self.process(timeout)
  File "/home/marco/.local/lib/python3.8/site-packages/bluepy/btle.py", line 840, in process
    isNewData = dev._update(resp)
  File "/home/marco/.local/lib/python3.8/site-packages/bluepy/btle.py", line 696, in _update
    raise BTLEInternalError("Address type changed during scan, for address %s" % self.addr)
bluepy.btle.BTLEInternalError: Address type changed during scan, for address 40:4e:36:a5:37:a0


I also do have yellow warnings inside SteamVR but I guess that's just "normal" on Linux?!
scaine Oct 10, 2020
Base station power management? That's like if you're running SteamVR via Proton, or on Windows. On Linux, you just get "Bluetooth not available", hence the entire need for this solution/script.

What distro are you on? Are you on the Steam Beta? Are you on the SteamVR Beta? Can you post a screenshot of running the script in your terminal?
Blu3ye Oct 10, 2020
I'm running on Manjaro KDE.
Just installed Steam through Pamac. Installed packages are: steam-manjaro 1.0.0.66-1 and steam-native 1.0.0.62-3.
I do have Proton 5.0.3 globally enabled on the Steam settings but I just Start Steam from Manjaro menu. No betas.


Here's a gif showing it.
scaine Oct 10, 2020
...but there's always output?? I have no idea what's going there. Perhaps try opting into the Steam beta (I am), but there's no need for the SteamVR beta. How do you get to the "Base Station Power Management" screen? Are you just right-clicking on a base station? Or is there another option I'm missing?

I have no idea how to help you here, I'm afraid! Other than KDE, you're running what I was running when I got this working for the first time!
Blu3ye Oct 10, 2020
It´s SteamVR menu button -> Devices -> Base station settings -> Energy management
Like normal for me as it´s the same on Windows. I would not be suprised you didn´t know of this! Many don´t like I read here and there online ^^

What do you mean by "always output"?
When I ran the script, it was always like on the gif. No output at all.
After giving it up and restarting my PC this evening I do get the above posted error every time now. And the lh stations aren´t anymore on the KDE bluetooth manager nor is there any bluetooth device listed anymore.

Restarting on Windows I do have everything working fine though the bluetooth settings inside SteamVR did show some error now. Power reset of Vive fixed this. Have that yellow warning signs on Windows now, too. But base stations power up and down without issues.
jens Oct 11, 2020
  • Supporter
@scaine, I came across this posting for turning the base station on/off with the launch options:
https://github.com/ValveSoftware/SteamVR-for-Linux/issues/207#issuecomment-691535293
While you're here, please consider supporting GamingOnLinux on:

Reward Tiers: Patreon. Plain Donations: PayPal.

This ensures all of our main content remains totally free for everyone! Patreon supporters can also remove all adverts and sponsors! Supporting us helps bring good, fresh content. Without your continued support, we simply could not continue!

You can find even more ways to support us on this dedicated page any time. If you already are, thank you!
Login / Register