Microsoft Teams Status

I think it would be a good idea to add parameter functionality to the orignal script, so you can run it with -Status “”.

When this has been added, you can run it when a shutdown EventID is logged:

I’ll start working on it later today :slight_smile:

I was thinking way to complex. I’ve added a check to see if Teams is running or not, and start monitoring the log if it is. Otherwise the status is set to Offline. This solves the issue the status showing incorrect when the computer is shutdown.

I’ve added some other improvements as well, which have been updated at Github.

1 Like

First off thank you! This is awesome and exactly what I needed to control lighting in my office. I prefer to work without lights on but when doing a video call I need the lights on. This allows me to automate based on my activity. Really appreciate this creativity!!

1 Like

A guy did this:

Any Webex Teams users reading. I have opened a PR for this feature in Home Assistant core.

Regarding th token: any user can generate a new token for this at developer.webex.com

I went the Powershell route here and I think my code is quite optimized: it requires only one line and works flawlessly!

Get-Content $env:APPDATA\Microsoft\Teams\logs.txt -Wait -Tail 0 | ? { $_ -match "(?<=StatusIndicatorStateService: Added )(\w+)" } | % { if($matches[0] -ne "NewActivity") {& "C:\Scripts\TeamsColor.ps1" $matches[0] }}

Get-Content -Wait -Tail 0 retrieves every line of the Teams log file, waits for new lines, while ignoring previous content of the file. These lines are then fed into a regex match filter. (After multiple tries, I found that this filter works best, as it still reports the updated status on top of a NewActivity status. It retrieves a single word after the matched expression.) For each matched object that is not NewActivity, another script (TeamsColor.ps1) is called with the status as argument.

This second script calls the HomeAssistant API at
/api/states/sensor.teams_raw with the state passed as argument:

$newval = [Convert]::ToString($args[0])

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer your_bearer_code")
$headers.Add("Content-Type", "application/json")

$body = "{`"state`": `"$newval`"}"

$response = Invoke-RestMethod 'https://your_domain/api/states/sensor.teams_raw' -Method 'POST' -Headers $headers -Body $body

This might not be necessary depending on your needs, but I also created a second template sensor sensor.teams which allow me to easily customize the displayed values from the raw values sent to HA:

sensor:
  - platform: template
    sensors:
      teams:
        friendly_name: "Microsoft Teams"
        unique_id: sensor.teams
        value_template: >-
            {% if states("sensor.teams_raw") in ["Available"] %}
              Available
            {% elif states("sensor.teams_raw") in ["DoNotDisturb","Presenting","Focusing"] %}
              Do not disturb
            {% elif states("sensor.teams_raw") in ["Busy","OnThePhone","DoNotDisturb","Presenting","Focusing","InAMeeting"] %}
              Busy
            {% elif states("sensor.teams_raw") in ["Away","BeRightBack"] %}
              Away
            {% else %}
              {{ states("sensor.teams_raw") }}
            {% endif %} 

Finally, I simply created an automation that is based on the sensor.teams_raw status:

- id: '1608509876133'
  alias: Update status light with Teams
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.teams
  condition: []
  action:
  - service: light.turn_on
    data:
      entity_id: light.statuslamp
      rgb_color: '{% if states("sensor.teams_raw") in ["Available"] %} [146, 195,
        93] {% elif states("sensor.teams_raw") in ["DoNotDisturb","Presenting","Focusing"]
        %} [255, 30, 50] {% elif states("sensor.teams_raw") in ["Busy","OnThePhone","DoNotDisturb","Presenting","Focusing","InAMeeting"]
        %} [255, 30, 50] {% elif states("sensor.teams_raw") in ["Away","BeRightBack"]
        %} [252, 209, 22] {% else %} [0, 0, 0] {% endif %}
        '
    entity_id: light.statuslamp
  mode: single

In addition to a sleep/shutdown scheduled script, I am also going to add a simple ping sensor as a condition for the lights, that pings my work laptop every 10 seconds or so to determine if it is online. Low tech, but I expect it to work quite nicely. Note that the Teams status sets itself to Away before putting the computer to sleep anyway, and depending on your purpose, that could be enough by itself!

Here is a small video demonstration: https://youtu.be/8kBtrowtfmk. I can provide more details if you are interested!

8 Likes

That looks great. Can you indeed share more details, also for the TeamsColor.ps1 script?

I updated my original post with more detail. :smile:
Do not hesitate if you have any further questions!

1 Like

Thanks. How are you automatically running the first script? Are you using NSSM for that?

I’m using the Windows Task Scheduler for the moment. I scheduled my script to be launched at logon as SYSTEM, so that the console is hidden. The whole thing is completely invisible and works fine, so I don’t see the point of doing anything else! :stuck_out_tongue:

1 Like

This is a great solution!

It works fine for me when I run the ps1 manually, but via Windows Task Scheduler not so much.
Also when I run the task manually from Windows Task Scheduler, it does not work.

Could you share how you set it up?

I am using the following parameters to the powershell command in the task scheduler.

-noprofile -executionpolicy bypass -windowstyle hidden -file c:\Scripts\GetTeamStatus.ps1

This way the Powershell windows closes automatically. I also added the second command because otherwise my laptop didn’t execute the TeamsColor.ps1 script due to execution policies for local scripts.

@Egglestron it is working great and is really fast. Thanks again for sharing this solution :smiley:

3 Likes

I’ve just something similair as well, I use IOTLink for that.
IOTLink provides a idle seconds sensor for your laptop. I convert this to a laptop active/inactive sensor like this:

