diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantComand.cs b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantServiceComand.cs similarity index 73% rename from HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantComand.cs rename to HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantServiceComand.cs index e9999b7..fb12e5d 100644 --- a/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantComand.cs +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantServiceComand.cs @@ -6,12 +6,10 @@ public class HomeAssistandCommand : PluginDynamicCommand { - - public HomeAssistandCommand() : base("Home assistant", "Controll your Home", "Entity") - { + public HomeAssistandCommand() : base("Call Service", "Controll your Home", "Entity") + { this.MakeProfileAction("tree"); } - protected override PluginProfileActionData GetProfileActionData() { var tree = new PluginProfileActionTree("Select Service and entity"); @@ -27,7 +25,7 @@ protected override PluginProfileActionData GetProfileActionData() foreach (String s in e.Entities) { pluginProfileActionTreeNode.SetPropertyValue("Service", e.Service); - pluginProfileActionTreeNode.AddItem(e.Service + "|" + s,s,e.Service); + pluginProfileActionTreeNode.AddItem(e.Service + "|" + s, s, e.Service); } } } @@ -37,7 +35,7 @@ protected override PluginProfileActionData GetProfileActionData() protected override String GetCommandDisplayName(String actionParameter, PluginImageSize imageSize) => String.IsNullOrEmpty(actionParameter) ? "HomeAssistant" : actionParameter; - + protected override void RunCommand(String actionParameter) { if (actionParameter.Contains("|")) @@ -50,25 +48,9 @@ protected override void RunCommand(String actionParameter) var body = @"{""entity_id"": """ + entity + @"""}"; _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", HomeAssistantPlugin.HomeAssistantPlugin.Config.Token); - var content = new StringContent(body,System.Text.Encoding.UTF8, "application/json"); //https://developers.home-assistant.io/docs/api/rest/ + var content = new StringContent(body, System.Text.Encoding.UTF8, "application/json"); //https://developers.home-assistant.io/docs/api/rest/ _client.PostAsync(url, content); } } - - /* - protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) - { - - using (var bitmapBuilder = new BitmapBuilder(imageSize)) - { - bitmapBuilder.Clear(BitmapColor.Black); - if (actionParameter.Contains("|")) - { - bitmapBuilder.DrawText(actionParameter.Split("|")[1].Replace(".",".\n"), BitmapColor.White, 15, 13, 3); - } - return bitmapBuilder.ToImage(); - } - } */ - } } diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantStateCommand.cs b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantStateCommand.cs new file mode 100644 index 0000000..8ef6bca --- /dev/null +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantStateCommand.cs @@ -0,0 +1,144 @@ +namespace Loupedeck.HomeAssistantPlugin.Actions +{ + using System; + using System.Collections.Generic; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Text.Json.Nodes; + using System.Timers; + using System.Web; + + + class HomeAssistantStateCommand : PluginDynamicCommand + { + protected HttpClient httpClient = new HttpClient(); + protected IDictionary stateData = new Dictionary(); + protected Timer timer; + + protected class StateData + { + public String state; + public Boolean IsValid = false; + public Boolean IsLoading = false; + } + + public HomeAssistantStateCommand() : base("Get State", "Get the state of an entity", "") + { + this.MakeProfileAction("text;Enter entity"); + + // Reload the data periodically every 1 minutes + this.timer = new Timer(60 * 1 * 1000); + this.timer.Elapsed += (Object, ElapsedEventArgs) => + { + foreach (var actionParameter in new List(this.stateData.Keys)) + { + this.LoadData(actionParameter); + } + }; + this.timer.AutoReset = true; + this.timer.Enabled = true; + } + + protected override void RunCommand(String actionParameter) + { + this.LoadData(actionParameter); + } + + protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) + { + if (actionParameter == null) + { + return null; + } + + StateData s = this.GetStateData(actionParameter); + if (!s.IsValid) + { + return null; + } + + var img = new BitmapBuilder(imageSize); + using (var bitmapBuilder = new BitmapBuilder(imageSize)) + { + var fn = EmbeddedResources.FindFile("ButtonBaseHomeAssistant.png"); + bitmapBuilder.SetBackgroundImage(EmbeddedResources.ReadImage(fn)); + if (this.stateData[actionParameter].IsValid) + { + bitmapBuilder.DrawText(this.stateData[actionParameter].state); + } + else + { + bitmapBuilder.DrawText(actionParameter); + } + + + return bitmapBuilder.ToImage(); + } + } + + protected StateData GetStateData(string actionParameter) + { + StateData d; + if (this.stateData.TryGetValue(actionParameter, out d)) + return d; + + d = new StateData(); + stateData[actionParameter] = d; + + LoadData(actionParameter); + + return d; + } + + protected StateData _GetStateData(String actionParameter) + { + + this.LoadData(actionParameter); + + return this.stateData[actionParameter]; + } + + protected async void LoadData(String actionParameter) + { + if (actionParameter == null) + { + return; + } + + if (this.stateData[actionParameter] == null) + { + this.stateData[actionParameter] = new StateData(); + } + + StateData d = this.GetStateData(actionParameter); + if (d.IsLoading) + { + return; + } + + d.IsLoading = true; + + try + { + var _client = new HttpClient(); + var url = HomeAssistantPlugin.Config.Url + "states/" + actionParameter; + _client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", HomeAssistantPlugin.Config.Token); + HttpResponseMessage resp = await _client.GetAsync(url); + var json = JsonNode.Parse(await resp.Content.ReadAsStringAsync()); + d.state = json["state"].GetValue(); + } + catch (Exception e) + { + d.state = "error"; + } + finally + { + d.IsLoading = false; + d.IsValid = true; + this.ActionImageChanged(actionParameter); + } + } + } + +} diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantTemplateCommand.cs b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantTemplateCommand.cs new file mode 100644 index 0000000..ddbe2b0 --- /dev/null +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantTemplateCommand.cs @@ -0,0 +1,140 @@ +namespace Loupedeck.HomeAssistantPlugin +{ + using System; + using System.Collections.Generic; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Text.Json.Nodes; + using System.Timers; + + class HomeAssistantTemplateCommand : PluginDynamicCommand + { + protected HttpClient httpClient = new HttpClient(); + protected IDictionary templateData = new Dictionary(); + protected Timer timer; + + protected class TemplateData + { + public String template; + public Boolean IsValid = false; + public Boolean IsLoading = false; + } + + public HomeAssistantTemplateCommand() : base("Eval a template", "Evaluate a template to show the result.", "") + { + this.MakeProfileAction("text;Enter template"); + + // Reload the data periodically every 1 minutes + this.timer = new Timer(60 * 1 * 1000); + this.timer.Elapsed += (Object, ElapsedEventArgs) => + { + foreach (var actionParameter in new List(this.templateData.Keys)) + { + this.LoadData(actionParameter); + } + }; + this.timer.AutoReset = true; + this.timer.Enabled = true; + } + + protected override void RunCommand(String actionParameter) + { + this.LoadData(actionParameter); + } + + protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) + { + if (actionParameter == null) + { + return null; + } + + TemplateData s = this.GetTemplateData(actionParameter); + if (!s.IsValid) + { + return null; + } + + var img = new BitmapBuilder(imageSize); + using (var bitmapBuilder = new BitmapBuilder(imageSize)) + { + var fn = EmbeddedResources.FindFile("ButtonBaseHomeAssistant.png"); + bitmapBuilder.SetBackgroundImage(EmbeddedResources.ReadImage(fn)); + if (this.templateData[actionParameter].IsValid) + { + bitmapBuilder.DrawText(this.templateData[actionParameter].template); + } + else + { + bitmapBuilder.DrawText("Error"); + } + + + return bitmapBuilder.ToImage(); + } + } + + protected TemplateData GetTemplateData(String actionParameter) + { + TemplateData d; + if (this.templateData.TryGetValue(actionParameter, out d)) + return d; + + d = new TemplateData(); + templateData[actionParameter] = d; + + LoadData(actionParameter); + + return d; + } + + protected async void LoadData(String actionParameter) + { + if (actionParameter == null) + { + return; + } + + if (this.templateData[actionParameter] == null) + { + this.templateData[actionParameter] = new TemplateData(); + } + + TemplateData d = this.GetTemplateData(actionParameter); + if (d.IsLoading) + { + return; + } + + d.IsLoading = true; + + try + { + var _client = new HttpClient(); + + var url = HomeAssistantPlugin.Config.Url + "template"; + var body = @"{""template"": """ + actionParameter + @"""}"; + _client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", HomeAssistantPlugin.Config.Token); + var content = new StringContent(body, System.Text.Encoding.UTF8, "application/json"); //https://developers.home-assistant.io/docs/api/rest/ + var resp = await _client.PostAsync(url, content); + if (resp.IsSuccessStatusCode) + { d.template = await resp.Content.ReadAsStringAsync(); } + else + { d.template = "Error"; } + + } + catch (Exception e) + { + d.template = "error"; + } + finally + { + d.IsLoading = false; + d.IsValid = true; + this.ActionImageChanged(actionParameter); + } + } + } + +} diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantTest.cs b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantTest.cs new file mode 100644 index 0000000..9ccb21c --- /dev/null +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/Actions/HomeAssistantTest.cs @@ -0,0 +1,86 @@ +namespace Loupedeck.HomeAssistantPlugin +{ + using System; + using System.Net.Http.Headers; + using System.Net.Http; + using System.Collections; + using System.Text.Json.Nodes; + using System.Threading.Tasks; + using System.Timers; + using System.Threading; + + public class HomeAssistantState : PluginDynamicCommand + { + protected Hashtable _States = new Hashtable(); + protected System.Timers.Timer timer; + + public HomeAssistantState() : base("Get State","Get the state of an entity", "" ) + { + this.MakeProfileAction("text;Enter entity;"); + + // Update icons periodically + this.timer = new System.Timers.Timer(15 * 1000); + this.timer.Elapsed += (Object, ElapsedEventArgs) => { + + foreach (String key in this._States.Keys ) + { + HttpRunAsync(key, this._States); + } + this.ActionImageChanged(); + }; + this.timer.AutoReset = true; + this.timer.Enabled = true; + } + + protected override void RunCommand(String actionParameter) + { + //HttpRunAsync(actionParameter, this._States); + // ActionImageChanged(actionParameter); + } + + static async Task HttpRunAsync(String actionParameter, Hashtable States) + { + var _client = new HttpClient(); + var url = HomeAssistantPlugin.Config.Url + "states/" + actionParameter; + _client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", HomeAssistantPlugin.Config.Token); + HttpResponseMessage resp = await _client.GetAsync(url); + + ; + if (resp.IsSuccessStatusCode) + { + var json = JsonNode.Parse(await resp.Content.ReadAsStringAsync()); + if (json["state"].GetValue() != null) + { + if (States.ContainsKey(actionParameter)){ + States[actionParameter] = json["state"].GetValue(); + } else { + States.Add(actionParameter, json["state"].GetValue()); + } + } + } else + { + States.Add(actionParameter, "Error"); + } + } + + protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) + { + using (var bitmapBuilder = new BitmapBuilder(imageSize)) + { + var fn = EmbeddedResources.FindFile("ButtonBaseHomeAssistant.png"); + bitmapBuilder.SetBackgroundImage(EmbeddedResources.ReadImage(fn)); + if (this._States.ContainsKey(actionParameter)) + { + bitmapBuilder.DrawText(this._States[actionParameter].ToString()); + } else + { + bitmapBuilder.DrawText(actionParameter); + } + + this.ActionImageChanged(actionParameter); + return bitmapBuilder.ToImage(); + } + } + } +} \ No newline at end of file diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/App.config b/HomeAssistantPlugin/src/HomeAssistantPlugin/App.config index 25b52c3..969a1b6 100644 --- a/HomeAssistantPlugin/src/HomeAssistantPlugin/App.config +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/App.config @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ - + diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.cs b/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.cs index e39e276..aea1ca8 100644 --- a/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.cs +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.cs @@ -21,7 +21,6 @@ public class HAServiceEntry { public String Service; public String[] Entities; - } public class HAAPIConfig { @@ -29,6 +28,7 @@ public class HAAPIConfig public String Token; public HAServiceEntry[] Entries; + public String[] States; } internal static HAAPIConfig Config; @@ -45,13 +45,10 @@ public override void Unload() { } - - - private void Init() + private void Init() { if (!Directory.Exists(Path.Combine(UserProfilePath, DEFAULT_PATH))) { - Directory.CreateDirectory(Path.Combine(UserProfilePath, DEFAULT_PATH)); } var fp = Path.Combine(UserProfilePath, DEFAULT_PATH); diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.csproj b/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.csproj index 11e2830..45d3a51 100644 --- a/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.csproj +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/HomeAssistantPlugin.csproj @@ -36,14 +36,42 @@ 4 + + ..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + False C:\Program Files (x86)\Loupedeck\Loupedeck2\PluginApi.dll /Applications/Loupedeck.app/Contents/MonoBundle/PluginApi.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.7.0.0\lib\net462\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + @@ -53,7 +81,10 @@ - + + + + @@ -70,19 +101,21 @@ Designer + - - - + + + + call "$(ProjectDir)BuildEvents\postbuild.cmd" "$(ProjectDir)" "$(TargetDir)" diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/Resources/ButtonBaseHomeAssistant.png b/HomeAssistantPlugin/src/HomeAssistantPlugin/Resources/ButtonBaseHomeAssistant.png new file mode 100644 index 0000000..f2e508e Binary files /dev/null and b/HomeAssistantPlugin/src/HomeAssistantPlugin/Resources/ButtonBaseHomeAssistant.png differ diff --git a/HomeAssistantPlugin/src/HomeAssistantPlugin/packages.config b/HomeAssistantPlugin/src/HomeAssistantPlugin/packages.config new file mode 100644 index 0000000..fb1eba0 --- /dev/null +++ b/HomeAssistantPlugin/src/HomeAssistantPlugin/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file