Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pathartl committed Oct 6, 2021
1 parent 1810e4d commit bd23ed9
Show file tree
Hide file tree
Showing 13 changed files with 515 additions and 0 deletions.
6 changes: 6 additions & 0 deletions App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
12 changes: 12 additions & 0 deletions HomeAssistantEntityStateUpdate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace TeamsPresence
{
public class HomeAssistantEntityStateUpdate
{
[JsonProperty(PropertyName = "state")]
public string State { get; set; }
[JsonProperty(PropertyName = "attributes")]
public HomeAssistantEntityStateUpdateAttributes Attributes { get; set; }
}
}
12 changes: 12 additions & 0 deletions HomeAssistantEntityStateUpdateAttributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace TeamsPresence
{
public class HomeAssistantEntityStateUpdateAttributes
{
[JsonProperty(PropertyName = "friendly_name")]
public string FriendlyName { get; set; }
[JsonProperty(PropertyName = "state")]
public string Icon { get; set; }
}
}
41 changes: 41 additions & 0 deletions HomeAssistantService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using RestSharp;
using RestSharp.Serializers.NewtonsoftJson;

namespace TeamsPresence
{
public class HomeAssistantService
{
private string Token { get; set; }
private string Url { get; set; }
private RestClient Client { get; set; }

public HomeAssistantService(string url, string token)
{
Token = token;
Url = url;
Client = new RestClient(url);

Client.AddDefaultHeader("Authorization", $"Bearer {Token}");
Client.UseNewtonsoftJson();
}

public void UpdateEntity(string entity, string state, string stateFriendlyName, string icon)
{
var update = new HomeAssistantEntityStateUpdate()
{
State = state,
Attributes = new HomeAssistantEntityStateUpdateAttributes()
{
FriendlyName = stateFriendlyName,
Icon = icon
}
};

var request = new RestRequest($"api/states/{entity}", Method.POST, DataFormat.Json);

request.AddJsonBody(update);

Client.Execute(request);
}
}
}
117 changes: 117 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace TeamsPresence
{
class Program
{
private static HomeAssistantService HomeAssistantService;
private static TeamsLogService TeamsLogService;
private static TeamsPresenceConfig Config;

static void Main(string[] args)
{
var configFile = "config.json";

if (File.Exists(configFile))
{
Console.WriteLine("Config file found!");

try
{
Config = JsonConvert.DeserializeObject<TeamsPresenceConfig>(File.ReadAllText(configFile));
}
catch
{
Console.WriteLine("Config file could not be used. Either fix it or delete it and restart this application to scaffold a new one.");
}
}
else
{
Console.WriteLine("Config file doesn't exist. Creating...");

Config = new TeamsPresenceConfig()
{
HomeAssistantUrl = "https://yourha.duckdns.org",
HomeAssistantToken = "eyJ0eXAiOiJKV1...",
AppDataRoamingPath = "",
StatusEntity = "sensor.teams_status",
ActivityEntity = "sensor.teams_activity",
FriendlyStatusNames = new Dictionary<TeamsStatus, string>()
{
{ TeamsStatus.Available, "Available" },
{ TeamsStatus.Busy, "Busy" },
{ TeamsStatus.OnThePhone, "On the phone" },
{ TeamsStatus.Away, "Away" },
{ TeamsStatus.BeRightBack, "Be right back" },
{ TeamsStatus.DoNotDisturb, "Do not disturb" },
{ TeamsStatus.Presenting, "Presenting" },
{ TeamsStatus.Focusing, "Focusing" },
{ TeamsStatus.InAMeeting, "In a meeting" },
{ TeamsStatus.Offline, "Offline" },
{ TeamsStatus.Unknown, "Unknown" }
},
FriendlyActivityNames = new Dictionary<TeamsActivity, string>()
{
{ TeamsActivity.InACall, "In a call" },
{ TeamsActivity.NotInACall, "Not in a call" },
{ TeamsActivity.Unknown, "Unknown" }
},
ActivityIcons = new Dictionary<TeamsActivity, string>()
{
{ TeamsActivity.InACall, "mdi:phone-in-talk-outline" },
{ TeamsActivity.NotInACall, "mdi:phone-off" },
{ TeamsActivity.Unknown, "mdi:phone-cancel" }
}
};

File.WriteAllText(configFile, JsonConvert.SerializeObject(Config, new JsonSerializerSettings()
{
Formatting = Formatting.Indented
}));

Console.WriteLine("Done. Fill out the config file and restart this application.");

return;
}

if (!String.IsNullOrWhiteSpace(Config.AppDataRoamingPath))
{
TeamsLogService = new TeamsLogService(Config.AppDataRoamingPath);
}
else
{
TeamsLogService = new TeamsLogService();
}

HomeAssistantService = new HomeAssistantService(Config.HomeAssistantUrl, Config.HomeAssistantToken);

TeamsLogService.StatusChanged += Service_StatusChanged;
TeamsLogService.ActivityChanged += Service_ActivityChanged;

Console.WriteLine("Service started. Waiting for Teams updates...");

TeamsLogService.Start();
}

private static void Service_StatusChanged(object sender, TeamsStatus status)
{
HomeAssistantService.UpdateEntity(Config.StatusEntity, status.ToString(), Config.FriendlyStatusNames[status], "mdi:microsoft-teams");

Console.WriteLine($"Updated status to {Config.FriendlyStatusNames[status]} ({status})");
}

private static void Service_ActivityChanged(object sender, TeamsActivity activity)
{
HomeAssistantService.UpdateEntity(Config.ActivityEntity, activity.ToString(), Config.FriendlyActivityNames[activity], "mdi:microsoft-teams");

Console.WriteLine($"Updated activity to {Config.FriendlyActivityNames[activity]} ({activity})");
}
}
}
36 changes: 36 additions & 0 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Teams Presence")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Teams Presence")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7373d528-f767-4685-bc5f-5894ce155859")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# TeamsPresence
A .NET console application that will update entities in Home Assistant based on Microsoft Teams status

## Initial Configuration

When you run the application for the first time it will create a sample `config.json` file. To get up an running right away, update the `HomeAssistantUrl` and `HomeAssistantToken` values.

**Note:** You can set the `AppDataRoamingPath` to hard code which user profile is used for `%appdata%`

Some changes to Home Assistant's config is also needed. Add the following to your `configuration.yaml`:

```yaml
sensor:
- platform: template
sensors:
teams_status:
friendly_name: "Microsoft Teams status"
value_template: "{{states('input_text.teams_status')}}"
icon_template: "{{state_attr('input_text.teams_status','icon')}}"
unique_id: sensor.teams_status
teams_activity:
friendly_name: "Microsoft Teams activity"
value_template: "{{states('input_text.teams_activity')}}"
unique_id: sensor.teams_activity

input_text:
teams_status:
name: Microsoft Teams Status
icon: mdi:microsoft-teams
teams_activity:
name: Microsoft Teams Activity
icon: mdi:phone-off
```
Once these steps are completed, you should be able to start the application and see changes to your Teams status and call activity get updated both in the console and in Home Assistant.
31 changes: 31 additions & 0 deletions TeamsEnums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TeamsPresence
{
public enum TeamsStatus
{
Unknown,
Available,
Busy,
OnThePhone,
Away,
BeRightBack,
DoNotDisturb,
Presenting,
Focusing,
InAMeeting,
Offline
}

public enum TeamsActivity
{
Unknown,
NotInACall,
InACall
}
}
Loading

0 comments on commit bd23ed9

Please sign in to comment.