MS Teams Status Updater for openHAB

Hi there,

i wanted to get my MS Teams Status into openHAB and use it to inform my wife wether i´m on the phone or not.
So i found this thread and the solution mentioned in the last post.

This is fine but i didn´t liked the fact that i either have a powershell window or no window at all.
The window is a visual indicator wether the script is running or not but takes space in my taskbar.
The no window has no visual indicator and i don´t know if the script is still running.

I searched for a solution to get the powershell script into a service that runs at startup and stops when shutting down the machine. This would also result in two new states that weren´t possible with the script only solution.

I found winsw and gave it a try.
After some trial and error i found a working solution i want to share with you.

What you need?

  • winsw - can be found on Github
  • Powershell ISE - should already be available on Windows 10
  • openHAB - yeah that´s obvious :slight_smile:

What you get!

  • A Windows service that updates an openHAB Item based on your MS Teams status
  • A script that reads the MS Teams logfile to get your status
  • A start and stop message to get more states for openHAB rules

1. Preparing winsw

  • Download the latest version you´re comfortable with (i used the version 3 alpha) as .exe
  • Prepare a folder where the service will work and the scripts will be placed later on
  • I choosed C:\Scripts\msTeamsUpdater
  • Place the downloaded WinSW-x64.exe inside this folder and rename it to something like msTeamsStatusUpdater.exe

2. Creating a config file

  • Start an editor of your choice (e.g. Notepad++) and create a file with the same name your choosed for the winsw.exe and save it at the same path (C:\Scripts\msTeamsUpdater)
  • In my example msTeamsStatusUpdater.xml
  • I used the following config for my service
<service>
  <id>msTeamsStatusUpdater</id>
  <name>openHAB Status Updater for MS Teams</name>
  <description>This service will update an openHAB Item based on your MS Teams status.</description>
  <executable>PowerShell.exe</executable>
  <arguments>-ExecutionPolicy Bypass -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -file C:\Scripts\msTeamsUpdater\Updater.ps1</arguments>
  <log mode="roll"></log>
  <delayedAutoStart>true</delayedAutoStart>
  <poststop>
    <executable>PowerShell.exe</executable>
	<arguments>-ExecutionPolicy Bypass -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -file C:\Scripts\msTeamsUpdater\Startup.ps1 -method Offline</arguments>
    <stdoutPath>NUL</stdoutPath>
    <stderrPath>NUL</stderrPath>
  </poststop>
  <poststart>
    <executable>PowerShell.exe</executable>
	<arguments>-ExecutionPolicy Bypass -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -file C:\Scripts\msTeamsUpdater\Startup.ps1 -method Online</arguments>
    <stdoutPath>NUL</stdoutPath>
    <stderrPath>NUL</stderrPath>
  </poststart>
  <onfailure action="restart" delay="10 sec"/>
  <onfailure action="restart" delay="20 sec"/>
</service>

3. Explanation

  • <id> - needs to be a unique id for your service that isn´t used by any other service on your machine
  • <name> - the display name of your service
  • <description> - a description for your service that will be shown under services.msc
  • <executable> - in this case powershell to run the script that reads the MS Teams logfile
  • <arguments> - this list of arguments is something like a best-practice i found and it contains the path to your powershell scripts
    • In my example it´s the same path as for the service
  • <log mode="roll"> - thiss will create rolling logs with a default of 10MB per logfile and 8 rolling files
  • <delayedAutoStart> - this is very important to get the start message Online as otherwise the service would start too early and isn´t able to send this message
  • <poststart> / <poststop> - these are used to get a start and stop message with Online and Offline
  • <onfailure action="restart" delay="10 sec"/> - this will restart the service 10 seconds after it crashed and the second line will restart it 20 seconds after the second crash
  • More information can be found in the Github repository of winsw

4. The powershell scripts

  • Start the Powershell ISE
    • paste the following line for the first script
    • replace <openHAB-IP-address> with the ip-address of your openHAB instance
    • replace msTeamsStatus with the name of your status item
    • save it as Updater.ps1 in your working directory