automation:
  - alias: 'Set personal laptop active based on idle time'
    initial_state: true
    trigger:
      platform: template
      value_template: '{{ (states.sensor.desktop_system_idle_time.state | int < states.input_number.win10_laptop_inactive_timout.state | int * 60) and states.sensor.desktop_system_idle_time.state != "unavailable"}}'
    condition:
      condition: state
      entity_id: input_boolean.win10_laptop_active
      state: 'off'
    action:
    - service: input_boolean.turn_on
      entity_id: input_boolean.win10_laptop_active

  - alias: 'Set personal laptop inactive based on idle time'
    initial_state: true
    trigger:
      platform: template
      value_template: '{{ (states.sensor.desktop_system_idle_time.state | int > states.input_number.win10_laptop_inactive_timout.state | int * 60) or states.sensor.desktop_system_idle_time.state == "unavailable"}}'
    condition:
      condition: state
      entity_id: input_boolean.win10_laptop_active
      state: 'on'
    action:
    - service: input_boolean.turn_off
      entity_id: input_boolean.win10_laptop_active

I then use this automation to turn off the indicator light:

automation:
  - alias: Update status light when work PC inactive
    description: ''
    trigger:
    - platform: state
      entity_id: input_boolean.win10_work_laptop_active
      to: 'off'
    action:
    - service: light.turn_off
      entity_id: light.statuslamp
    mode: single

IOTLink looks very interesting for my personal computer!
Unfortunately, I don’t have administrator rights on my work computer… Thus, for me, a ping binary_sensor works best for the Teams status.

Regarding the automation of the script, I have a startup.bat file in which I added this line:

:: Other commands
START pwsh -Command "& C:\Scripts\TeamsStatus.ps1"

As stated before, this bat file is launched as the SYSTEM user, with the trigger “At log on of any user”.

1 Like

Hi @EBOOZ
I hacked your powershell so it can deal with rapid update changes by only looking at the very last presence update. I chose to only look for the string “Setting the taskbar overlay icon”, but maybe that’s limiting me somehow. Seems to work ok, I use MQTT to update HA and have ordered a Unicorn mini HAT for a Pi Zero WH to create my status lamp (this will listen to an MQTT topic that HA will be in control of, turning lamp off when outside of working hours etc)
What do you think ?

DO {

$fileContents = Get-Content -Path “C:\Users\zzzz\AppData\Roaming\Microsoft\Teams\logs.txt” -Tail 100
$lineNum = (($fileContents | Select-String ‘Setting the taskbar overlay icon’)[-1].LineNumber) - 1
$TeamsLog = $fileContents | Select -Index $lineNum

If ($TeamsLog -like “Available”) {
$TeamsStatus = “Available”

}
ElseIf ($TeamsLog -like “Busy”) {
$TeamsStatus = “Busy”

}
ElseIf ($TeamsLog -like “Away” -or $TeamsLog -like “Be Right Back”) {
$TeamsStatus = “Away”

}
ElseIf ($TeamsLog -like “Do not disturb”) {
$TeamsStatus = “Do not disturb”

}
ElseIf ($TeamsLog -like “In a meeting” -or $TeamsLog -like “InAMeeting”) {
$TeamsStatus = “In a meeting”

}
ElseIf ($TeamsLog -like “On the phone”) {
$TeamsStatus = “In a call”

}
ElseIf ($TeamsLog -like “ain window” -or $TeamsLog -like “Offline”) {
$TeamsStatus = “Offline”

}

If ($CurrentState -ne $TeamsStatus) {
$CurrentState = $TeamsStatus
Write-Host $CurrentState

 $app = "C:\Program Files\mosquitto\mosquitto_pub.exe" 
 $arg1 = "-h 10.10.10.10 -u user -P password -t teams/presence -m ";
 $arg2 = $CurrentState;
 $arg=$arg1+"""$arg2"""
 Start-Process $app -ArgumentList $arg

}
Sleep 2
} Until ($Enable -eq 0)

So, seeing as the HACS o365 addon already figures out all of the login an token stuff.

I’ve made this PR on the underlying library to allow fetching your teams status.

Now I just need it to be merged…

4 Likes

@EBOOZ, Brilliant work. Thanks so much for this, will come in very handy for informing the family. I’ve been waiting for something like this.

1 Like

Maybe you were using an old version of the script. Selecting only the last line that matches the search string has been implemented a while ago:

$TeamsStatus = Get-Content -Path "C:\Users\$UserName\AppData\Roaming\Microsoft\Teams\logs.txt" -Tail 100 | Select-String -Pattern `
  'Setting the taskbar overlay icon -',`
  'StatusIndicatorStateService: Added' | Select-Object -Last 1
# Get Teams Logfile and last app update deamon status
$TeamsActivity = Get-Content -Path "C:\Users\$UserName\AppData\Roaming\Microsoft\Teams\logs.txt" -Tail 100 | Select-String -Pattern `
  'Resuming daemon App updates',`
  'Pausing daemon App updates',`
  'SfB:TeamsNoCall',`
  'SfB:TeamsPendingCall',`
  'SfB:TeamsActiveCall' | Select-Object -Last 1

You should not forget to include your search with StatusIndicatorStateService: Added, because otherwise the status won’t be updated when the icon in the taskbar has a NewActivity badge on it (like 1 new message, mention, etc.).

You can download the latest version at: https://github.com/EBOOZ/TeamsStatus

Do you know if this one supports refresh-tokens? My previous attempt to get this up and running failed because my token expired and didn’t refresh. This was a known REST-API in HA at that moment.

@Mey Any idea when this will get merged?