Recently my colleague Nikola shared a blog post about how he came up with a setup to indicate whether he is in a meeting or not. I too face the same problem and wish for an indicator to let my family know I’m in a meeting or not. Let’s see how I came up with a similar setup with a BBC micro:bit.

Meeting Status Indicator using BBC micro:bit

Hardware

First, I began searching for On-Air lights that I can control remotely (Smart Light?). But I couldn’t find any in Amazon India. I found some neon lights but they are not controllable. I can control its power through an Arduino controlled relay, but I want to start with a simple solution, preferably with components that I already have. I have an unused BBC micro:bit lying around which I bought for my sons. The micro:bit has a 5x5 LED array and it can be controlled from the desktop quite easily. So I decided to use the micro:bit as my meeting status indicator.

BBC micro:bit

Micro:bit Code

The micro:bit needs to turn on/off the LED array based on desktop instruction. The micro:bit can receive the desktop instruction through its serial port.

instruction = ""
basic.clear_screen()

def on_forever():
   global instruction
   instruction = serial.read_string()
   if instruction == "1":
       basic.show_leds("""
           # # # # #
           # # # # #
           # # # # #
           # # # # #
           # # # # #
           """)
   elif instruction == "0":
       basic.clear_screen()

basic.forever(on_forever)

The micro:bit code for the functionality is straightforward. In a forever-loop, the micro:bit reads a string from (usb)serial port and turns on the LED array if the string is “1” and turns off the LED array if the string is “0”. The string can be empty too, it does nothing(maintains the state) in that case.

Meeting Detection

My primary meeting application is Google Meet. To detect an ongoing meeting, I thought I could check for the presence of Google Meet network connections on my desktop. Despite Google having a fixed IP/port range for Google Meet, I couldn’t find any connection with the IP/port range when I’m connected with a meeting.

So I was thinking of an alternate solution and wondered why not detect the use of the system’s input audio device/microphone to detect an active meeting. A quick search on the Internet and this StackOverflow post shows how the audio device’s proc file-system can be used to determine the usage status. I thought this approach mightn’t work if we are muted in a meeting. But turned out the mute happens on the software level and the microphone is in use even on muted meetings. This approach also makes the overall solution application neutral as it can work with any meeting application.

NOTE: The same approach won’t work with camera usage. Camera is not in use when the video is turned off in meetings.

Desktop Script

I wrote a Python script to detect the use of input audio devices/microphones and instruct the micro:bit to turn on/off the LED array.

import os
import pathlib
import serial
import time


MICROBIT_SERIAL_DEVICE_FILE = "/dev/ttyACM0"

def is_microphone_in_use():
   for root, _, files in os.walk("/proc/asound"):
       for file in files:
           if file == "status":
               status_text = pathlib.Path(root, file).read_text()
               if status_text.strip() != "closed":
                   return True
   return False

if __name__ == "__main__":
   microbit_serial = None
  
   indicator_on = False
   update_indicator = False
   while True:
       if os.path.exists(MICROBIT_SERIAL_DEVICE_FILE) and not microbit_serial:
           microbit_serial = serial.Serial(MICROBIT_SERIAL_DEVICE_FILE, 115200, timeout=1)
           update_indicator = True
       elif not os.path.exists(MICROBIT_SERIAL_DEVICE_FILE) and microbit_serial:
           microbit_serial.close()


       if is_microphone_in_use() and not indicator_on:
           print("microphone is in-use")
           indicator_on = True
           update_indicator = True
       elif not is_microphone_in_use() and indicator_on:
           print("microphone is not in-use")
           indicator_on = False
           update_indicator = True


       if microbit_serial and update_indicator:
           data = (1 if indicator_on else 0)
           print(f"writing {data} to microbit serial")
           microbit_serial.write(f"{data}".encode("ascii"))
           update_indicator = False
      
       time.sleep(5)

The script opens the (usb) serial port and writes the string “1” if it finds any of the system input devices/microphones being in use, and writes “0” if not being in-use. The script maintains the indicator status to avoid writing the string repeatedly. Each iteration of usage check happens in a 5 seconds (arbitrary) interval.

Manual Override

I realised that there might be times when I want to turn on the micro:bit LED array manually, regardless of the meeting status. This manual override would be useful when I want to focus on something and not be disturbed. So I extended the micro:bit code to use Button A and Button B for manual control of the LED array’s on function.

def on_button_pressed_a():
   global manual_on
   manual_on = 1
input.on_button_pressed(Button.A, on_button_pressed_a)


def on_button_pressed_b():
   global manual_on
   manual_on = 0
input.on_button_pressed(Button.B, on_button_pressed_b)


instruction = ""
manual_on = 0
basic.clear_screen()

def on_forever():
   global instruction
   instruction = serial.read_string()
   if manual_on == 1 or instruction == "1":
       basic.show_leds("""
           # # # # #
           # # # # #
           # # # # #
           # # # # #
           # # # # #
           """)
   elif instruction == "0":
       basic.clear_screen()

basic.forever(on_forever)