Get-Content C:\Users\Michael.Bredehorn\AppData\Roaming\Microsoft\Teams\logs.txt -Wait -Tail 0 | ? { $_ -match "(?<=StatusIndicatorStateService: Added )(\w+)" } | % { if($matches[0] -ne "NewActivity") {& Invoke-WebRequest 'http://<openHAB-IP-address>:8080/rest/items/msTeamsStatus' -Body $matches[0] -Method 'Post' -ContentType 'text/plain' }}
  • Open a new Powershell ISE window
    • paste the following line for the second script
    • replace <openHAB-IP-address> with the ip-address of your openHAB instance
    • replace msTeamsStatus with the name of your status item
param ($method)
Invoke-WebRequest 'http://<openHAB-IP-address>:8080/rest/items/msTeamsStatus' -Body $method -Method 'Post' -ContentType 'text/plain'

5. Preparing openHAB

  • Create a new item with the same name you used in the scripts
  • In my example it´s inside a text based items file called presence.items
String msTeamsStatus "Current State of MS Teams [%s]"
  • You can also work with a .MAP transformation file to make the status more user friendly or translate it to your local language
String msTeamsStatus "Current State of MS Teams [MAP(TeamsStatus.map):%s]"
  • Example for the TeamsStatus.map file
OnThePhone=Telefoniert
InAMeeting=In einer Besprechung
Presenting=Präsentiert
Available=Verfügbar
...

6. Install the service

  • Open a commandline with administrator rights
    • Open the start menu, search for cmd and click on Run as administrator
  • Switch to the directory were you placed the service, the config and your powershell script
    • cd C:\Scripts\msTeamsUpdater
  • Execute the following command to install your service
    • msTeamsStatusUpdater.exe install
  • The commandline should show you a success message
  • Open your services.msc and search for your new service
    • 2021-08-06 19_14_35-Window
  • Open the preferences and start your service
  • Check your openHAB item and if it´s changing to Online
  • Open your MS Teams, try to change the status and see if it´s pushed to openHAB
    • 2021-08-06 19_12_11-Window

7. Control a hue bulb with the new item

  • I´m using a color hue bulb to show the current state and switch the bulb on/off
rule "Teams Status Update"

when

    Item msTeamsStatus changed

then

    val currentState = msTeamsStatus.state

    switch currentState {
        case 'Online': {
            hueStatus_Temp.sendCommand(50) // White
        }
        case 'Available': {
            hueStatus_Color.sendCommand("120,100,100") // Green
        }
        case 'Busy': {
            hueStatus_Color.sendCommand("45,100,100") // Yellow
        }
        case 'DoNotDisturb': {
            hueStatus_Color.sendCommand("45,100,100") // Yellow
        }
        case 'BeRightBack': {
            hueStatus_Temp.sendCommand(50) // White
        }
        case 'OnThePhone': {
            hueStatus_Color.sendCommand("0,100,100") // Red
        }
        case 'InAMeeting': {
            hueStatus_Color.sendCommand("0,100,100") // Red
        }
        case 'Presenting': {
            hueStatus_Color.sendCommand("0,100,100") // Red
        }
        case 'Away': {
            hueStatus_Color.sendCommand(OFF) // Switching Off
        }
        case 'Offline': {
            hueStatus_Color.sendCommand(OFF) // Switching Off
        }
    }

end
  • There might be more states but i wasn´t able to reproduce them alone
    • The out of office states are mixed with the normal status if someone is available and has an active out of office message

kind regards
Michael

3 Likes

Great! Already thought about that.
I think that I need to check, if I have the right permissions to go implement on my business environment.

Yeah that´s a problem for some business environments.
I´m in the happy state to have local administrative rights for my daily work.

It´s the same problem why i couldn´t follow the pull method over Microsft Graph.
My company hasn´t opened the feature for us so i´m not able to use it.
I would rather pull the status from Teams instead of pushing it from my working machine to openHAB.

This is a perfect idea and will solve a lot of my problems :wink:
My problem with this solution is, that my netbook isn´t in my local network. My next idea will be sending an email with this script instead of http request.
Cause I have no experience with Shell Scripts I hope to finde someone who will write me this script.
Joe
edit: my thinking was not really good, because openhab mail binding can only send emails and not read. I´m searching forward, mayby someone has an idea to get the status in openhab without local network or msgraph.

Are you able to reach openHAB from outside of your network?

You bring me on the right direction. I changed

Invoke-WebRequest 'http://<openHAB-IP-address>:8080/rest/items/msTeamsStatus' -Body $method -Method 'Post' -ContentType 'text/plain'

