Zoom Meeting Monitoring to HA

Preview

Recorded in real time!
2020-11-18 11.46.11

Note

This is not a turn-key solution, but it should get the grey matter thinking about your own meeting presence solution!

What?

With the whole WFH climate, I simply wanted to detect when I was in a Zoom meeting so I could push a notification and an LED change

Why?

To let family know I wasn’t available to speak or so they can reduce noise.
Also, to wear pants when entering the office …

Setup

Computer/OS: MacBook Pro/Catalina
Languages: Python, Bash
Applications: Zoom, BitBar, MQTT

How?

I did a random probe on ps in the terminal and discovered that the zoom process creates a child which declares the meeting ID (silly idea) only when you are in a meeting, so running filter for:

ps x | grep -E "\-key [0-9]{10,10}"

returns:

your.user     53663   0.0  0.1  4454492  12204   ??  S    12:20pm   0:00.08 /Applications/zoom.us.app/Contents/Frameworks/cpthost.app/Contents/MacOS/CptHost -pid xxx -evtname CptHostxxx-key 0000000000

When there is no meeting, you simply get (on ps x):

your.user     67658   0.0  0.1  4465672  14048   ??  S    11:01am   0:00.26 /Applications/zoom.us.app/Contents/Frameworks/caphost.app/Contents/MacOS/caphost -pid xxx -evtname caphostxxx -key rpc

Python Script

With this info, I wrote a quick Python application to monitor for this case and publish out to MQTT:

import subprocess
import paho.mqtt.client as mqtt
#import time

mqttBroker ="xxx.xxx.xxx.xxx"

client = mqtt.Client("Zoom_Meetings")
client.connect(mqttBroker)

# Keep 'while True' and 'time.sleep()' if this script needs to loop

#while True:
p1 = subprocess.Popen(['ps', 'x'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "-E", "\-key [0-9]{10,10}"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()

output = p2.communicate()[0]

if output:
    code = output.split()[-1].decode()
    print("Meeting ID:", str(code))
    client.publish("home/person/xxx/meeting_status", "ON")
else:
    print("Avail.")
    client.publish("home/person/xxx/meeting_status", "OFF")

# time.sleep(5)

BitBar Integration

In my case, I have BitBar which allows me to put anything I can script into my status bar, so I leveraged that to poll every 5 seconds.
But this could easily be replaced with allowing the Python script above loop to check.

In case anyone else wants to replicate this on BitBar:

#!/bin/bash

# <bitbar.title>Zoom Meeting Status</bitbar.title>
# <bitbar.version>v1.0</bitbar.version>
# <bitbar.author>fanuch</bitbar.author>
# <bitbar.author.github>fanuch</bitbar.author.github>
# <bitbar.desc>Simply run a Python script to detect an active meeting</bitbar.desc>

pythonenv="/Users/your.user/Documents/Code/Python/ZoomMonitor"
script="main.py"

$pythonenv/venv/bin/python $pythonenv/$script

Not that is is needed, but I get a nice little status with BitBar
image

Comments, questions, criticisms welcome.
Just note that I whipped this up in 30 minutes and it serves its intended purpose.

4 Likes

Are you aware of this component?


I think your method has the benefit that it does not require setting up a Zoom app.
1 Like

I wasn’t!
This was one of those “what if I can detect Zoom meeting?” through to completed PoC.

Couple of other benefits:

  • This is local only
  • Some organisation prevent creation of “apps” (I.e I can’t create Slack apps without approval)

I like how that one would cover all devices with one flow; if I needed to take a meeting on mobile phone or something.
I am impressed reading though that component, that’s exactly what I originally wanted accomplish!

1 Like

My organization limits this, but I can still create oauth2 which is the one that works.

Zoom meeting IDs can also be 9 digits, so that line needs to use

p2 = subprocess.Popen(["grep", "-E", "\-key [0-9]{9,10}"], stdin=p1.stdout, stdout=subprocess.PIPE)

instead.

Nonetheless, I love this solution, it’s much better than all of those that need your HA installation be internet accessible.

Even better solution if you are using multiple conferencing solutions:

That just works on Windows, unfortunately.

1 Like

Not true. You can download the .Net runtime on any OS.

Thanks for sharing that link.
I agree that it’s a better solution as it’s conference solution agnostic.

I wish it was on Linux and perhaps the ability to monitor from a gateway (such as a router or FW; could then use this for anyone in the house-hold so long as you know the device IP per user)

Note:

RTC-Call-Monitor requires that your console has elevated privileges in order to monitor network traffic.

Any half decent IT would be restricting elevated access to a managed work machine

Haven’t looked at the code but surely there are some Windows API calls that will not translate to Linux :roll_eyes:

edit: How do you think Microsoft.Extensions.Logging will fair on Ubuntu? :stuck_out_tongue:

I am sure you could comment out the logging or make some other minor modifications to the code and get it working fairly quickly. At least there is a great starting point for those who do not use Windows. Of course the best solution would be to use Windows and have an Ubuntu VM running for your Linux needs. :wink:

As for a gateway that would be great too but you would need to manage/monitor all the workstation(s) in your environment. I use conferencing both on my phone and my laptop. I don’t want automations happening using my phone but that could be resolved through a gateway configuration.

Not going to open that can of worms …

Part of a solution which isn’t on a client would definitely have whitelisting or blacklisting very quickly.

I don’t think you’ve seen the code if you’re saying only a “minor modification” is required to make it portable

@fanuch I wrote the app to be cross platform, and it does run on Linux. There is a permissions issue that I haven’t sorted out yet. I still can’t do network packet inspection even running via sudo. I don’t use my Ubuntu install as my primary OS so I haven’t looked into it any further, but it would be great for someone to create a PR for how to solve the permissions issue.

Microsoft.extensions.Logging works fine on any Linux system, and I use it in our production .net core apps.

Today I learned …

I’ll give it a test. Thanks for your work!

1 Like

this command works well over ssh and Linux, I know is very static and limited but gets the job done.

DISPLAY=:1 XAUTHORITY=$(ls /run/user/1000/xauth_*)  wmctrl -lv 2>/dev/null | grep 'Zoom Meeting' >/dev/null 2>&1 && echo 1 || echo 0