Working from Home – Teams Availability

In this post I am going to explain how I make my status in Microsoft Teams running on my work laptop available in Home Assistant.

I have been working from home for more than six months now and have my work area in a fairly good and functional shape now – large desk, comfy chair, second monitor, good lighting, etc. However, there is one thing that has been a little bit out of my control: My desk is in a large open space in our house and it is close to the kitchen. And every now and then I find myself in the middle of a conference call while the family is turning on the kettle or cleaning the dishes in the background. If only there was a way to make it more obvious that I am in the middle of a call…

We are heavily using Microsoft Teams in our organisation, so my solution focuses on the presence concept of Teams. And if you have been reading my blog for some time now, you would be aware that I am a long time user of Home Assistant, so of course I want to represent my presence in there. This will give me all the flexibility to not only remote control a status light, but maybe other things, too, like for example turn off the radio when a meeting starts.

One thing that really caught my eye and kicked off this whole investigation was a recent post on the Home Assistant subreddit.

So now that we now what the vision for this integration is, let’s see how we can get there.

Access presence status from Teams

The first thing I tried was Microsoft’s Graph API. To play around with the various API calls you can try the Graph Explorer. The key API call for this integration is probably https://graph.microsoft.com/beta/me/presence which returns the availability and activity status.

The biggest challenge here is security. Of course security is important, especially with personal information such as whether you are working or not. However, multi-factor authentication and tokens make it hard to use this API on the server-side.

Luckily someone in the HA community forum pointed me to an app called PresenceLight. This app takes care of the authentication and authorisation process with the Graph API and actually provides a bit of a shortcut if you are not using Home Assistant – it can directly control Philips Hue, Yeelight or LIFX lights and change the colour based on your status. However it also contains a custom API option where you can define a URL to POST to – the perfect integration point for Home Assistant’s webhooks.

Installing PresenceLight

I installed PresenceLight from the Microsoft Store on my Windows 10 work laptop. Administrator permissions for the installation were not required in my case – your experience may be different depending on the security constraints implemented by your organisation.

PresenceLight Microsoft Store

Authorisation Process

As part of the initial startup of the app you are being guided through the authorisation process that will allow PresenceLight to access your Teams status. The experience may be slightly different depending on whether or not your organisation has Multi-factor authentication (MFA) enabled, and whether or not you are already logged on to Office 365. After the successful authentication, the app shows the current Teams status on the first tab.

PresenceLight First Start
PresenceLight Sign-in – Pick an Account
PresenceLight Sign-in – Permissions requested

Note: If instead at this step you get a message “Need admin approval”, then you will need to ask your friendly IT department to help you with the installation and authorisation.

Autostart PresenceLight

Because Teams has become such an essential part of my workday it is automatically starting up when I start Windows. Hence it makes sense to also start PresenceLight automatically.

In Windows 10 you can for example do that by opening Windows Explorer and go to %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup. Now you can drag and drop the PresenceLight icon from the start menu into that folder and Windows automatically creates a link.

Windows 10 Create Startup Link

Shortcut if you are not using Home Assistant

If you are not using Home Assistant and either have a Philips Hue, Yeelight or LIFX lamp in your local network then have a look at the other tabs in the app. You can connect a lamp and change the colour depending on your status in Teams. I haven’t actually tried these options myself, because all my smart lights are integrated into Home Assistant and my work laptop is in a separate VLAN that has little access to the rest of my network.

If however you want to use the full power of Home Assistant then please continue reading.

Home Assistant Configuration

There are a couple of things to know and prepare for this integration. I decided to create 2 input selects – one for availability and one for activity. Each input select simply stores the actual value provided by the PresenceLight app. I decided to store a more human-readable form of the status instead of the original values used in the Graph API without spaces.

Next we need two automations that each use a webhook trigger. The webhook ID does not need to be defined separately and is just extracted from the URL that we will configure in PresenceLight. The action in each automation extracts a query parameter status and sets the value on the corresponding input select entity.

Instead of YAML configuration, this time I am only using a UI based configuration hence the screenshots below.

Availability Input Select

Input Select – Availability

Availability Webhook Automation

Webhook Automation – Availability

Activity Input Select

Input Select – Activity

Activity Webhook Automation

Webhook Automation – Activity

Network Access Considerations

Let’s quickly talk about the network setup and access to Home Assistant:

  • If Home Assistant and your computer running Teams are in the same local network then the setup should be fairly easy.
  • However, if you are frequently using a VPN to dial into the corporate network, all traffic is routed through the VPN and local access to Home Assistant is not available anymore.
  • If your Home Assistant instance is already accessible from outside your local network then make sure you can access its URL from inside your local network as well as through the corporate VPN.
  • An alternative is to use Nabu Casa’s webhook capability. After creating the automations above, go to Configuration -> Home Assistant Cloud and scroll down to the Webhooks section as shown below, find the new webhooks, activate them and use the URL displayed as your base URL in the PresenceLight configuration.
Webhooks via Nabu Casa

PresenceLight Configuration

