I thought it would be interesting, and incredibly useful, to build a device that displays a visual cue when my laptops webcam is turned on. I work from home and I’m in a large amount of video meetings either on Zoom or Google Meet. This handy device helps others in the household know when I’m on a video call without needing to see the screen.
GitHub Repository containing full code

I based my work largely on another great tutorial I found here on medium:
https://edransit.medium.com/an-on-air-sign-with-iot-5bf2f2bc7dc9
The principle is the same, but things are a bit updated and expanded. I needed this to work on both my MacBook and my Linux laptop.
Hardware:
- ESP32 microcontroller
- Neopixel LED strip
- Wooden box
- Translucent Plexiglass (3mm)
- Micro USB cord
- Mosquitto Broker Server
Mosquitto Server:
The original tutorial utilizes an Arduino to run the broker. However, Arduinos are currently like gold because of the chip shortage and are both hard and expensive to find. Since I already have a server at home running TrueNAS, I spun up a broker server there from the community repository.
Checking the camera (Linux):
I’m sure there may be a more efficient way to write this, but I created a quick bash script that checks for a 1 or 0 on the uncvideo output under lsmod.
camera_on=$(lsmod | awk '{print $1,$3}' | grep uvcvideo | awk '{if ($2 == 1) print "true"; else print "false";}')
Once the camera turns on, I publish a message to the broker with the JSON displaying 1 for onair.
mosquitto_pub --topic sensor/camera/laptop -h 192.168.86.245 --message "{\"onair\": 1}"
I setup the script (full code below) to run in a cron job on reboot, continuously checking for the status of the camera.
#!/usr/bin/env bash echo 'Running Script' camera_on=false while : do until [ $camera_on = true ] do camera_on=$(lsmod | awk '{print $1,$3}' | grep uvcvideo | awk '{if ($2 == 1) print "true"; else print "false";}') sleep 2 done mosquitto_pub --topic sensor/camera/laptop -h 192.168.86.245 --message "{\"onair\": 1}" until [ $camera_on = false ] do camera_on=$(lsmod | awk '{print $1,$3}' | grep uvcvideo | awk '{if ($2 == 1) print "true"; else print "false";}') sleep 2 done mosquitto_pub --topic sensor/camera/laptop -h 192.168.86.245 --message "{\"onair\": 0}" done
Checking the camera (MacOS):
The original tutorial utilizes a slightly different check in the log stream. In my version of MacOS, the kCameraStreamStart event simply wasn’t in the logs – so I set out to find what I could utilize.
For my OS – I found the proper log message being displayed for on and off under appleh13camerad. I’m not sure how future-proof this may be, but it works for now.
log stream | grep "ISP_PowerOnCamera: powered on camera" log stream | grep "PowerOffCamera : ISP_PowerOffCamera"
With that knowledge I edited to the final script below and setup a ‘Run Shell Script’ task in Automator to run at login.
#!/bin/bash log stream | awk ' /ISP_PowerOnCamera: powered on camera/ { system("/opt/homebrew/bin/mosquitto_pub --topic sensor/camera/laptop -h 192.168.86.245 --message \"{ \\\"onair\\\": 1 }\"") } /PowerOffCamera : ISP_PowerOffCamera/ { system("/opt/homebrew/bin/mosquitto_pub --topic sensor/camera/laptop -h 192.168.86.245 --message \"{ \\\"onair\\\": 0 }\"") }'
Arduino Source Code
The source code has been modified slightly from the original. The loop will continually check for WIFI and Moquitto connections. If WIFI is lost/connecting then the box will glow Yellow, and if the Mosquitto Broker connection is lost/connecting then the box will glow Blue. The box glows red when the camera turns on.
Project Box Build
The build was straight forward. I found a hollow wooden cube at a craft store and cut it open, drilling out a window and filing until it was smooth. Then I found some 3mm Acrylic/Plexiglass from Amazon that was translucent and cut to shape.




