Skip to content

Commit

Permalink
v2022.2.27
Browse files Browse the repository at this point in the history
  • Loading branch information
LAB02 Research committed Feb 27, 2022
1 parent 03e3c85 commit cdfb7f5
Show file tree
Hide file tree
Showing 117 changed files with 7,079 additions and 2,078 deletions.
4 changes: 2 additions & 2 deletions src/HASS.Agent/HASSAgent.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31402.337
# Visual Studio Version 17
VisualStudioVersion = 17.0.32126.317
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HASSAgent", "HASSAgent\HASSAgent.csproj", "{407FFF5A-97EA-429E-BD5E-81D93240A1BD}"
EndProject
Expand Down
100 changes: 97 additions & 3 deletions src/HASS.Agent/HASSAgent/Commands/CommandsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading.Tasks;
using HASSAgent.Enums;
using HASSAgent.Models.Config;
using HASSAgent.Mqtt;
using HASSAgent.Settings;
using Serilog;
Expand Down Expand Up @@ -94,7 +95,6 @@ private static async void Process()
// on the first run, just wait 1 sec - this is to make sure we're announcing ourselves,
// when there are no sensors or when the sensor manager's still initialising
await Task.Delay(TimeSpan.FromSeconds(1));
firstRun = false;
}
else await Task.Delay(TimeSpan.FromSeconds(30));

Expand All @@ -108,6 +108,9 @@ private static async void Process()
continue;
}

// we're starting the first real run
firstRun = false;

// do we have commands?
if (!CommandsPresent()) continue;

Expand All @@ -120,6 +123,7 @@ private static async void Process()
// publish command autodisco's
foreach (var command in Variables.Commands.TakeWhile(command => !_pause).TakeWhile(command => _active))
{
if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue;
await command.PublishAutoDiscoveryConfigAsync();
}

Expand All @@ -128,6 +132,7 @@ private static async void Process()
{
foreach (var command in Variables.Commands.TakeWhile(command => !_pause).TakeWhile(command => _active))
{
if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue;
await MqttManager.SubscribeAsync(command);
}
subscribed = true;
Expand All @@ -140,13 +145,98 @@ private static async void Process()
// publish command states (they have their own time-based scheduling)
foreach (var command in Variables.Commands.TakeWhile(command => !_pause).TakeWhile(command => _active))
{
if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue;
await command.PublishStateAsync();
}
}
catch (Exception ex)
{
Log.Fatal(ex, "[COMMANDSMANAGER] Eroor while publishing: {err}", ex.Message);
Log.Fatal(ex, "[COMMANDSMANAGER] Error while publishing: {err}", ex.Message);
}
}
}

/// <summary>
/// Stores the provided commands, and (re)publishes them
/// </summary>
/// <param name="commands"></param>
/// <param name="toBeDeletedCommands"></param>
/// <returns></returns>
internal static async Task<bool> StoreAsync(List<ConfiguredCommand> commands, List<ConfiguredCommand> toBeDeletedCommands = null)
{
if (toBeDeletedCommands == null) toBeDeletedCommands = new List<ConfiguredCommand>();

try
{
// pause processing
Pause();

// process the to-be-removed
if (toBeDeletedCommands.Any())
{
foreach (var abstractCommand in toBeDeletedCommands.Select(StoredCommands.ConvertConfiguredToAbstract).Where(abstractCommand => abstractCommand != null))
{
// remove and unregister
await abstractCommand.UnPublishAutoDiscoveryConfigAsync();
await MqttManager.UnubscribeAsync(abstractCommand);
Variables.Commands.RemoveAt(Variables.Commands.FindIndex(x => x.Id == abstractCommand.Id));

Log.Information("[COMMANDS] Removed command: {command}", abstractCommand.Name);
}
}

// copy our list to the main one
foreach (var abstractCommand in commands.Select(StoredCommands.ConvertConfiguredToAbstract).Where(abstractCommand => abstractCommand != null))
{
if (Variables.Commands.All(x => x.Id != abstractCommand.Id))
{
// new, add and register
Variables.Commands.Add(abstractCommand);
await MqttManager.SubscribeAsync(abstractCommand);
await abstractCommand.PublishAutoDiscoveryConfigAsync();
await abstractCommand.PublishStateAsync(false);

Log.Information("[COMMANDS] Added command: {command}", abstractCommand.Name);
continue;
}

// existing, update and re-register
var currentCommandIndex = Variables.Commands.FindIndex(x => x.Id == abstractCommand.Id);
if (Variables.Commands[currentCommandIndex].Name != abstractCommand.Name)
{
// name changed, unregister and resubscribe on new mqtt channel
Log.Information("[COMMANDS] Command changed name, re-registering as new entity: {old} to {new}", Variables.Commands[currentCommandIndex].Name, abstractCommand.Name);

await Variables.Commands[currentCommandIndex].UnPublishAutoDiscoveryConfigAsync();
await MqttManager.UnubscribeAsync(Variables.Commands[currentCommandIndex]);
await MqttManager.SubscribeAsync(abstractCommand);
}

Variables.Commands[currentCommandIndex] = abstractCommand;
await abstractCommand.PublishAutoDiscoveryConfigAsync();
await abstractCommand.PublishStateAsync(false);

Log.Information("[COMMANDS] Modified command: {command}", abstractCommand.Name);
}

// annouce ourselves
await MqttManager.AnnounceAvailabilityAsync();

// store to file
StoredCommands.Store();

// done
return true;
}
catch (Exception ex)
{
Log.Fatal(ex, "[COMMANDSMANAGER] Error while storing: {err}", ex.Message);
return false;
}
finally
{
// resume processing
Unpause();
}
}

