Teams Presence Light with Raspberry Pi

Almost every one of us is working from home these days due to the Corono situation we are in as of the time I am writing this article. I wrote a recent blog post about controlling devices from PowerApps with the help of a Raspberry PI and thought of extending the project by creating a Teams presence light with the help of a Raspberry Pi & couple of LED’s with different colours. This was possible due to the availability of the presence API endpoint in MS Graph, this helps us get the user’s current team presence (Available, Busy, Be right back, Do not disturb etc) for a logged in user. As of the time I am writing this article application permissions are not supported.

Device Code Flow:

The supported permission type is Delegated to get the presence information in MS graph, the user must sign in to get the users Teams presence. So how can a user signin/authenticate on a device like Raspberry Pi if we are only using a Terminal window to develop & run the application which I will doing it here, Device code flow to the rescue which is an authentication flow to get the data from MS graph for handling delegated permissions with remote signin/authentication using an auto generated device code. This flow lets the user use another device (for instance the windows client with the VS Code) to sign-in interactively. By using the device code flow, the application obtains tokens through a two-step process especially designed for these devices like Raspberry Pi. Examples of such applications are applications running on iOT, or Command-Line tools (CLI).

Refer this blog post for the steps & instructions to develop applications remotely on a Raspberry Pi using VS code.

Application Design:

There will be a .NET core console application polling the MS Graph presence endpoint every 5 seconds and based on the status, the corresponding coloured lights will be turned on. Find below the high-level design of the application

Active Directory application registration:

Start with registering an Application in Active directory with the following settings

Supported Account Types: Accounts in any organizational directory

Redirect URI (Public client/native): https://login.microsoftonline.com/common/oauth2/nativeclient

Enable Allow public client flows a required setting for the device code flow to work as shown below

Add the permission Presence.Read.All if you going to create a presence light for some other user other than the signed in user and Presence.Read if its going to be only for the signed in user. Once the permission is added, grant admin consent.

Console Application:

A console application with the following packages

Package NamePurpose
System.Devices.GpioTo control the GPIO pins for turning on different coloured lights
Microsoft.Identity.ClientAuthentication library for .NET console app facilitating MS graph token handling, caching, token expiration etc
System.ThreadingTimer to poll MS graph presence endpoint every 5 seconds
Newtonsoft.JsonTo parse the MS Graph presence endpoint response
System.Net.HttpTo make a HTTP request GET for presence endpoint

If you wanted to try the MS Graph presence endpoint go the Graph explorer and sign-in using your work account linked to your teams

Beta endpoint URL: https://graph.microsoft.com/beta/me/presence

Request Type: GET

In this example, GPIO pins 12 and 13 are used with Green and Red LED’s but you can also use a RGB LED matrix supported for Raspberry Pi which are readily available in the market. Use the Client Id and the tenant id of the application in the app.

  • Provide the GPIO pins the root permissions through the command on the terminal window /usr/bin/gpio export 12 out and /usr/bin/gpio export 13 out.
  • Run the application by using dotnet run
  • Method AcquireByDeviceCodeAsync(IPublicClientApplication pca) generates the device code
  • As soon as the application is run from the command line, the code is generated as shown below
  • Use the URL https://microsoft.com/devicelogin to login and authenticate against the code generated above
  • Code pca.AcquireTokenSilent(Scopes, accounts.FirstOrDefault()).ExecuteAsync(); generates the token which will used along with the graph GET request for getting the teams presence status of the user
  • The Token will be valid only for 3599 seconds which is close to 1 hour. Generate one more token using the same line of code after an hour which I have not handled in the sample code.
  • Polling will happen every 5 seconds using the .NET Timer_timer.Change(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(5));
  • Based on the teams presence, the corresponding lights will be turned on using the below code
switch (presenceStatus)
{
                        case "Available":
                            Console.WriteLine($"{DateTime.Now} : User is Available");
                            controller.Write(pinGreen, PinValue.High);
                            controller.Write(pinRed, PinValue.Low);
                            break;
                        case "Busy":
                            Console.WriteLine($"{DateTime.Now} : User is Busy");
                            controller.Write(pinGreen, PinValue.Low);
                            controller.Write(pinRed, PinValue.High);
                            break;
}

Code for this application can be found in this GitHub repo link.

More Information about the Device code Flow:

 A POST request to the URL https://login.microsoftonline.com/yourTenantID/oauth2/devicecode with the following information for Header:

Content-Type: application/x-www-form-urlencoded

Request Body: resource=https%3A%2F%2Fgraph.windows.net&client_id=ADClientId/Appid

Will generate the following response

Login & authenticate using the URL https://microsoft.com/devicelogin with the work account.

Token Generation:

With the information from the above request, the token can be generated with a POST request to the URL https://login.microsoftonline.com/youtTenantID/oauth2/token with the following information for Header:

Content-Type: application/x-www-form-urlencoded

Request Body: grant_type=device_code&resource=https%3A%2F%2Fgraph.windows.net&code=CAQABAAEAAAB2UyzwtQEKR7-rWbgdcBZIsC_ydGuxXqxKTcIvapYfPR0edvvCOBAW4VoOZgLHdaAgrf0cBy-5s9Szoez1NmqIgoe0Ggs9p_7-vVilrU6r9CFom5N_M(Information from the Previous response)&client_id= ADClientId/Appid

Will generate the token in the response

Refresh Token:

This token is used to generate access token after the initial one expires by making another request with information like this in the request body

All of these are handled for us by the Microsoft Authentication library for .NET.

Summary: I’ve used MSAL for .NET library  but there are also libraries for MSAL for Python and for other languages as well based on your comfort with the programming language. Hope you have found this informational & interesting. Let me know any feedback or comments on the comment section below

Reference:

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code

https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Device-Code-Flow

https://github.com/Azure-Samples/active-directory-dotnetcore-devicecodeflow-v2

https://ashiqf.com/2020/10/25/tools-to-call-microsoft-graph-api-endpoints-as-a-user-and-application/

Advertisement

2 thoughts on “Teams Presence Light with Raspberry Pi

  1. This is good stuff, I’ve been looking for a busy light device that I can put elsewhere in my house.

    Can the code presented here be easily used to get my presence on two or three accounts, and then set the lights based on the “busiest” status?

    Like

    1. The code works for one user, if you need for 3 accounts then there has to be 3 applications running on Raspberry Pi with an registered AD app for each account. Also the token should be renewed after an hour which I have mentioned in the post.

      Like

Leave a Reply to Mohamed Ashiq Faleel Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s