On the Configure Custom API tab in PresenceLight you have to tick the checkbox at the top and then fill in all the details.

  • The API Method must be set to POST because that is the only method that the Home Assistant webhooks support.
  • The base URL of course depends on how you have set up your Home Assistant and how it is accessible from the computer running PresenceLight.
  • The path is /api/webhook/<webhook ID> where the webhook ID must correspond with the one configured in the automation triggers above.
  • If you decided to use Nabu Casa’s webhook integration the whole public URL including path is provided on the Home Assistant Cloud page. If you have already activated the webhook you can click on “Manage” to copy the public URL.
  • Finally I added a URL parameter status that carries the value, and which of course must correspond with the input select options.
    The format for the first URL parameter is ?status=<value> appended to the URL without a space. This works with both the direct approach where your Home Assistant instance is publicly accessible as well as with the Nabu Casa webhook integration.
PresenceLight – Configure Custom API

Originally I thought about using just a single webhook ID, but that approach revealed a couple of challenges. While only a single automation would have been required, I had to use different URL parameters to distinguish availability and activity and thus the action would have become a bit more complicated to distinguish the two. Also, PresenceLight typically sends the two API calls very quickly in a row, so the automation mode would need to change to Queued or Parallel to correctly process both of them.

Now each time the presence status changes in Teams – whether manually or automatically – PresenceLight should call the corresponding webhook and update the status in Home Assistant. In my tests this typically happens in less than 5 seconds.

Home Assistant Panel

The following glance panel shows the current state of the two input select entities.

Presence Status Panel

And now that the status information is available in Home Assistant you can start creating automations based on state changes.

Outlook

In the next part of this series I am going to show a simple configuration of a light based on the Teams status. And in the meantime I am going to think about how my final status light is going to look like and what components I will need for that.

Another area of research could be finding out the status of the microphone – muted or unmuted. This information is something that Teams itself via the Graph API does not expose, so I will need to look for something else.

Compatibility

At the time of writing this post, I used:

  • Home Assistant 0.115.6 with Python 3.7.5 (please note that there appears to be an issue in 0.116.0 with the Nabu Casa webhook integration)
  • Microsoft Teams 1.3.00.13565 on Windows 10
  • PresenceLight 3.0.43.0

4 Replies to “Working from Home – Teams Availability”

  1. I have been trying to do something similar, but ran into the blocker than my organisation requires admin approval for accessing the Graph API, and blocks almost all apps in the Microsoft Store – therefore I have been unable to install PresenceLight and even if I could, would not easily be able to get approval to use the Graph API. I expect this will be a common limitation for many organisations, particularly large ones, who have tightly controlled security. I haven’t bothered to ask permission – as I know that it will be too hard. (I really wish Teams would also expose something locally to the machine that an app could read, as Skype for Business does).

    While it’s far from ideal, the solution I have put in place is to use AutoHotKey to look for the Teams icon in my system tray and depending on the icon, send a webhook to Home Assistant. This has some significant limitations, including needing to be visible on my screen to work, and I can only distinguish between Available/Busy/DND/Away as those are the only icon distinctions.

    For those in a similar situation as me, I have put my AHK solution up on GitHub here: https://github.com/ajobbins/AHK-Teams-Presence

    To your point about mic in use, I’ve also looked into this and there is no great solution. I’d also like to know if my camera is on. I am working on an update to my AHK script above to look at the screen to see the status of both the mic and video icons in the Teams UI and update accordingly. I’ve got a partially working solution already, but needs some cleanup before I publish to GitHub.

    1. Thanks very much for the details, Adam.
      I was actually positively surprised that my organisation did allow me to install the app and access the Graph API, but you are right, there will be many organisations who won’t. The approach you are taking is quite smart, just looking at icons or other information available on the screen. I have seen some people who looked at using DLLs to locally access the Teams status but that all required custom code.

  2. Great post, this will really help keeping my home office ‘zen’ while working.
    But during testing I noticed an error when updating my status, logging says the following when updating:
    Invalid option: {{ trigger.query[“status”] }} (possible options: Available, Busy…

    Do you have an idea?
    This is the service data I have configured:
    option: ‘{{ trigger.query[“status”] }}’
    entity_id: entity_id: input_select.home_office_presence_bo_activity

    1. Thanks for your feedback, Bo.

      First of all, your configuration appears to contain entity_id twice. Is that a copy&paste issue into the comment? If not, that line should only read entity_id: input_select.home_office_presence_bo_activity.

      That error message you are getting indicates that the expression '{{ trigger.query["status"] }}' is not recognised as a template, but instead the automation literally tries to set that string as option. If I had to make a guess I would say that the single-quote or double-quotes may not be quite right. I just copied and pasted the configuration snippet from your comment into a text editor and that shows different single-quote/double-quote characters.

      Not sure if it’s going to work, but try to copy&paste this into the service data field:
      option: '{{ trigger.query["status"] }}'
      entity_id: input_select.home_office_presence_bo_activity

Leave a Reply

Your email address will not be published. Required fields are marked *