Expand All @@ -159,7 +249,7 @@ private static async void Process()
/// <returns></returns>
internal static string GetCommandDefaultInfo(CommandType type)
{
return !CommandInfo.ContainsKey(type) ? "unknown command" : CommandInfo[type];
return !CommandInfo.ContainsKey(type) ? "Unknown command, make sure HASS.Agent has finished booting up." : CommandInfo[type];
}

/// <summary>
Expand All @@ -170,6 +260,7 @@ private static void LoadCommandInfo()
CommandInfo.Add(CommandType.ShutdownCommand, "Shuts down the machine after one minute.\r\n\r\nTip: accidentally triggered? Run 'shutdown /a' to abort.");
CommandInfo.Add(CommandType.RestartCommand, "Restarts the machine after one minute.\r\n\r\nTip: accidentally triggered? Run 'shutdown /a' to abort.");
CommandInfo.Add(CommandType.HibernateCommand, "Sets the machine in hibernation.");
CommandInfo.Add(CommandType.SleepCommand, "Puts the machine to sleep.\r\n\r\nNote: due to a limitation in Windows, this only works if hibernation is disabled, otherwise it will just hibernate.\r\n\r\nYou can use something like NirCmd (http://www.nirsoft.net/utils/nircmd.html) to circumvent this.");
CommandInfo.Add(CommandType.LogOffCommand, "Logs off the current session.");
CommandInfo.Add(CommandType.LockCommand, "Locks the current session.");
CommandInfo.Add(CommandType.CustomCommand, "Execute a custom command.\r\n\r\nThese commands run without special elevation. To run elevated, create a Scheduled Task, and use 'schtasks /Run /TN \"TaskName\"' as the command to execute your task.\r\n\r\nOr enable 'run as low integrity' for even stricter execution.");
Expand All @@ -181,6 +272,9 @@ private static void LoadCommandInfo()
CommandInfo.Add(CommandType.MediaVolumeDownCommand, "Simulates 'volume down' key.");
CommandInfo.Add(CommandType.MediaMuteCommand, "Simulates 'mute' key.");
CommandInfo.Add(CommandType.KeyCommand, "Simulates a single keypress.\r\n\r\nYou can pick any of these values: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes \r\n\r\nAnother option is using a tool like AutoHotKey and binding it to a CustomCommand.");
CommandInfo.Add(CommandType.PublishAllSensorsCommand, "Resets all sensor checks, forcing all sensors to process and send their value.\r\n\r\nUseful for example if you want to force HASS.Agent to update all your sensors after a HA reboot.");
CommandInfo.Add(CommandType.LaunchUrlCommand, "Launches the provided URL, by default in your default browser.\r\n\r\nTo use 'incognito', provide a specific browser in Configuration -> External Tools.");
CommandInfo.Add(CommandType.CustomExecutorCommand, "Executes the command through the configured custom executor (in Configuration -> External Tools).\r\n\r\nYour command is provided as an argument 'as is', so you have to supply your own quotes etc. if necessary.");
}
}
}
Loading

0 comments on commit cdfb7f5

Please sign in to comment.