in my adresse

Invoke-WebRequest 'http://USER:PASSWORD@myopenhab.org/rest/items/msTeamsStatus' -Body $method -Method 'Post' -ContentType 'text/plain'

but it doesn´t work.

My error log:

Invoke-WebRequest : Unauthorized
In C:\Scripts\msTeamsUpdater\Updater1.ps1:1 Zeichen:190

  • … Activity") {& Invoke-WebRequest 'https://chri
  •             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
      eption
    • FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
      Invoke-WebRequest : Unauthorized
      In C:\Scripts\msTeamsUpdater\Updater1.ps1:1 Zeichen:190
  • … Activity") {& Invoke-WebRequest 'https://chri
  •             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
      eption
    • FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Maybe someone can help.
Joe

Hi all, so there is the “new Microsoft Teams” now and with this new version there is no Log-File in AppData anymore. Does anyone have an idea where the status is now logged?

Looks like it’s in C:\Users\username\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Logs now. The log file is the MSTeams_ ones. If you search for "availability: " you’ll find the status changes.

1 Like

Thank you, that’s it!
Here is my new Powershell-command to push the current status to OpenHAB:

Get-ChildItem C:\Users\username\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Logs\MSTeams_*.log -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | Get-Content -Wait -Tail 0 | ForEach-Object {if($_ -match 'availability: (\w+)}$') {Invoke-WebRequest 'http://192.168.178.100:8080/rest/items/TeamsMode' -Body $matches[1] -Method 'Post' -ContentType 'text/plain'}}

I start it with a scheduled task after sign-in with a delay of 30 seconds (so that Teams already started and created the newest log file). Maybe it’s useful for somebody else.

1 Like

Unfortunately, the new log isn’t as good as the old one. The “availability” in the log file only shows my own set status. When I get on the phone or if I’m presenting and the status changes automatically, it isn’t logged there. Anyone an idea where to catch this information? I want to switch a light to red when I’m on the phone, so this is the only information I need :smiley:

There’s a much more reliable solution like this available - especially for “new Teams”:

just send the JSON-information to OpenHab and then do some magic there.

for those still on “old Teams”, there’s also a straightforward solution:

here you have to change the webhook within the script, as this one will try to send it to a HomeAssistant instance.

Downside
The only downside I see is in “new Teams” you don’t have access to your “status” as new Teams assumes you have more than one account and you can have multiple accounts with different status. But of course the API offers the most common information: “on the phone”, “webcam on” and “mic muted” (as well as others - see JSON). Perhaps MS is working on not only offering meetingState but multiple accountState information within the API, but not presently.

Okay, that’s pretty cool, thank you! But how do I get the information to OpenHAB? If I use my Rest-API call http://192.168.178.100:8080/rest/items/TeamsMode nothing happens.

Edit: Okay, this tool is also not suitable for me, because it only monitors the current meeting state, but not my Teams-status (Busy, DoNotDisturb etc).

So I need a possibility to read just the “OnThePhone” status out of the logs. Everything else works fine (Away, Busy, DoNotDisturb (what is also Presenting))…

“new Teams” doesn’t allow for the current Teams-Status, only Meeting-Status:

{
  "meetingUpdate": {
    "meetingState": {
      "isMuted": false,
      "isVideoOn": false,
      "isHandRaised": false,
      "isInMeeting": false,
      "isRecordingOn": false,
      "isBackgroundBlurred": false,
      "isSharing": false,
      "hasUnreadMessages": false
    },
    "meetingPermissions": {
 ...
    }
  }
}

I do have a logic with a simple RGB-light:

  • green light => no meeting aka everything false
  • orange light => I’m in a meeting, but no video
  • red light => I’m in a meeting, camera on

That’s enough for me. A lot of meetings don’t last the projected time, so I’m green for my family to enter, even though my “busy” state is “occupied”. But that’s only my use case.

I’m thinking as the webhook is a POST, that the OH-REST doesn’t react to it. For other reasons I set up Node-Red and the webhook POSTs the JSON to a Node there, and Node-Red then sends MQTT, which in turns OH subscribes to for status updates. I guess, you can write a feature request to the author for making the http-request type optional for PUT or POST… He’s kinda responsive!