[ad_1]
Often, the next occurs…
Son (opens the workplace door): “Dad! the place is my Energy Rangers Dino Cost Beast Saber Sword?”
- Daughter (opens the workplace door): “Dad, the place is the cellphone charger?“.
- Spouse (very softly opens the workplace door): “Only a fast query… are you able to decide up the youngsters later at this time?“.
- Mom-in-law when visiting (opens the workplace door): “What’s the situation with the water strain??” (BTW, there isn’t any situation with the water strain…).
Sure, I did ask them (many instances) to be extra aware/appreciable and examine if I’m on a name earlier than approaching these super-important questions.
Then I requested my son the next:
- Me: “Buddy, you see that I’m working and on a video name. Are you able to wait a bit along with your query?“.
- Son: “However dad! I didn’t know that you just have been in a gathering with the video on…“.
Effectively, he’s proper. He didn’t know that I used to be on a video name. So… How can I “higher educate” my household to know once I’m on a name and like to not be disturbed?
My choices:
Ask once more (and once more) – I’ll try this, however I would like one thing extra speedy…
- Use some bodily indication each time I’m in a gathering (see 👉) – That wouldn’t scale…
- Relocate my workplace area – Then I’ll be far-off from the fridge 😉
- Leverage & combine totally different applied sciences – Sure! 👍
The Plan
Let’s combine Webex (standing indication) with Philips Hue! That approach, they may know (see! 👀) my availability standing!
- Inexperienced == Out there.
- Blue == On a name.
- Orange== On a Webex assembly with video OFF.
- Crimson== On a Webex assembly with video ON.
- Yellow == Asking for quiet time (DoNotDisturb).
Cisco Webex and Philips Hue expose their APIs
As each Webex and Philips Hue expose their APIs, that shouldn’t be difficult. Proper?
Effectively, I discovered two challenges
- Webex Token:
- Webex API requires a legitimate and everlasting token
- The private token is proscribed to 12 hours
- The visitor consumer token can’t entry the “standing” knowledge because it isn’t a part of the group
- The integration token (OAuth grant utilizing a net browser) isn’t relevant for a easy script
- How can I discover out if/when the Webex video is turned on/off throughout a name? 🤔
After some fast analysis, I got here up with the next options
- Create a brand new Webex Bot and leverage its token (which is everlasting and a part of the group).
- Choice #1 – Use this Webex API name. The response returns if the individuals are utilizing video or not. Nonetheless, once I tried that, I all the time acquired “video: off” within the response. I had a fast dialogue with the Webex Dev crew, and so they confirmed it’s a bug (additionally, the API name works ONLY if you’re the assembly host…).
- Choice #2 – Use the macOS “log stream” CLI command to trace when the video is getting used. True, It’s a bit extra difficult, however… price it. (To be taught extra in regards to the “log stream,” examine right here).
The Code (Mac OS solely) 👨💻
To continually tail the Mac OS “log stream” log (to trace if the video is on/off), and on the similar time, run the Webex API code portion, I created a multithreaded python script. One thread is devoted to tail the “log stream”, whereas the second thread is devoted to the Webex API integration code.
Let’s evaluation the code
Step #1 – Import the required python modules.
- requests – Python HTTP library.
- phue – Philips Hue library.
- time – To arrange a sleep assertion.
- Threading & Subprocess – For multithreading.
importrequests
from phue import Bridge
from threading import Thread
from time import sleep
import subprocess
Step #2 – Outline Webex and Philips Hue variables.
- myID – My private Webex ID (examine right here for more information).
- URL – Webex API name to find out my availability standing.
- token – Webex Bot token.
- bridgeIpAddress – Philips Hue bridge IP tackle.
# Webex variables myID = "xxx" url = "https://webexapis.com/v1/individuals/" + myID token = "xxx" # pHue variables bridgeIpAddress = 'x.x.x.x'
Step #3 – Outline the Philips Hue connectivity operate (Be aware: the primary connection would require authentication utilizing: “b.join()”).
def access_lights(bridgeIpAddress): b = Bridge(bridgeIpAddress) # b.join() light_names = b.get_light_objects('identify') return light_names
Step #4 – Outline the 5 availability choices/features.
- The features are relevant for the “Workplace Lightstrip” (you may configure a gaggle of lights as properly).
- on/off – On/Off state of the sunshine.
- hue – The hue worth to set mild to (The hue worth is a wrapping worth between 0 and 65535).
- saturation – Saturation of the sunshine (254 is essentially the most saturated, coloured, and 0 is the least saturated, white).
- brightness – The brightness worth to set the sunshine to (Brightness is a scale from 1, the minimal the sunshine is able to, to 254, the utmost).
def lively():
lights = access_lights(bridgeIpAddress)
for mild in ['Office Lightstrip']:
lights[light].on = True
lights[light].hue = 25500 # Inexperienced
lights[light].saturation = 254
lights[light].brightness = 254
def name():
lights = access_lights(bridgeIpAddress)
for mild in ['Office Lightstrip']:
lights[light].on = True
lights[light].hue = 46920 # Blue
lights[light].saturation = 254
lights[light].brightness = 254
def meeting_without_video():
lights = access_lights(bridgeIpAddress)
for mild in ['Office Lightstrip']:
lights[light].on = True
lights[light].hue = 7000 # Orange
lights[light].saturation = 254
lights[light].brightness = 254
def meeting_with_video():
lights = access_lights(bridgeIpAddress)
for mild in ['Office Lightstrip']:
lights[light].on = True
lights[light].hue = 65535 # Crimson
lights[light].saturation = 254
lights[light].brightness = 254
def DoNotDisturb():
lights = access_lights(bridgeIpAddress)
for mild in ['Office Lightstrip']:
lights[light].on = True
lights[light].hue = 12750 # Yellow
lights[light].saturation = 254
lights[light].brightness = 254
Step #5 – Outline the operate to examine if the is video is on/off.
- The creation of the “output.txt” file was wanted as I used to be unable to (actually) tail the “log stream” course of/output (the “output.txt” file shops the video standing info, which is utilized in step 6). When you have a suggestion for a greater strategy, let me know!
- the complete (unparsed) “log stream” command is: “log stream –information –debug –predicate ‘(course of == “VDCAssistant”) and (eventMessage incorporates “Submit occasion kCameraStream”)’” Study extra in regards to the “log stream” command).
def func1(): f = open("output.txt", "w") subprocess.name(['/usr/bin/log', 'stream' ,'--info', '--debug', '--predicate' , '(process == "VDCAssistant") and (eventMessage contains "Post event kCameraStream")'], stdout=f) return f
Step #6 – Examine the Webex standing indication AND the video standing to find out the Philips Hue mild colour.
- This operate runs on a 5 seconds loop to examine the 8 circumstances.
- print statements have been added for debugging/demo functions.
def func2(): whereas True: sleep(5) headers = { 'Authorization': 'Bearer ' + token } response = requests.request("GET", url, headers=headers) r_json = response.json() myStatus = r_json["status"] with open("output.txt", "r") as file: outcome = (record(file)[-1]) if "kCameraStreamStart" in outcome and myStatus == "assembly": # print("Assembly is ON and Video is ON") meeting_with_video() elif "kCameraStreamStart" not in outcome and myStatus == "assembly": # print("Assembly is ON and Video is OFF") meeting_without_video() elif "kCameraStreamStart" in outcome and myStatus == "lively": # print("Out there") lively() elif "kCameraStreamStart" not in outcome and myStatus == "lively": # print("Out there") lively() elif "kCameraStreamStart" in outcome and myStatus == "name": # print("On a Name") name() elif "kCameraStreamStart" not in outcome and myStatus == "name": # print("On a Name") name() elif "kCameraStreamStart" in outcome and myStatus == "DoNotDisturb": # print("DoNotDisturb") DoNotDisturb() elif "kCameraStreamStart" not in outcome and myStatus == "DoNotDisturb": # print("DoNotDisturb") DoNotDisturb() if __name__ == '__main__': Thread(goal = func1).begin() Thread(goal = func2).begin()
The Demo 🎥
Remaining ideas
BTW, over the weekend, I discovered one other (humorous) answer 👇 😉
Associated assets
We’d love to listen to what you assume. Ask a query or depart a remark beneath.
And keep related with Cisco DevNet on social!
Twitter @CiscoDevNet | Fb | LinkedIn
Go to the brand new Developer Video Channel
[ad_2]