Using the Luxafor Flag and a Raspberry Pi Zero W as a Teams Status Light
When working in an open office, how do you avoid being interrupted so often? Pre-COVID I got a Luxafor Flag as a way to indicate to my coworkers when I was busy. The Luxafor did great for this when paired with my Elgato Stream Deck. With the tap of a button on the Sream Deck, I could show whether I was busy or open to interruptions.
But then COVID hit and I was working from home full time. Our company made the switch from Slack to Microsoft Teams and now I had a new set of co-workers. The rest of my family. Like many people, for the first part of COVID, I spent my time working at a desk out in the open. That was fine, but distracting. As I started to realize I wasn’t going to be back in the office any time soon, I made the move into a different room of my house. But my co-workers (my kids), weren’t very familiar with how many meetings I was in during the day. I still had that Luxafor Flag, so I decided to put it to use.
Just like at work, I placed the Luxafor Flag on the top of my monitor and controlled the color using the Stream Deck. This iteration didn’t last long because I kept forgetting to set my status when I was in meetings and my kids still had to open the door to see if I was busy or not.
Since my company move to Microsoft Teams full time, I researched if I could get my Teams Status through the Teams client. Unfortunately, there doesn’t appear to be any local way to get status from Teams. Luckily, Microsoft had recently added Teams Presence into the Graph API. I now had my way to get my status in Teams.
I’ve been programming in .NET for over 10 years, so my first attempt was to write a .NET Core application to interact with the API. Aside from my level of comfort with C#, I assumed that Microsoft would likely have a good library for the Graph API. And while that was true, I ran into a snag.
The Luxafor has an API so you can write your own integrations to using the device. The API is implemented by exposing the Luxafor Flag as a USB HID device. My primary work laptop is a Mac. So how could I talk to the Luxafor over USB HID? I did some research but didn’t find either a Luxafor library in C# that ran on macOS or an easy to use library for interacting with the Luxafor over USB HID. And while I’m still interested in learning how to communicate with the Luxafor by USB HID myself, that wasn’t what I was trying to do. So I began my search in other languages.
I found the busylight-for-humans package in Python and it fit the bill perfectly. I’m not a particularly great Python developer, but I’ve been using Python much more recently so I’m familiar enough to know I could write my app in Python without a major struggle.
It took a few days for me to get a good handle on both how to connect my Python app to the Graph and then how to navigate the Graph API itself. But once I did, I had a script that I could run in the background that would poll my Teams status every 5 seconds and update itself based on my status. Which you can see in the example below:
Great! Now all I need is a very long USB cable to stretch from my computer to the outside of the door.
That very long USB cable prompted me to look elsewhere since I couldn’t find a cable long enough. Instead, I dug out one of my old Raspberry Pi Model B’s that I have floating around. They are original B’s so they are very slow. After re-flashing my SD card with a current Raspberry Pi OS, I pulled down my source code and tried to run pipenv install.
Pipenv immediately yelled at me saying I didn’t have Python 3.9, since that’s what I had on my Mac when I wrote the app. After checking, I realized that the Raspberry Pi OS updates rather slowly and still hadn’t included Python 3.9, or even 3.8! Instead of trying to get Python 3.9 running, I modified my Pipfile and tried installing. Still no luck. It was struggling with all the dependencies it needed. Instead of working to resolve the issues, I decided to pip install every dependency I needed, and it worked! After a few more steps with busylight-for-humans, I was able to get my Python app running and pulling my Teams State. Now I could place the Raspberry Pi outside my room.
After I got settled on the Raspberry Pi B, I got an itch to condense the package a bit and see if I could make it into something I could eventually stick to the wall. The Raspberry Pi B was just kind of sitting on a box and I wanted to improve how it looked a bit.
Of course, this gave me a chance to hit up Adafruit and buy a few things! I got a Raspberry Pi Zero W, a case, and an Adapter. Once those arrived, I was ready to get the Pi Zero W set up!
Instead of hacking the script like I had originally. I wanted to get it working out of the box. After running into a few hurdles with the Raspberry Pi — I learned I have a micro-HDMI cable, not a mini-HDMI plug the Pi Zero uses. The Pi was set up and ready to go.
Now the finished package is considerably smaller, actually stored in source control, and able to run from outside my office door. Here’s a picture of it mounted next to my door:
I plan on cleaning up the cables a bit and mounting the Pi better, but I’m happy with the results and I’ll see how well it works out!
I’ve made my GitHub repo public in case people are interested in using the code. Since I wrote this post, I’ve changed jobs and I’m not actively using the code. Fork the code and make it your own! If you end up using this code or modifying it, let me know on Twitter! Thanks to @TheNoname for asking if I could publish the code, otherwise I would’ve likely kept it private since I’m a little self-conscious of the code quality.