So I tried this with dcnoren suggestions on my own computer and it is working. Next i tried it on my work computer and no luck. The biggest problem seems to be Constrained Language mode, after I was able to bypass execution policy. I found that using powershell v2 will get around the constrained language mode, as it didn’t exist in v2. But other functions such as get-content -tail wont work as tail was implemented in v3. I didn’t go through all of the command not found exceptions but there seem to be a few.
Anyone get this working in a super restricted environment? No admin rights, can’t run exe, and constrained language mode…
I have a (mostly) working script that runs under AutoHotKey that can pull the status from the log file and send it to a HA webhook. This works without any elevated permissions and can be run by AHK portable (nothing to install).
Key limitation is that I haven’t got it getting the status on initial script load (as it’s just tailing the log). Can work around by toggling the status initially, but welcome someone with better coding skills than I working out how to get the last status on initial load.
I am moving jobs and won’t be using Teams much longer but hopefully this is useful for those like me who can’t get access to the Graph API and who don’t have local admin permissions.
I’m now using a Mac and have moved to using the HA Companion app which can create sensors to show when your mic and camera in use. The only issue is that there is a big with M1 Macs where the camera is currently always showing as on, but the mic sensor works fine
yes i immediately found out about the mac app. i have been using HA for 3 years and did not even know the mac app was launched for a whole year now. this is amazing! the possibilities are endless: i can raise my desk, set the mood lighting etc when i unlock my macbook
I prefer IoTLink because my automation stuff lives in an isolated VLAN and can’t communicate directly with my PC. I was already using it to shutdown my PC, so it made sense to create the Addon and use what was already there rather than create Scheduled Tasks or PowerShell services.
Thanks for doing this. Does this addon constantly poll or check the log file and therefore consume cpu cycles that would impact overall pc performance?
thanks
Its fairly efficient from the small amount of testing I’ve done. The code I used to watch the log file comes from a code snippet called Tail .NET. Essentially it checks the size of the log file every 1 second and if the filesize has changed it only reads the changed data (rather than loading the entire log file which can be quite large). I expect it to consume similar resource as the PowerShell based solutions (which also tail the log file).
maybe someone know what to do …
I`ve try to do it like EBOOZ wrote… instruction looks very easy but got error with last command in PowerShell
PS C:\Scripts> Start-Service -Name "Microsoft Teams Status Monitor"
Start-Service : Service 'Microsoft Teams Status Monitor (Microsoft Teams Status Monitor)' cannot be started due to the
following error: Cannot start service Microsoft Teams Status Monitor on computer '.'.
At line:1 char:1
+ Start-Service -Name "Microsoft Teams Status Monitor"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service],
ServiceCommandException
+ FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand
PS C:\Scripts>
Great idea using the Teams log, that’s exactly what I was looking for. However I came with a different way of extracting the status from Teams, I’m looking for “Setting the taskbar overlay icon”. Here is the Powershell script I created, it works well. I find that querying the log every 5 seconds and grabbing the last 2000 lines is sufficient so far.
Got this working on my work machine.
For anyone wanting to automate this.
Open “Task Scheduler”
“Create Task”
Give it a “Name” and importantly tick “Run with highest privileges”
Triggers tab
a. New
b. Dropdown “Begin task” set to “On log on”
Action tab
a. New
b. “Start a Program”
c. Program/script: “C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe”
d. Add arguments-NonInteractive -WindowStyle Hidden -File "C:\path\to\the\script\on\your\machine\teams_meeting_presence.ps1"
Note: you might need to look for Powershell on your machine with Get-Command powershell.exe from a powershell session.
I got it all working, very nice job of you all !!! (I use the scheduler task to start the script when I boot). But, I have one more question: If reboot Home Assistant, my status is changed to ‘Unknown’ and get changed again when I run the script on my laptop.
Does anyone have a clue on how to ‘update’ the status once HA gets rebooted ?
Well, how long does it take after reboot of HA for the script to send once again the status of my teams agent ? It seems that, unless I manually execute the script, the status will remain on ‘UNKNOWN’
Quick look at the code and it only sends state to HA when there is a change
So in your case, you restart HA but didn’t change Teams state it will show “Unavailable”.
The last script up there runs every 5 seconds so it would send state regardless.
If you change
If ($CurrentStatus -ne $Status -and $Status -ne $null) {
to
If ($Status -ne $null) {
Then it will send status every time the code runs. Or you could get this code to check if the state is unavailable and send an update if so.
Tried to adapt following your remarks, but still my teamsstatus gets an unknown state after reboot of Hass. I think the problem is that the start / sleep functionality doesn’t work somehow to periodically send the status over:
# Configuring parameter for interactive run
Param($SetStatus)
# Import Settings PowerShell script
. ($PSScriptRoot + "\Settings.ps1")
$headers = @{"Authorization"="Bearer $HAToken";}
# Run the script when a parameter is used and stop when done
If($null -ne $SetStatus){
Write-Host ("Setting Microsoft Teams status to "+$SetStatus+":")
$params = @{
"state"="$SetStatus";
"attributes"= @{
"friendly_name"="$entityStatusName";
"icon"="mdi:microsoft-teams";
}
}
$params = $params | ConvertTo-Json
Invoke-RestMethod -Uri "$HAUrl/api/states/$entityStatus" -Method POST -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($params)) -ContentType "application/json"
break
}
If ($env:APPDATA -match "C:\\Users") {
$path = "$env:APPDATA\Microsoft\Teams\logs.txt"
}
Else {
$path = "C:\Gebruikers\bart.weemaels$([char]0X0040)cegeka.be\AppData\Roaming\Microsoft\Teams\logs.txt"
}
# Start monitoring the Teams logfile when no parameter is used to run the script
Get-Content -Path $path -Tail 10000 -ReadCount 0 -Encoding Utf8 -Wait | % {
# Get Teams Logfile and last icon overlay status
$TeamsStatus = $_ | Select-String -Pattern `
'Setting the taskbar overlay icon -',`
'StatusIndicatorStateService: Added' | Select-Object -Last 1
# Get Teams Logfile and last app update deamon status
$TeamsActivity = $_ | Select-String -Pattern `
'Resuming daemon App updates',`
'Pausing daemon App updates',`
'SfB:TeamsNoCall',`
'SfB:TeamsPendingCall',`
'SfB:TeamsActiveCall',`
'name: desktop_call_state_change_send, isOngoing' | Select-Object -Last 1
# Get Teams application process
$TeamsProcess = Get-Process -Name Teams -ErrorAction SilentlyContinue
# Check if Teams is running and start monitoring the log if it is
If ($null -ne $TeamsProcess) {
If($TeamsStatus -eq $null){ }
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgAvailable*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added Available*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: Available -> NewActivity*") {
$Status = $lgAvailable
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgBusy*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added Busy*" -or `
$TeamsStatus -like "*Setting the taskbar overlay icon - $lgOnThePhone*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added OnThePhone*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: Busy -> NewActivity*") {
$Status = $lgBusy
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgAway*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added Away*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: Away -> NewActivity*") {
$Status = $lgAway
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgBeRightBack*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added BeRightBack*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: BeRightBack -> NewActivity*") {
$Status = $lgBeRightBack
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgDoNotDisturb *" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added DoNotDisturb*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: DoNotDisturb -> NewActivity*") {
$Status = $lgDoNotDisturb
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgFocusing*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added Focusing*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: Focusing -> NewActivity*") {
$Status = $lgFocusing
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgPresenting*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added Presenting*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: Presenting -> NewActivity*") {
$Status = $lgPresenting
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgInAMeeting*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added InAMeeting*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added NewActivity (current state: InAMeeting -> NewActivity*") {
$Status = $lgInAMeeting
Write-Host $Status
}
ElseIf ($TeamsStatus -like "*Setting the taskbar overlay icon - $lgOffline*" -or `
$TeamsStatus -like "*StatusIndicatorStateService: Added Offline*") {
$Status = $lgOffline
Write-Host $Status
}
If($TeamsActivity -eq $null){ }
ElseIf ($TeamsActivity -like "*Resuming daemon App updates*" -or `
$TeamsActivity -like "*SfB:TeamsNoCall*" -or `
$TeamsActivity -like "*name: desktop_call_state_change_send, isOngoing: false*") {
$Activity = $lgNotInACall
$ActivityIcon = $iconNotInACall
Write-Host $Activity
}
ElseIf ($TeamsActivity -like "*Pausing daemon App updates*" -or `
$TeamsActivity -like "*SfB:TeamsActiveCall*" -or `
$TeamsActivity -like "*name: desktop_call_state_change_send, isOngoing: true*") {
$Activity = $lgInACall
$ActivityIcon = $iconInACall
Write-Host $Activity
}
}
# Set status to Offline when the Teams application is not running
Else {
$Status = $lgOffline
$Activity = $lgNotInACall
$ActivityIcon = $iconNotInACall
Write-Host $Status
Write-Host $Activity
}
# Call Home Assistant API to set the status and activity sensors
# If ($CurrentStatus -ne $Status -and $Status -ne $null) {
If ($Status -ne $null) {
$CurrentStatus = $Status
$params = @{
"state"="$CurrentStatus";
"attributes"= @{
"friendly_name"="$entityStatusName";
"icon"="mdi:microsoft-teams";
}
}
$params = $params | ConvertTo-Json
Invoke-RestMethod -Uri "$HAUrl/api/states/$entityStatus" -Method POST -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($params)) -ContentType "application/json"
}
If ($CurrentActivity -ne $Activity) {
$CurrentActivity = $Activity
$params = @{
"state"="$Activity";
"attributes"= @{
"friendly_name"="$entityActivityName";
"icon"="$ActivityIcon";
}
}
$params = $params | ConvertTo-Json
Invoke-RestMethod -Uri "$HAUrl/api/states/$entityActivity" -Method POST -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($params)) -ContentType "application/json"
Start-Sleep 5
}
}