From b1b7d814f4746bf22f055a57a4a0ba028c343c4e Mon Sep 17 00:00:00 2001 From: LAB02 Research Date: Sun, 27 Mar 2022 13:00:33 +0200 Subject: [PATCH] v2022.3.27 --- src/CustomGroupBox/CustomGroupBox.sln | 26 - .../CustomGroupBox/CustomGroupBox.csproj | 52 - .../CustomGroupBox/Properties/AssemblyInfo.cs | 35 - src/HASS.Agent/HASSAgent.sln | 32 - src/HASS.Agent/HASSAgent/App.config | 8 - .../HASSAgent/Commands/CommandsManager.cs | 281 ----- .../Controls/Configuration/ExternalTools.resx | 125 -- .../Controls/Configuration/General.cs | 23 - .../Controls/Configuration/General.resx | 125 -- .../Controls/Configuration/HotKey.cs | 20 - .../Controls/Configuration/HotKey.resx | 120 -- .../Controls/Configuration/LocalStorage.resx | 120 -- .../Configuration/Logging.Designer.cs | 118 -- .../Controls/Configuration/Logging.cs | 23 - .../Controls/Configuration/Logging.resx | 129 --- .../HASSAgent/Controls/Configuration/MQTT.cs | 74 -- .../Controls/Configuration/MQTT.resx | 120 -- .../Configuration/Notifications.Designer.cs | 167 --- .../Controls/Configuration/Notifications.cs | 31 - .../Controls/Configuration/Startup.resx | 125 -- .../Controls/Configuration/Updates.cs | 20 - .../Controls/Onboarding/1-Welcome.resx | 120 -- .../Controls/Onboarding/2-Startup.resx | 120 -- .../Onboarding/3-Notifications.Designer.cs | 146 --- .../Controls/Onboarding/3-Notifications.cs | 38 - .../Controls/Onboarding/3-Notifications.resx | 120 -- .../Controls/Onboarding/4-Integration.resx | 136 --- .../HASSAgent/Controls/Onboarding/5-API.resx | 127 -- .../HASSAgent/Controls/Onboarding/6-MQTT.resx | 125 -- .../Controls/Onboarding/7-HotKey.resx | 120 -- .../HASSAgent/Controls/Onboarding/9-Done.resx | 130 --- .../Controls/QuickActionControl.resx | 120 -- src/HASS.Agent/HASSAgent/Enums/CommandType.cs | 64 - src/HASS.Agent/HASSAgent/Enums/LockState.cs | 9 - src/HASS.Agent/HASSAgent/Enums/MqttStatus.cs | 11 - src/HASS.Agent/HASSAgent/Enums/SensorType.cs | 93 -- .../HASSAgent/Enums/SystemStateEvent.cs | 20 - .../HASSAgent/Enums/UserNotificationState.cs | 13 - .../Forms/ChildApplications/PostUpdate.cs | 154 --- .../Forms/Commands/CommandsConfig.cs | 250 ---- .../Forms/QuickActions/QuickActionsConfig.cs | 242 ---- .../HASSAgent/Forms/Sensors/SensorsConfig.cs | 255 ---- .../Forms/Sensors/SensorsMod.Designer.cs | 347 ------ .../HASSAgent/Functions/CommandLineManager.cs | 1031 ----------------- .../Functions/PerformanceCounters.cs | 116 -- .../HASSAgent/Functions/PowershellManager.cs | 195 ---- .../HASSAgent/Functions/ScheduledTasks.cs | 324 ------ .../HASSAgent/Functions/SessionInfo.cs | 256 ---- .../Functions/WindowsUpdatesManager.cs | 187 --- src/HASS.Agent/HASSAgent/HASSAgent.csproj | 695 ----------- .../HASSAgent/Libraries/CustomGroupBox.dll | Bin 5120 -> 0 bytes .../HASSAgent/Libraries/CustomGroupBox.pdb | Bin 19968 -> 0 bytes .../Models/Config/ConfiguredCommand.cs | 35 - .../Models/Config/ConfiguredSensor.cs | 59 - .../HomeAssistant/AbstractDiscoverable.cs | 30 - .../HomeAssistant/Commands/AbstractCommand.cs | 74 -- .../HomeAssistant/Commands/CustomCommand.cs | 66 -- .../CustomCommands/HibernateCommand.cs | 10 - .../Commands/CustomCommands/LockCommand.cs | 10 - .../Commands/CustomCommands/LogOffCommand.cs | 10 - .../Commands/CustomCommands/RestartCommand.cs | 10 - .../CustomCommands/ShutdownCommand.cs | 10 - .../Commands/CustomCommands/SleepCommand.cs | 10 - .../HomeAssistant/Commands/InternalCommand.cs | 52 - .../InternalCommands/CustomExecutorCommand.cs | 74 -- .../HomeAssistant/Commands/KeyCommand.cs | 57 - .../Commands/KeyCommands/MediaMuteCommand.cs | 7 - .../Commands/KeyCommands/MediaNextCommand.cs | 7 - .../KeyCommands/MediaPlayPauseCommand.cs | 7 - .../KeyCommands/MediaPreviousCommand.cs | 7 - .../KeyCommands/MediaVolumeDownCommand.cs | 7 - .../KeyCommands/MediaVolumeUpCommand.cs | 7 - .../Commands/MultipleKeysCommand.cs | 59 - .../Commands/PowershellCommand.cs | 69 -- .../HomeAssistant/DiscoveryConfigModel.cs | 207 ---- .../Sensors/AbstractMultiValueSensor.cs | 67 -- .../Sensors/AbstractSingleValueSensor.cs | 85 -- .../GeneralSensors/MultiValue/AudioSensors.cs | 227 ---- .../MultiValue/BatterySensors.cs | 95 -- .../DataTypes/DataTypeBoolSensor.cs | 45 - .../DataTypes/DataTypeDoubleSensor.cs | 48 - .../MultiValue/DataTypes/DataTypeIntSensor.cs | 46 - .../DataTypes/DataTypeStringSensor.cs | 46 - .../MultiValue/DisplaySensors.cs | 103 -- .../MultiValue/NetworkSensors.cs | 291 ----- .../MultiValue/StorageSensors.cs | 127 -- .../MultiValue/WindowsUpdatesSensors.cs | 83 -- .../SingleValue/ActiveWindowSensor.cs | 44 - .../SingleValue/CurrentVolumeSensor.cs | 41 - .../GeneralSensors/SingleValue/DummySensor.cs | 24 - .../SingleValue/GpuLoadSensor.cs | 55 - .../SingleValue/GpuTemperatureSensor.cs | 56 - .../SingleValue/LastActiveSensor.cs | 67 -- .../SingleValue/LastBootSensor.cs | 30 - .../LastSystemStateChangeSensor.cs | 24 - .../SingleValue/LoggedUserSensor.cs | 32 - .../SingleValue/LoggedUsersSensor.cs | 274 ----- .../SingleValue/MicrophoneActiveSensor.cs | 94 -- .../SingleValue/NamedWindowSensor.cs | 35 - .../SingleValue/ProcessActiveSensor.cs | 48 - .../SingleValue/ServiceStateSensor.cs | 49 - .../SingleValue/SessionStateSensor.cs | 24 - .../UserNotificationStateSensor.cs | 37 - .../SingleValue/WebcamActiveSensor.cs | 97 -- .../SingleValue/CpuLoadSensor.cs | 21 - .../Sensors/PerformanceCounterSensor.cs | 68 -- .../HomeAssistant/Sensors/WmiQuerySensor.cs | 70 -- .../SingleValue/CurrentClockSpeedSensor.cs | 53 - .../SingleValue/MemoryUsageSensor.cs | 55 - .../Models/Internal/AudioSessionInfo.cs | 21 - .../Models/Internal/ConsoleResult.cs | 35 - .../Models/Internal/WindowsUpdateInfo.cs | 24 - src/HASS.Agent/HASSAgent/Program.cs | 116 -- .../HASSAgent/Properties/AssemblyInfo.cs | 35 - .../HASSAgent/Properties/Settings.Designer.cs | 26 - .../HASSAgent/Properties/Settings.settings | 5 - .../HASSAgent/Sensors/SensorsManager.cs | 373 ------ src/HASSAgent.sln | 32 + src/HASSAgent/Commands/CommandsManager.cs | 406 +++++++ .../Configuration/ExternalTools.Designer.cs | 86 +- .../Controls/Configuration/ExternalTools.cs | 66 +- .../Controls/Configuration/ExternalTools.resx | 65 ++ .../Configuration/General.Designer.cs | 122 +- .../Controls/Configuration/General.cs | 15 + .../Controls/Configuration/General.resx | 65 ++ .../HomeAssistantApi.Designer.cs | 55 +- .../Configuration/HomeAssistantApi.cs | 27 +- .../Configuration/HomeAssistantApi.resx | 62 +- .../Controls/Configuration/HotKey.Designer.cs | 29 +- .../Controls/Configuration/HotKey.cs | 10 + .../Controls/Configuration/HotKey.resx | 60 + .../Configuration/LocalStorage.Designer.cs | 104 +- .../Controls/Configuration/LocalStorage.cs | 17 +- .../Controls/Configuration/LocalStorage.resx | 60 + .../Configuration/Logging.Designer.cs | 100 ++ .../Controls/Configuration/Logging.cs | 15 + .../Controls/Configuration/Logging.resx | 63 + .../Controls/Configuration/MQTT.Designer.cs | 222 ++-- src/HASSAgent/Controls/Configuration/MQTT.cs | 59 + .../Controls/Configuration/MQTT.resx | 60 + .../Configuration/Notifications.Designer.cs | 209 ++++ .../Controls/Configuration/Notifications.cs | 66 ++ .../Controls/Configuration/Notifications.resx | 62 +- .../Configuration/Service.Designer.cs | 304 +++++ .../Controls/Configuration/Service.cs | 214 ++++ .../Controls/Configuration/Service.resx | 64 + .../Configuration/Startup.Designer.cs | 25 +- .../Controls/Configuration/Startup.cs | 29 +- .../Controls/Configuration/Startup.resx | 65 ++ .../Configuration/Updates.Designer.cs | 31 +- .../Controls/Configuration/Updates.cs | 10 + .../Controls/Configuration/Updates.resx | 62 +- .../Controls}/CustomGroupBox.cs | 9 +- .../Controls/Onboarding/1-Welcome.Designer.cs | 23 +- .../Controls/Onboarding/1-Welcome.cs | 5 +- .../Controls/Onboarding/1-Welcome.resx | 60 + .../Controls/Onboarding/2-Startup.Designer.cs | 15 +- .../Controls/Onboarding/2-Startup.cs | 5 +- .../Controls/Onboarding/2-Startup.resx | 60 + .../Onboarding/3-Notifications.Designer.cs | 142 +++ .../Controls/Onboarding/3-Notifications.cs | 24 + .../Controls/Onboarding/3-Notifications.resx | 60 + .../Onboarding/4-Integration.Designer.cs | 23 +- .../Controls/Onboarding/4-Integration.cs | 4 +- .../Controls/Onboarding/4-Integration.resx | 66 ++ .../Controls/Onboarding/5-API.Designer.cs | 35 +- .../HASSAgent/Controls/Onboarding/5-API.cs | 4 +- src/HASSAgent/Controls/Onboarding/5-API.resx | 65 ++ .../Controls/Onboarding/6-MQTT.Designer.cs | 157 +-- .../HASSAgent/Controls/Onboarding/6-MQTT.cs | 18 +- src/HASSAgent/Controls/Onboarding/6-MQTT.resx | 65 ++ .../Controls/Onboarding/7-HotKey.Designer.cs | 25 +- .../HASSAgent/Controls/Onboarding/7-HotKey.cs | 7 +- .../Controls/Onboarding/7-HotKey.resx | 60 + .../Controls/Onboarding/8-Updates.Designer.cs | 25 +- .../Controls/Onboarding/8-Updates.cs | 5 +- .../Controls/Onboarding/8-Updates.resx | 66 +- .../Controls/Onboarding/9-Done.Designer.cs | 22 +- .../HASSAgent/Controls/Onboarding/9-Done.cs | 4 +- src/HASSAgent/Controls/Onboarding/9-Done.resx | 69 ++ .../Controls/QuickActionControl.Designer.cs | 5 +- .../HASSAgent/Controls/QuickActionControl.cs | 50 +- .../Controls/QuickActionControl.resx | 60 + .../Controls/Service/Commands.Designer.cs | 272 +++++ src/HASSAgent/Controls/Service/Commands.cs | 223 ++++ src/HASSAgent/Controls/Service/Commands.resx | 88 ++ .../Controls/Service/Connect.Designer.cs | 214 ++++ src/HASSAgent/Controls/Service/Connect.cs | 210 ++++ src/HASSAgent/Controls/Service/Connect.resx | 60 + .../Controls/Service/General.Designer.cs | 490 ++++++++ src/HASSAgent/Controls/Service/General.cs | 414 +++++++ src/HASSAgent/Controls/Service/General.resx | 60 + .../Controls/Service/MQTT.Designer.cs | 517 +++++++++ src/HASSAgent/Controls/Service/MQTT.cs | 260 +++++ src/HASSAgent/Controls/Service/MQTT.resx | 60 + .../Controls/Service/Sensors.Designer.cs | 273 +++++ src/HASSAgent/Controls/Service/Sensors.cs | 223 ++++ src/HASSAgent/Controls/Service/Sensors.resx | 104 ++ .../HASSAgent/Enums/Component.cs | 3 +- .../HASSAgent/Enums/ComponentStatus.cs | 3 +- .../HASSAgent/Enums/HassAction.cs | 0 .../HASSAgent/Enums/HassDomain.cs | 0 .../HASSAgent/Enums/HassManagerStatus.cs | 0 .../HASSAgent/Enums/OnboardingStatus.cs | 0 src/HASSAgent/Enums/ServiceDesiredState.cs | 9 + src/HASSAgent/Extensions/RpcExtensions.cs | 225 ++++ src/HASSAgent/Extensions/SensorExtensions.cs | 44 + .../HASSAgent/Forms/About.Designer.cs | 274 +++-- src/{HASS.Agent => }/HASSAgent/Forms/About.cs | 31 +- .../HASSAgent/Forms/About.resx | 62 +- .../PortReservation.Designer.cs | 30 +- .../ChildApplications/PortReservation.cs | 17 +- .../ChildApplications/PortReservation.resx | 62 +- .../ChildApplications/PostUpdate.Designer.cs | 56 +- .../Forms/ChildApplications/PostUpdate.cs | 164 +++ .../Forms/ChildApplications/PostUpdate.resx | 62 +- .../ChildApplications/Restart.Designer.cs | 30 +- .../Forms/ChildApplications/Restart.cs | 23 +- .../Forms/ChildApplications/Restart.resx | 62 +- .../ServiceReinstall.Designer.cs | 133 +++ .../ChildApplications/ServiceReinstall.cs | 170 +++ .../ChildApplications/ServiceReinstall.resx | 87 ++ .../ServiceSetState.Designer.cs | 105 ++ .../ChildApplications/ServiceSetState.cs | 238 ++++ .../ChildApplications/ServiceSetState.resx | 87 ++ .../Forms/Commands/CommandsConfig.Designer.cs | 202 ++-- .../Forms/Commands/CommandsConfig.cs | 235 ++++ .../Forms/Commands/CommandsConfig.resx | 90 +- .../Forms/Commands/CommandsMod.Designer.cs | 298 +++-- .../HASSAgent/Forms/Commands/CommandsMod.cs | 284 +++-- .../HASSAgent/Forms/Commands/CommandsMod.resx | 115 +- .../HASSAgent/Forms/Configuration.Designer.cs | 256 ++-- .../HASSAgent/Forms/Configuration.cs | 71 +- .../HASSAgent/Forms/Configuration.resx | 62 +- .../HASSAgent/Forms/ExitDialog.Designer.cs | 14 +- .../HASSAgent/Forms/ExitDialog.cs | 12 +- .../HASSAgent/Forms/ExitDialog.resx | 62 +- .../HASSAgent/Forms/Help.Designer.cs | 57 +- src/{HASS.Agent => }/HASSAgent/Forms/Help.cs | 17 +- .../HASSAgent/Forms/Help.resx | 62 +- .../HASSAgent/Forms/Main.Designer.cs | 304 +++-- src/{HASS.Agent => }/HASSAgent/Forms/Main.cs | 101 +- .../HASSAgent/Forms/Main.resx | 62 +- .../HASSAgent/Forms/Onboarding.Designer.cs | 31 +- .../HASSAgent/Forms/Onboarding.cs | 11 +- .../HASSAgent/Forms/Onboarding.resx | 62 +- .../QuickActions/QuickActions.Designer.cs | 9 +- .../Forms/QuickActions/QuickActions.cs | 19 +- .../Forms/QuickActions/QuickActions.resx | 62 +- .../QuickActionsConfig.Designer.cs | 215 ++-- .../Forms/QuickActions/QuickActionsConfig.cs | 231 ++++ .../QuickActions/QuickActionsConfig.resx | 91 +- .../QuickActions/QuickActionsMod.Designer.cs | 64 +- .../Forms/QuickActions/QuickActionsMod.cs | 30 +- .../Forms/QuickActions/QuickActionsMod.resx | 62 +- .../Forms/Sensors/SensorsConfig.Designer.cs | 206 ++-- src/HASSAgent/Forms/Sensors/SensorsConfig.cs | 236 ++++ .../Forms/Sensors/SensorsConfig.resx | 91 +- .../Forms/Sensors/SensorsMod.Designer.cs | 512 ++++++++ .../HASSAgent/Forms/Sensors/SensorsMod.cs | 262 +++-- .../HASSAgent/Forms/Sensors/SensorsMod.resx | 115 +- .../Forms/Service/ServiceConfig.Designer.cs | 188 +++ src/HASSAgent/Forms/Service/ServiceConfig.cs | 113 ++ .../Forms/Service/ServiceConfig.resx | 87 ++ .../HASSAgent/Forms/UpdatePending.Designer.cs | 38 +- .../HASSAgent/Forms/UpdatePending.cs | 14 +- .../HASSAgent/Forms/UpdatePending.resx | 62 +- .../HASSAgent/Functions/CacheManager.cs | 6 +- .../Functions/CustomApplicationContext.cs | 7 +- .../HASSAgent/Functions/FirewallManager.cs | 8 +- .../HASSAgent/Functions/HelperFunctions.cs | 224 ++-- .../HASSAgent/Functions/HotKeyManager.cs | 28 +- .../HASSAgent/Functions/LaunchManager.cs | 39 +- src/HASSAgent/Functions/ListViewTheme.cs | 149 +++ .../HASSAgent/Functions/LoggingManager.cs | 62 +- .../HASSAgent/Functions/OnboardingManager.cs | 11 +- .../Functions/ServiceControllerManager.cs | 387 +++++++ src/HASSAgent/Functions/ServiceHelper.cs | 163 +++ .../HASSAgent/Functions/StorageManager.cs | 77 +- .../HASSAgent/Functions/SystemStateManager.cs | 30 +- .../HASSAgent/Functions/UpdateManager.cs | 11 +- src/HASSAgent/HASSAgent.csproj | 121 ++ src/HASSAgent/HASSAgent.csproj.DotSettings | 3 + src/HASSAgent/HASSAgent.csproj.user | 120 ++ .../HASSAgent/HomeAssistant/HassApiManager.cs | 94 +- src/{HASS.Agent => }/HASSAgent/LICENSE.rtf | 0 .../HASSAgent/Libraries/HADotNet.Core.dll | Bin .../HASSAgent/Libraries/HADotNet.Core.pdb | Bin .../HASSAgent/Libraries/HADotNet.Core.xml | 0 .../HASSAgent/Libraries/HotkeyListener.dll | Bin .../HASSAgent/Libraries/HotkeyListener.pdb | Bin .../Mqtt => HASSAgent/MQTT}/MqttManager.cs | 222 ++-- .../HASSAgent/Models/Config/AppSettings.cs | 35 +- .../InternalCommands/LaunchUrlCommand.cs | 2 +- .../PublishAllSensorsCommand.cs | 1 + .../Models/HomeAssistant/HassEntity.cs | 0 .../Models/HomeAssistant/Notification.cs | 0 .../HASSAgent/Models/Internal/Action.cs | 0 .../Models/Internal/CommandInfoCard.cs | 34 + .../Models/Internal/ComponentStatusUpdate.cs | 0 .../Models/Internal/PendingUpdate.cs | 7 +- .../HASSAgent/Models/Internal/QuickAction.cs | 8 +- .../Internal/QuickActionPanelControl.cs | 0 .../Models/Internal/SensorInfoCard.cs | 39 + .../HASSAgent/Models/Internal/UrlInfo.cs | 8 +- .../Notifications/NotifierConfiguration.cs | 0 .../Notifications/NotifierDeserialization.cs | 5 +- .../Notifications/NotifierEndpoints.cs | 4 +- .../Notifications/NotifierManager.cs | 51 +- src/HASSAgent/Program.cs | 246 ++++ .../Properties/Resources.Designer.cs | 170 +++ .../HASSAgent/Properties/Resources.resx | 51 + src/HASSAgent/Resources/agent_16.png | Bin 0 -> 584 bytes src/HASSAgent/Resources/agent_16_header.bmp | Bin 0 -> 824 bytes .../HASSAgent/Resources/bmac_logo.png | Bin .../HASSAgent/Resources/bmac_logo_32.png | Bin .../HASSAgent/Resources/discord_avatar.png | Bin .../HASSAgent/Resources/done_32.png | Bin .../HASSAgent/Resources/exit_24.png | Bin .../HASSAgent/Resources/exit_32.png | Bin .../HASSAgent/Resources/failed_32.png | Bin .../HASSAgent/Resources/gear_48.png | Bin .../HASSAgent/Resources/github_avatar.png | Bin src/HASSAgent/Resources/githubsponsors.png | Bin 0 -> 9340 bytes .../HASSAgent/Resources/hass_avatar.png | Bin .../HASSAgent/Resources/hide_32.png | Bin src/HASSAgent/Resources/hotkey_16.png | Bin 0 -> 341 bytes src/HASSAgent/Resources/hotkey_16_header.bmp | Bin 0 -> 824 bytes .../HASSAgent/Resources/logo_128.png | Bin .../HASSAgent/Resources/logo_256.png | Bin .../HASSAgent/Resources/logo_32.png | Bin src/HASSAgent/Resources/multivalue_16.png | Bin 0 -> 196 bytes .../Resources/multivalue_16_header.bmp | Bin 0 -> 824 bytes .../HASSAgent/Resources/qa_automate_225.png | Bin .../HASSAgent/Resources/qa_climate_225.png | Bin .../HASSAgent/Resources/qa_cover_225.png | Bin .../Resources/qa_inputboolean_225.png | Bin .../HASSAgent/Resources/qa_light_225.png | Bin .../Resources/qa_mediaplayer_225.png | Bin .../HASSAgent/Resources/qa_scene_225.png | Bin .../HASSAgent/Resources/qa_script_225.png | Bin .../HASSAgent/Resources/qa_switch_225.png | Bin .../HASSAgent/Resources/question_24.png | Bin .../HASSAgent/Resources/question_32.png | Bin .../HASSAgent/Resources/radar_48.png | Bin src/HASSAgent/Resources/refresh_16.png | Bin 0 -> 569 bytes src/HASSAgent/Resources/refresh_16_header.bmp | Bin 0 -> 824 bytes .../HASSAgent/Resources/remote_48.png | Bin src/HASSAgent/Resources/reset_24.png | Bin 0 -> 818 bytes .../HASSAgent/Resources/restart_32.png | Bin src/HASSAgent/Resources/service_16.png | Bin 0 -> 519 bytes src/HASSAgent/Resources/service_16_header.bmp | Bin 0 -> 824 bytes src/HASSAgent/Resources/service_48.png | Bin 0 -> 1200 bytes src/HASSAgent/Resources/shield_16.png | Bin 0 -> 420 bytes src/HASSAgent/Resources/shield_16_header.bmp | Bin 0 -> 824 bytes src/HASSAgent/Resources/show_24.png | Bin 0 -> 693 bytes .../HASSAgent/Resources/small_loader_32.gif | Bin .../HASSAgent/Resources/ti_exit_32.png | Bin .../HASSAgent/Resources/ti_gear_32.png | Bin .../HASSAgent/Resources/ti_radar_32.png | Bin .../HASSAgent/Resources/ti_remote_32.png | Bin .../HASSAgent/Resources/ti_update_32.png | Bin .../HASSAgent/Resources/ti_workflow_32.png | Bin .../HASSAgent/Resources/todo_32.png | Bin .../HASSAgent/Resources/update.png | Bin .../HASSAgent/Resources/workflow_48.png | Bin src/HASSAgent/Sensors/SensorsManager.cs | 559 +++++++++ .../Service/Protos/hassagentsatellite.proto | 144 +++ .../Service/Requests/RpcGetRequests.cs | 168 +++ .../Service/Requests/RpcSetRequests.cs | 179 +++ src/HASSAgent/Service/RpcClientService.cs | 101 ++ src/HASSAgent/Service/ServiceManager.cs | 119 ++ .../HASSAgent/Settings/SettingsManager.cs | 102 +- .../HASSAgent/Settings/StoredCommands.cs | 26 +- .../HASSAgent/Settings/StoredQuickActions.cs | 12 +- .../HASSAgent/Settings/StoredSensors.cs | 34 +- src/{HASS.Agent => }/HASSAgent/Variables.cs | 58 +- src/{HASS.Agent => }/HASSAgent/app.manifest | 18 +- src/{HASS.Agent => }/HASSAgent/hassagent.ico | Bin 379 files changed, 14906 insertions(+), 15194 deletions(-) delete mode 100644 src/CustomGroupBox/CustomGroupBox.sln delete mode 100644 src/CustomGroupBox/CustomGroupBox/CustomGroupBox.csproj delete mode 100644 src/CustomGroupBox/CustomGroupBox/Properties/AssemblyInfo.cs delete mode 100644 src/HASS.Agent/HASSAgent.sln delete mode 100644 src/HASS.Agent/HASSAgent/App.config delete mode 100644 src/HASS.Agent/HASSAgent/Commands/CommandsManager.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/General.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/General.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.Designer.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.Designer.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.cs delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.resx delete mode 100644 src/HASS.Agent/HASSAgent/Controls/QuickActionControl.resx delete mode 100644 src/HASS.Agent/HASSAgent/Enums/CommandType.cs delete mode 100644 src/HASS.Agent/HASSAgent/Enums/LockState.cs delete mode 100644 src/HASS.Agent/HASSAgent/Enums/MqttStatus.cs delete mode 100644 src/HASS.Agent/HASSAgent/Enums/SensorType.cs delete mode 100644 src/HASS.Agent/HASSAgent/Enums/SystemStateEvent.cs delete mode 100644 src/HASS.Agent/HASSAgent/Enums/UserNotificationState.cs delete mode 100644 src/HASS.Agent/HASSAgent/Forms/ChildApplications/PostUpdate.cs delete mode 100644 src/HASS.Agent/HASSAgent/Forms/Commands/CommandsConfig.cs delete mode 100644 src/HASS.Agent/HASSAgent/Forms/QuickActions/QuickActionsConfig.cs delete mode 100644 src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsConfig.cs delete mode 100644 src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsMod.Designer.cs delete mode 100644 src/HASS.Agent/HASSAgent/Functions/CommandLineManager.cs delete mode 100644 src/HASS.Agent/HASSAgent/Functions/PerformanceCounters.cs delete mode 100644 src/HASS.Agent/HASSAgent/Functions/PowershellManager.cs delete mode 100644 src/HASS.Agent/HASSAgent/Functions/ScheduledTasks.cs delete mode 100644 src/HASS.Agent/HASSAgent/Functions/SessionInfo.cs delete mode 100644 src/HASS.Agent/HASSAgent/Functions/WindowsUpdatesManager.cs delete mode 100644 src/HASS.Agent/HASSAgent/HASSAgent.csproj delete mode 100644 src/HASS.Agent/HASSAgent/Libraries/CustomGroupBox.dll delete mode 100644 src/HASS.Agent/HASSAgent/Libraries/CustomGroupBox.pdb delete mode 100644 src/HASS.Agent/HASSAgent/Models/Config/ConfiguredCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/Config/ConfiguredSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/AbstractDiscoverable.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/AbstractCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/HibernateCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LockCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LogOffCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/RestartCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/ShutdownCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/SleepCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/CustomExecutorCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaMuteCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaNextCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPlayPauseCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPreviousCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeDownCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeUpCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/MultipleKeysCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/PowershellCommand.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/DiscoveryConfigModel.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractMultiValueSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractSingleValueSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/AudioSensors.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/BatterySensors.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeBoolSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeDoubleSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeIntSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeStringSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DisplaySensors.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/NetworkSensors.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/StorageSensors.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/WindowsUpdatesSensors.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ActiveWindowSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/CurrentVolumeSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/DummySensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuLoadSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuTemperatureSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastActiveSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastBootSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastSystemStateChangeSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUserSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUsersSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/MicrophoneActiveSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/NamedWindowSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ProcessActiveSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ServiceStateSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/SessionStateSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/UserNotificationStateSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/WebcamActiveSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerfCounterSensors/SingleValue/CpuLoadSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerformanceCounterSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiQuerySensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/CurrentClockSpeedSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/MemoryUsageSensor.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/Internal/AudioSessionInfo.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/Internal/ConsoleResult.cs delete mode 100644 src/HASS.Agent/HASSAgent/Models/Internal/WindowsUpdateInfo.cs delete mode 100644 src/HASS.Agent/HASSAgent/Program.cs delete mode 100644 src/HASS.Agent/HASSAgent/Properties/AssemblyInfo.cs delete mode 100644 src/HASS.Agent/HASSAgent/Properties/Settings.Designer.cs delete mode 100644 src/HASS.Agent/HASSAgent/Properties/Settings.settings delete mode 100644 src/HASS.Agent/HASSAgent/Sensors/SensorsManager.cs create mode 100644 src/HASSAgent.sln create mode 100644 src/HASSAgent/Commands/CommandsManager.cs rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs (80%) rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/ExternalTools.cs (67%) create mode 100644 src/HASSAgent/Controls/Configuration/ExternalTools.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/General.Designer.cs (51%) create mode 100644 src/HASSAgent/Controls/Configuration/General.cs create mode 100644 src/HASSAgent/Controls/Configuration/General.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs (81%) rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/HomeAssistantApi.cs (75%) rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/HomeAssistantApi.resx (50%) rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/HotKey.Designer.cs (84%) create mode 100644 src/HASSAgent/Controls/Configuration/HotKey.cs create mode 100644 src/HASSAgent/Controls/Configuration/HotKey.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs (62%) rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/LocalStorage.cs (67%) create mode 100644 src/HASSAgent/Controls/Configuration/LocalStorage.resx create mode 100644 src/HASSAgent/Controls/Configuration/Logging.Designer.cs create mode 100644 src/HASSAgent/Controls/Configuration/Logging.cs create mode 100644 src/HASSAgent/Controls/Configuration/Logging.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/MQTT.Designer.cs (68%) create mode 100644 src/HASSAgent/Controls/Configuration/MQTT.cs create mode 100644 src/HASSAgent/Controls/Configuration/MQTT.resx create mode 100644 src/HASSAgent/Controls/Configuration/Notifications.Designer.cs create mode 100644 src/HASSAgent/Controls/Configuration/Notifications.cs rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/Notifications.resx (50%) create mode 100644 src/HASSAgent/Controls/Configuration/Service.Designer.cs create mode 100644 src/HASSAgent/Controls/Configuration/Service.cs create mode 100644 src/HASSAgent/Controls/Configuration/Service.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/Startup.Designer.cs (84%) rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/Startup.cs (76%) create mode 100644 src/HASSAgent/Controls/Configuration/Startup.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/Updates.Designer.cs (80%) create mode 100644 src/HASSAgent/Controls/Configuration/Updates.cs rename src/{HASS.Agent => }/HASSAgent/Controls/Configuration/Updates.resx (50%) rename src/{CustomGroupBox/CustomGroupBox => HASSAgent/Controls}/CustomGroupBox.cs (83%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs (84%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/1-Welcome.cs (81%) create mode 100644 src/HASSAgent/Controls/Onboarding/1-Welcome.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs (89%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/2-Startup.cs (93%) create mode 100644 src/HASSAgent/Controls/Onboarding/2-Startup.resx create mode 100644 src/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs create mode 100644 src/HASSAgent/Controls/Onboarding/3-Notifications.cs create mode 100644 src/HASSAgent/Controls/Onboarding/3-Notifications.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs (83%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/4-Integration.cs (82%) create mode 100644 src/HASSAgent/Controls/Onboarding/4-Integration.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/5-API.Designer.cs (86%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/5-API.cs (94%) create mode 100644 src/HASSAgent/Controls/Onboarding/5-API.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs (65%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/6-MQTT.cs (80%) create mode 100644 src/HASSAgent/Controls/Onboarding/6-MQTT.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs (87%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/7-HotKey.cs (91%) create mode 100644 src/HASSAgent/Controls/Onboarding/7-HotKey.resx rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs (86%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/8-Updates.cs (85%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/8-Updates.resx (52%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/9-Done.Designer.cs (84%) rename src/{HASS.Agent => }/HASSAgent/Controls/Onboarding/9-Done.cs (81%) create mode 100644 src/HASSAgent/Controls/Onboarding/9-Done.resx rename src/{HASS.Agent => }/HASSAgent/Controls/QuickActionControl.Designer.cs (91%) rename src/{HASS.Agent => }/HASSAgent/Controls/QuickActionControl.cs (70%) create mode 100644 src/HASSAgent/Controls/QuickActionControl.resx create mode 100644 src/HASSAgent/Controls/Service/Commands.Designer.cs create mode 100644 src/HASSAgent/Controls/Service/Commands.cs create mode 100644 src/HASSAgent/Controls/Service/Commands.resx create mode 100644 src/HASSAgent/Controls/Service/Connect.Designer.cs create mode 100644 src/HASSAgent/Controls/Service/Connect.cs create mode 100644 src/HASSAgent/Controls/Service/Connect.resx create mode 100644 src/HASSAgent/Controls/Service/General.Designer.cs create mode 100644 src/HASSAgent/Controls/Service/General.cs create mode 100644 src/HASSAgent/Controls/Service/General.resx create mode 100644 src/HASSAgent/Controls/Service/MQTT.Designer.cs create mode 100644 src/HASSAgent/Controls/Service/MQTT.cs create mode 100644 src/HASSAgent/Controls/Service/MQTT.resx create mode 100644 src/HASSAgent/Controls/Service/Sensors.Designer.cs create mode 100644 src/HASSAgent/Controls/Service/Sensors.cs create mode 100644 src/HASSAgent/Controls/Service/Sensors.resx rename src/{HASS.Agent => }/HASSAgent/Enums/Component.cs (78%) rename src/{HASS.Agent => }/HASSAgent/Enums/ComponentStatus.cs (75%) rename src/{HASS.Agent => }/HASSAgent/Enums/HassAction.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Enums/HassDomain.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Enums/HassManagerStatus.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Enums/OnboardingStatus.cs (100%) create mode 100644 src/HASSAgent/Enums/ServiceDesiredState.cs create mode 100644 src/HASSAgent/Extensions/RpcExtensions.cs create mode 100644 src/HASSAgent/Extensions/SensorExtensions.cs rename src/{HASS.Agent => }/HASSAgent/Forms/About.Designer.cs (67%) rename src/{HASS.Agent => }/HASSAgent/Forms/About.cs (70%) rename src/{HASS.Agent => }/HASSAgent/Forms/About.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/PortReservation.Designer.cs (83%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/PortReservation.cs (87%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/PortReservation.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/PostUpdate.Designer.cs (71%) create mode 100644 src/HASSAgent/Forms/ChildApplications/PostUpdate.cs rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/PostUpdate.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/Restart.Designer.cs (83%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/Restart.cs (79%) rename src/{HASS.Agent => }/HASSAgent/Forms/ChildApplications/Restart.resx (61%) create mode 100644 src/HASSAgent/Forms/ChildApplications/ServiceReinstall.Designer.cs create mode 100644 src/HASSAgent/Forms/ChildApplications/ServiceReinstall.cs create mode 100644 src/HASSAgent/Forms/ChildApplications/ServiceReinstall.resx create mode 100644 src/HASSAgent/Forms/ChildApplications/ServiceSetState.Designer.cs create mode 100644 src/HASSAgent/Forms/ChildApplications/ServiceSetState.cs create mode 100644 src/HASSAgent/Forms/ChildApplications/ServiceSetState.resx rename src/{HASS.Agent => }/HASSAgent/Forms/Commands/CommandsConfig.Designer.cs (53%) create mode 100644 src/HASSAgent/Forms/Commands/CommandsConfig.cs rename src/{HASS.Agent => }/HASSAgent/Forms/Commands/CommandsConfig.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/Commands/CommandsMod.Designer.cs (51%) rename src/{HASS.Agent => }/HASSAgent/Forms/Commands/CommandsMod.cs (69%) rename src/{HASS.Agent => }/HASSAgent/Forms/Commands/CommandsMod.resx (52%) rename src/{HASS.Agent => }/HASSAgent/Forms/Configuration.Designer.cs (75%) rename src/{HASS.Agent => }/HASSAgent/Forms/Configuration.cs (87%) rename src/{HASS.Agent => }/HASSAgent/Forms/Configuration.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/ExitDialog.Designer.cs (93%) rename src/{HASS.Agent => }/HASSAgent/Forms/ExitDialog.cs (80%) rename src/{HASS.Agent => }/HASSAgent/Forms/ExitDialog.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/Help.Designer.cs (87%) rename src/{HASS.Agent => }/HASSAgent/Forms/Help.cs (85%) rename src/{HASS.Agent => }/HASSAgent/Forms/Help.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/Main.Designer.cs (75%) rename src/{HASS.Agent => }/HASSAgent/Forms/Main.cs (86%) rename src/{HASS.Agent => }/HASSAgent/Forms/Main.resx (70%) rename src/{HASS.Agent => }/HASSAgent/Forms/Onboarding.Designer.cs (88%) rename src/{HASS.Agent => }/HASSAgent/Forms/Onboarding.cs (84%) rename src/{HASS.Agent => }/HASSAgent/Forms/Onboarding.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActions.Designer.cs (90%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActions.cs (93%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActions.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActionsConfig.Designer.cs (57%) create mode 100644 src/HASSAgent/Forms/QuickActions/QuickActionsConfig.cs rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActionsConfig.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActionsMod.Designer.cs (85%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActionsMod.cs (93%) rename src/{HASS.Agent => }/HASSAgent/Forms/QuickActions/QuickActionsMod.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Forms/Sensors/SensorsConfig.Designer.cs (53%) create mode 100644 src/HASSAgent/Forms/Sensors/SensorsConfig.cs rename src/{HASS.Agent => }/HASSAgent/Forms/Sensors/SensorsConfig.resx (61%) create mode 100644 src/HASSAgent/Forms/Sensors/SensorsMod.Designer.cs rename src/{HASS.Agent => }/HASSAgent/Forms/Sensors/SensorsMod.cs (62%) rename src/{HASS.Agent => }/HASSAgent/Forms/Sensors/SensorsMod.resx (52%) create mode 100644 src/HASSAgent/Forms/Service/ServiceConfig.Designer.cs create mode 100644 src/HASSAgent/Forms/Service/ServiceConfig.cs create mode 100644 src/HASSAgent/Forms/Service/ServiceConfig.resx rename src/{HASS.Agent => }/HASSAgent/Forms/UpdatePending.Designer.cs (88%) rename src/{HASS.Agent => }/HASSAgent/Forms/UpdatePending.cs (90%) rename src/{HASS.Agent => }/HASSAgent/Forms/UpdatePending.resx (61%) rename src/{HASS.Agent => }/HASSAgent/Functions/CacheManager.cs (94%) rename src/{HASS.Agent => }/HASSAgent/Functions/CustomApplicationContext.cs (90%) rename src/{HASS.Agent => }/HASSAgent/Functions/FirewallManager.cs (88%) rename src/{HASS.Agent => }/HASSAgent/Functions/HelperFunctions.cs (77%) rename src/{HASS.Agent => }/HASSAgent/Functions/HotKeyManager.cs (81%) rename src/{HASS.Agent => }/HASSAgent/Functions/LaunchManager.cs (56%) create mode 100644 src/HASSAgent/Functions/ListViewTheme.cs rename src/{HASS.Agent => }/HASSAgent/Functions/LoggingManager.cs (77%) rename src/{HASS.Agent => }/HASSAgent/Functions/OnboardingManager.cs (95%) create mode 100644 src/HASSAgent/Functions/ServiceControllerManager.cs create mode 100644 src/HASSAgent/Functions/ServiceHelper.cs rename src/{HASS.Agent => }/HASSAgent/Functions/StorageManager.cs (78%) rename src/{HASS.Agent => }/HASSAgent/Functions/SystemStateManager.cs (85%) rename src/{HASS.Agent => }/HASSAgent/Functions/UpdateManager.cs (95%) create mode 100644 src/HASSAgent/HASSAgent.csproj create mode 100644 src/HASSAgent/HASSAgent.csproj.DotSettings create mode 100644 src/HASSAgent/HASSAgent.csproj.user rename src/{HASS.Agent => }/HASSAgent/HomeAssistant/HassApiManager.cs (87%) rename src/{HASS.Agent => }/HASSAgent/LICENSE.rtf (100%) rename src/{HASS.Agent => }/HASSAgent/Libraries/HADotNet.Core.dll (100%) rename src/{HASS.Agent => }/HASSAgent/Libraries/HADotNet.Core.pdb (100%) rename src/{HASS.Agent => }/HASSAgent/Libraries/HADotNet.Core.xml (100%) rename src/{HASS.Agent => }/HASSAgent/Libraries/HotkeyListener.dll (100%) rename src/{HASS.Agent => }/HASSAgent/Libraries/HotkeyListener.pdb (100%) rename src/{HASS.Agent/HASSAgent/Mqtt => HASSAgent/MQTT}/MqttManager.cs (75%) rename src/{HASS.Agent => }/HASSAgent/Models/Config/AppSettings.cs (57%) rename src/{HASS.Agent => }/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs (91%) rename src/{HASS.Agent => }/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs (87%) rename src/{HASS.Agent => }/HASSAgent/Models/HomeAssistant/HassEntity.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Models/HomeAssistant/Notification.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Models/Internal/Action.cs (100%) create mode 100644 src/HASSAgent/Models/Internal/CommandInfoCard.cs rename src/{HASS.Agent => }/HASSAgent/Models/Internal/ComponentStatusUpdate.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Models/Internal/PendingUpdate.cs (76%) rename src/{HASS.Agent => }/HASSAgent/Models/Internal/QuickAction.cs (81%) rename src/{HASS.Agent => }/HASSAgent/Models/Internal/QuickActionPanelControl.cs (100%) create mode 100644 src/HASSAgent/Models/Internal/SensorInfoCard.cs rename src/{HASS.Agent => }/HASSAgent/Models/Internal/UrlInfo.cs (51%) rename src/{HASS.Agent => }/HASSAgent/Notifications/NotifierConfiguration.cs (100%) rename src/{HASS.Agent => }/HASSAgent/Notifications/NotifierDeserialization.cs (86%) rename src/{HASS.Agent => }/HASSAgent/Notifications/NotifierEndpoints.cs (91%) rename src/{HASS.Agent => }/HASSAgent/Notifications/NotifierManager.cs (85%) create mode 100644 src/HASSAgent/Program.cs rename src/{HASS.Agent => }/HASSAgent/Properties/Resources.Designer.cs (70%) rename src/{HASS.Agent => }/HASSAgent/Properties/Resources.resx (76%) create mode 100644 src/HASSAgent/Resources/agent_16.png create mode 100644 src/HASSAgent/Resources/agent_16_header.bmp rename src/{HASS.Agent => }/HASSAgent/Resources/bmac_logo.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/bmac_logo_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/discord_avatar.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/done_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/exit_24.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/exit_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/failed_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/gear_48.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/github_avatar.png (100%) create mode 100644 src/HASSAgent/Resources/githubsponsors.png rename src/{HASS.Agent => }/HASSAgent/Resources/hass_avatar.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/hide_32.png (100%) create mode 100644 src/HASSAgent/Resources/hotkey_16.png create mode 100644 src/HASSAgent/Resources/hotkey_16_header.bmp rename src/{HASS.Agent => }/HASSAgent/Resources/logo_128.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/logo_256.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/logo_32.png (100%) create mode 100644 src/HASSAgent/Resources/multivalue_16.png create mode 100644 src/HASSAgent/Resources/multivalue_16_header.bmp rename src/{HASS.Agent => }/HASSAgent/Resources/qa_automate_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_climate_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_cover_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_inputboolean_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_light_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_mediaplayer_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_scene_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_script_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/qa_switch_225.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/question_24.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/question_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/radar_48.png (100%) create mode 100644 src/HASSAgent/Resources/refresh_16.png create mode 100644 src/HASSAgent/Resources/refresh_16_header.bmp rename src/{HASS.Agent => }/HASSAgent/Resources/remote_48.png (100%) create mode 100644 src/HASSAgent/Resources/reset_24.png rename src/{HASS.Agent => }/HASSAgent/Resources/restart_32.png (100%) create mode 100644 src/HASSAgent/Resources/service_16.png create mode 100644 src/HASSAgent/Resources/service_16_header.bmp create mode 100644 src/HASSAgent/Resources/service_48.png create mode 100644 src/HASSAgent/Resources/shield_16.png create mode 100644 src/HASSAgent/Resources/shield_16_header.bmp create mode 100644 src/HASSAgent/Resources/show_24.png rename src/{HASS.Agent => }/HASSAgent/Resources/small_loader_32.gif (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/ti_exit_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/ti_gear_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/ti_radar_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/ti_remote_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/ti_update_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/ti_workflow_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/todo_32.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/update.png (100%) rename src/{HASS.Agent => }/HASSAgent/Resources/workflow_48.png (100%) create mode 100644 src/HASSAgent/Sensors/SensorsManager.cs create mode 100644 src/HASSAgent/Service/Protos/hassagentsatellite.proto create mode 100644 src/HASSAgent/Service/Requests/RpcGetRequests.cs create mode 100644 src/HASSAgent/Service/Requests/RpcSetRequests.cs create mode 100644 src/HASSAgent/Service/RpcClientService.cs create mode 100644 src/HASSAgent/Service/ServiceManager.cs rename src/{HASS.Agent => }/HASSAgent/Settings/SettingsManager.cs (77%) rename src/{HASS.Agent => }/HASSAgent/Settings/StoredCommands.cs (92%) rename src/{HASS.Agent => }/HASSAgent/Settings/StoredQuickActions.cs (91%) rename src/{HASS.Agent => }/HASSAgent/Settings/StoredSensors.cs (93%) rename src/{HASS.Agent => }/HASSAgent/Variables.cs (59%) rename src/{HASS.Agent => }/HASSAgent/app.manifest (84%) rename src/{HASS.Agent => }/HASSAgent/hassagent.ico (100%) diff --git a/src/CustomGroupBox/CustomGroupBox.sln b/src/CustomGroupBox/CustomGroupBox.sln deleted file mode 100644 index afd821c..0000000 --- a/src/CustomGroupBox/CustomGroupBox.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31729.503 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomGroupBox", "CustomGroupBox\CustomGroupBox.csproj", "{2AD41F9E-E8D2-4FBF-B5D6-02427DA81BD7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2AD41F9E-E8D2-4FBF-B5D6-02427DA81BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2AD41F9E-E8D2-4FBF-B5D6-02427DA81BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2AD41F9E-E8D2-4FBF-B5D6-02427DA81BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2AD41F9E-E8D2-4FBF-B5D6-02427DA81BD7}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - VisualSVNWorkingCopyRoot = . - SolutionGuid = {7DB55DEF-70F0-49F5-B5E3-93E2534AEDED} - EndGlobalSection -EndGlobal diff --git a/src/CustomGroupBox/CustomGroupBox/CustomGroupBox.csproj b/src/CustomGroupBox/CustomGroupBox/CustomGroupBox.csproj deleted file mode 100644 index 2bbd362..0000000 --- a/src/CustomGroupBox/CustomGroupBox/CustomGroupBox.csproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Debug - AnyCPU - {2AD41F9E-E8D2-4FBF-B5D6-02427DA81BD7} - Library - CustomGroupBox - CustomGroupBox - v4.8 - 512 - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - Component - - - - - - \ No newline at end of file diff --git a/src/CustomGroupBox/CustomGroupBox/Properties/AssemblyInfo.cs b/src/CustomGroupBox/CustomGroupBox/Properties/AssemblyInfo.cs deleted file mode 100644 index 03b74d0..0000000 --- a/src/CustomGroupBox/CustomGroupBox/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -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("CustomGroupBox")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("LAB02 Research")] -[assembly: AssemblyProduct("CustomGroupBox")] -[assembly: AssemblyCopyright("Copyright © LAB02 Research 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("2ad41f9e-e8d2-4fbf-b5d6-02427da81bd7")] - -// 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("2021.12.1.0")] -[assembly: AssemblyFileVersion("2021.12.1.0")] diff --git a/src/HASS.Agent/HASSAgent.sln b/src/HASS.Agent/HASSAgent.sln deleted file mode 100644 index dacb123..0000000 --- a/src/HASS.Agent/HASSAgent.sln +++ /dev/null @@ -1,32 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# 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 -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Debug|x64.ActiveCfg = Debug|x64 - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Debug|x64.Build.0 = Debug|x64 - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Release|Any CPU.Build.0 = Release|Any CPU - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Release|x64.ActiveCfg = Release|x64 - {407FFF5A-97EA-429E-BD5E-81D93240A1BD}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7C2BA89F-434B-40F9-93F5-DD62C005ABFE} - VisualSVNWorkingCopyRoot = . - EndGlobalSection -EndGlobal diff --git a/src/HASS.Agent/HASSAgent/App.config b/src/HASS.Agent/HASSAgent/App.config deleted file mode 100644 index 387d978..0000000 --- a/src/HASS.Agent/HASSAgent/App.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Commands/CommandsManager.cs b/src/HASS.Agent/HASSAgent/Commands/CommandsManager.cs deleted file mode 100644 index 632eaaa..0000000 --- a/src/HASS.Agent/HASSAgent/Commands/CommandsManager.cs +++ /dev/null @@ -1,281 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using HASSAgent.Enums; -using HASSAgent.Models.Config; -using HASSAgent.Mqtt; -using HASSAgent.Settings; -using Serilog; - -namespace HASSAgent.Commands -{ - /// - /// Continuously performs command autodiscovery and state publishing - /// - internal static class CommandsManager - { - private static readonly Dictionary CommandInfo = new Dictionary(); - - private static bool _active = true; - private static bool _pause; - - private static DateTime _lastAutoDiscoPublish = DateTime.MinValue; - - /// - /// Initializes the command manager - /// - internal static async void Initialize() - { - // load command descriptions - LoadCommandInfo(); - - // wait while mqtt's connecting - while (MqttManager.GetStatus() == MqttStatus.Connecting) await Task.Delay(250); - - // start background processing - _ = Task.Run(Process); - } - - /// - /// Stop processing commands - /// - internal static void Stop() => _active = false; - - /// - /// Pause processing commands - /// - internal static void Pause() => _pause = true; - - /// - /// Resume processing commands - /// - internal static void Unpause() => _pause = false; - - /// - /// Unpublishes all commands - /// - /// - internal static async Task UnpublishAllCommands() - { - // unpublish the autodisco's - if (!CommandsPresent()) return; - foreach (var command in Variables.Commands) - { - await command.UnPublishAutoDiscoveryConfigAsync(); - await MqttManager.UnubscribeAsync(command); - } - } - - /// - /// Generates new ID's for all commands - /// - internal static void ResetCommandIds() - { - if (!CommandsPresent()) return; - foreach (var command in Variables.Commands) command.Id = Guid.NewGuid().ToString(); - - StoredCommands.Store(); - } - - /// - /// Continuously processes commands (autodiscovery, state) - /// - private static async void Process() - { - var firstRun = true; - var subscribed = false; - - while (_active) - { - try - { - if (firstRun) - { - // 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)); - } - else await Task.Delay(TimeSpan.FromSeconds(30)); - - // are we paused? - if (_pause) continue; - - // is mqtt available? - if (MqttManager.GetStatus() != MqttStatus.Connected) - { - // nothing to do - continue; - } - - // we're starting the first real run - firstRun = false; - - // do we have commands? - if (!CommandsPresent()) continue; - - // publish availability & sensor autodisco's every 30 sec - if ((DateTime.Now - _lastAutoDiscoPublish).TotalSeconds > 30) - { - // let hass know we're still here - await MqttManager.AnnounceAvailabilityAsync(); - - // 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(); - } - - // are we subscribed? - if (!subscribed) - { - 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; - } - - // log moment - _lastAutoDiscoPublish = DateTime.Now; - } - - // 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] Error while publishing: {err}", ex.Message); - } - } - } - - /// - /// Stores the provided commands, and (re)publishes them - /// - /// - /// - /// - internal static async Task StoreAsync(List commands, List toBeDeletedCommands = null) - { - if (toBeDeletedCommands == null) toBeDeletedCommands = new List(); - - 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(); - } - } - - private static bool CommandsPresent() => Variables.Commands != null && Variables.Commands.Any(); - - /// - /// Returns default information for the specified command type - /// - /// - /// - internal static string GetCommandDefaultInfo(CommandType type) - { - return !CommandInfo.ContainsKey(type) ? "Unknown command, make sure HASS.Agent has finished booting up." : CommandInfo[type]; - } - - /// - /// Loads info regarding the various command types - /// - 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."); - CommandInfo.Add(CommandType.PowershellCommand, "Execute a Powershell command or script.\r\n\r\nYou can either provide the location of a script (*.ps1), or a single-line command.\r\n\r\nThis will run without special elevation."); - CommandInfo.Add(CommandType.MediaPlayPauseCommand, "Simulates 'media playpause' key."); - CommandInfo.Add(CommandType.MediaNextCommand, "Simulates 'media next' key."); - CommandInfo.Add(CommandType.MediaPreviousCommand, "Simulates 'media previous' key."); - CommandInfo.Add(CommandType.MediaVolumeUpCommand, "Simulates 'volume up' key."); - 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\nIf you need more keys and/or modifiers like CTRL, use the MultipleKeys command."); - 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."); - CommandInfo.Add(CommandType.MultipleKeysCommand, "Simulates pressing mulitple keys.\r\n\r\nYou need to put [ ] between every key, otherwise HASS.Agent can't tell them apart. So say you want to press X TAB Y SHIFT-Z, it'd be [X] [{TAB}] [Y] [+Z].\r\n\r\nThere are a few tricks you can use:\r\n\r\n- Special keys go between { }, like {TAB} or {UP}\r\n\r\n- Put a + in front of a key to add SHIFT, ^ for CTRL and % for ALT. So, +C is SHIFT-C. Or, +(CD) is SHIFT-C and SHIFT-D, while +CD is SHIFT-C and D\r\n\r\n- For multiple presses, use {z 15}, which means Z will get pressed 15 times.\r\n\r\nMore info: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys"); - } - } -} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.resx deleted file mode 100644 index 5b7adf9..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.resx +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - By default, HASS.Agent will launch URLs using your default browser. If you want, you can also -configure a specific browser. Additionally, you can configure the arguments used to launch -in private mode. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/General.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/General.cs deleted file mode 100644 index 27f3680..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/General.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace HASSAgent.Controls.Configuration -{ - public partial class General : UserControl - { - public General() - { - InitializeComponent(); - - TbDisconnectGrace.Culture = CultureInfo.InstalledUICulture; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/General.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/General.resx deleted file mode 100644 index 4960c02..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/General.resx +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Important: if you change this value, HASS.Agent will unpublish all your sensors and commands -and force a restart of itself, so they can be republished under the new device name. -Your automations and scripts will keep working. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.cs deleted file mode 100644 index f3c5c7d..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace HASSAgent.Controls.Configuration -{ - public partial class HotKey : UserControl - { - public HotKey() - { - InitializeComponent(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.Designer.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.Designer.cs deleted file mode 100644 index e9fec7b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.Designer.cs +++ /dev/null @@ -1,118 +0,0 @@ -namespace HASSAgent.Controls.Configuration -{ - partial class Logging - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Logging)); - this.LblCoderr = new System.Windows.Forms.Label(); - this.label22 = new System.Windows.Forms.Label(); - this.CbExceptionReporting = new System.Windows.Forms.CheckBox(); - this.label23 = new System.Windows.Forms.Label(); - this.CbExtendedLogging = new System.Windows.Forms.CheckBox(); - this.SuspendLayout(); - // - // LblCoderr - // - this.LblCoderr.AutoSize = true; - this.LblCoderr.Cursor = System.Windows.Forms.Cursors.Hand; - this.LblCoderr.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblCoderr.Location = new System.Drawing.Point(632, 426); - this.LblCoderr.Name = "LblCoderr"; - this.LblCoderr.Size = new System.Drawing.Size(49, 17); - this.LblCoderr.TabIndex = 34; - this.LblCoderr.Text = "Coderr"; - this.LblCoderr.Click += new System.EventHandler(this.LblCoderr_Click); - // - // label22 - // - this.label22.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label22.Location = new System.Drawing.Point(110, 194); - this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(535, 124); - this.label22.TabIndex = 33; - this.label22.Text = resources.GetString("label22.Text"); - // - // CbExceptionReporting - // - this.CbExceptionReporting.AutoSize = true; - this.CbExceptionReporting.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbExceptionReporting.Location = new System.Drawing.Point(113, 331); - this.CbExceptionReporting.Name = "CbExceptionReporting"; - this.CbExceptionReporting.Size = new System.Drawing.Size(185, 21); - this.CbExceptionReporting.TabIndex = 32; - this.CbExceptionReporting.Text = "enable exception reporting"; - this.CbExceptionReporting.UseVisualStyleBackColor = true; - // - // label23 - // - this.label23.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label23.Location = new System.Drawing.Point(110, 40); - this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(535, 82); - this.label23.TabIndex = 31; - this.label23.Text = resources.GetString("label23.Text"); - // - // CbExtendedLogging - // - this.CbExtendedLogging.AutoSize = true; - this.CbExtendedLogging.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbExtendedLogging.Location = new System.Drawing.Point(113, 125); - this.CbExtendedLogging.Name = "CbExtendedLogging"; - this.CbExtendedLogging.Size = new System.Drawing.Size(173, 21); - this.CbExtendedLogging.TabIndex = 30; - this.CbExtendedLogging.Text = "enable extended logging"; - this.CbExtendedLogging.UseVisualStyleBackColor = true; - // - // Logging - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); - this.Controls.Add(this.LblCoderr); - this.Controls.Add(this.label22); - this.Controls.Add(this.CbExceptionReporting); - this.Controls.Add(this.label23); - this.Controls.Add(this.CbExtendedLogging); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.Margin = new System.Windows.Forms.Padding(4); - this.Name = "Logging"; - this.Size = new System.Drawing.Size(700, 457); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - private System.Windows.Forms.Label label22; - private System.Windows.Forms.Label label23; - internal System.Windows.Forms.Label LblCoderr; - internal System.Windows.Forms.CheckBox CbExceptionReporting; - internal System.Windows.Forms.CheckBox CbExtendedLogging; - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.cs deleted file mode 100644 index 011a01c..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Functions; - -namespace HASSAgent.Controls.Configuration -{ - public partial class Logging : UserControl - { - public Logging() - { - InitializeComponent(); - } - - private void LblCoderr_Click(object sender, EventArgs e) => HelperFunctions.LaunchUrl("https://coderr.io"); - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.resx deleted file mode 100644 index 83cc970..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Logging.resx +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - HASS.Agent can use the excellent Coderr platform to gather error reports. This way, it becomes easier to catch and fix bugs. However, there is a chance that machine-specific info gets sent as well (like machinename, or username). - -Only enable if you're aware of this and don't mind. -Note: only exceptions are logged, nothing else, no telemetry, no periodic information, nothing. - - - Extended logging provides more verbose and in-depth logging, in case the default logging isn't sufficient. Please note that enabling this can cause the logfiles to grow large, and should only be used when you suspect something's wrong with HASS.Agent itself or when asked by the developers. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.cs deleted file mode 100644 index c475b47..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace HASSAgent.Controls.Configuration -{ - // ReSharper disable once InconsistentNaming - public partial class MQTT : UserControl - { - public MQTT() - { - InitializeComponent(); - - TbIntMqttPort.Culture = CultureInfo.InstalledUICulture; - } - - private void TbMqttRootCertificate_DoubleClick(object sender, EventArgs e) - { - using (var dialog = new OpenFileDialog()) - { - dialog.CheckFileExists = true; - dialog.Multiselect = false; - dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) return; - - TbMqttRootCertificate.Text = dialog.FileName; - } - } - - private void TbMqttClientCertificate_DoubleClick(object sender, EventArgs e) - { - using (var dialog = new OpenFileDialog()) - { - dialog.CheckFileExists = true; - dialog.Multiselect = false; - dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) return; - - TbMqttClientCertificate.Text = dialog.FileName; - } - } - - private void BtnMqttClearConfig_Click(object sender, EventArgs e) - { - TbMqttAddress.Text = string.Empty; - TbIntMqttPort.IntegerValue = 1883; - CbMqttTls.CheckState = CheckState.Unchecked; - TbMqttUsername.Text = string.Empty; - TbMqttPassword.Text = string.Empty; - TbMqttDiscoveryPrefix.Text = "homeassistant"; - TbMqttClientId.Text = string.Empty; - TbMqttRootCertificate.Text = string.Empty; - TbMqttClientCertificate.Text = string.Empty; - CbAllowUntrustedCertificates.CheckState = CheckState.Checked; - CbUseRetainFlag.CheckState = CheckState.Checked; - } - - private void MQTT_Load(object sender, EventArgs e) - { - // - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.Designer.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.Designer.cs deleted file mode 100644 index b6f1c30..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.Designer.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System.Globalization; - -namespace HASSAgent.Controls.Configuration -{ - partial class Notifications - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Notifications)); - this.label18 = new System.Windows.Forms.Label(); - this.label12 = new System.Windows.Forms.Label(); - this.TbIntNotifierApiPort = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); - this.BtnNotificationsReadme = new Syncfusion.WinForms.Controls.SfButton(); - this.label1 = new System.Windows.Forms.Label(); - this.CbAcceptNotifications = new System.Windows.Forms.CheckBox(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntNotifierApiPort)).BeginInit(); - this.SuspendLayout(); - // - // label18 - // - this.label18.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label18.Location = new System.Drawing.Point(27, 217); - this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(393, 156); - this.label18.TabIndex = 37; - this.label18.Text = resources.GetString("label18.Text"); - // - // label12 - // - this.label12.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label12.Location = new System.Drawing.Point(27, 19); - this.label12.Name = "label12"; - this.label12.Size = new System.Drawing.Size(677, 58); - this.label12.TabIndex = 36; - this.label12.Text = "HASS.Agent can receive notifications from Home Assistant, using text and/or image" + - "s.\r\n\r\n"; - // - // TbIntNotifierApiPort - // - this.TbIntNotifierApiPort.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntNotifierApiPort.BeforeTouchSize = new System.Drawing.Size(92, 25); - this.TbIntNotifierApiPort.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbIntNotifierApiPort.CurrentCultureRefresh = true; - this.TbIntNotifierApiPort.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbIntNotifierApiPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.IntegerValue = ((long)(1883)); - this.TbIntNotifierApiPort.Location = new System.Drawing.Point(160, 98); - this.TbIntNotifierApiPort.MaxValue = ((long)(66000)); - this.TbIntNotifierApiPort.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.MinValue = ((long)(1)); - this.TbIntNotifierApiPort.Name = "TbIntNotifierApiPort"; - this.TbIntNotifierApiPort.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.Size = new System.Drawing.Size(92, 25); - this.TbIntNotifierApiPort.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbIntNotifierApiPort.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbIntNotifierApiPort.TabIndex = 32; - this.TbIntNotifierApiPort.Text = "1,883"; - this.TbIntNotifierApiPort.ThemeName = "Metro"; - this.TbIntNotifierApiPort.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntNotifierApiPort.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // - // BtnNotificationsReadme - // - this.BtnNotificationsReadme.AccessibleName = "Button"; - this.BtnNotificationsReadme.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnNotificationsReadme.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.BtnNotificationsReadme.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnNotificationsReadme.Location = new System.Drawing.Point(455, 411); - this.BtnNotificationsReadme.Name = "BtnNotificationsReadme"; - this.BtnNotificationsReadme.Size = new System.Drawing.Size(228, 31); - this.BtnNotificationsReadme.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnNotificationsReadme.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnNotificationsReadme.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnNotificationsReadme.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnNotificationsReadme.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnNotificationsReadme.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnNotificationsReadme.Style.PressedForeColor = System.Drawing.Color.Black; - this.BtnNotificationsReadme.TabIndex = 35; - this.BtnNotificationsReadme.Text = "notifications documentation"; - this.BtnNotificationsReadme.UseVisualStyleBackColor = false; - this.BtnNotificationsReadme.Click += new System.EventHandler(this.BtnNotificationsReadme_Click); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(121, 101); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(33, 17); - this.label1.TabIndex = 34; - this.label1.Text = "port"; - // - // CbAcceptNotifications - // - this.CbAcceptNotifications.AutoSize = true; - this.CbAcceptNotifications.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbAcceptNotifications.Location = new System.Drawing.Point(277, 100); - this.CbAcceptNotifications.Name = "CbAcceptNotifications"; - this.CbAcceptNotifications.Size = new System.Drawing.Size(139, 21); - this.CbAcceptNotifications.TabIndex = 33; - this.CbAcceptNotifications.Text = "accept notifications"; - this.CbAcceptNotifications.UseVisualStyleBackColor = true; - // - // Notifications - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); - this.Controls.Add(this.label18); - this.Controls.Add(this.label12); - this.Controls.Add(this.TbIntNotifierApiPort); - this.Controls.Add(this.BtnNotificationsReadme); - this.Controls.Add(this.label1); - this.Controls.Add(this.CbAcceptNotifications); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.Margin = new System.Windows.Forms.Padding(4); - this.Name = "Notifications"; - this.Size = new System.Drawing.Size(700, 457); - this.Load += new System.EventHandler(this.Notifications_Load); - ((System.ComponentModel.ISupportInitialize)(this.TbIntNotifierApiPort)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label label18; - private System.Windows.Forms.Label label12; - private System.Windows.Forms.Label label1; - internal Syncfusion.Windows.Forms.Tools.IntegerTextBox TbIntNotifierApiPort; - internal Syncfusion.WinForms.Controls.SfButton BtnNotificationsReadme; - internal System.Windows.Forms.CheckBox CbAcceptNotifications; - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.cs deleted file mode 100644 index f531f36..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Functions; - -namespace HASSAgent.Controls.Configuration -{ - public partial class Notifications : UserControl - { - public Notifications() - { - InitializeComponent(); - - TbIntNotifierApiPort.Culture = CultureInfo.InstalledUICulture; - } - - private void BtnNotificationsReadme_Click(object sender, EventArgs e) => HelperFunctions.LaunchUrl("https://github.com/LAB02-Research/HASS.Agent/wiki/Notification-Usage-&-Examples"); - - private void Notifications_Load(object sender, EventArgs e) - { - // - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.resx b/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.resx deleted file mode 100644 index 3beb216..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.resx +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - HASS.Agent can start when you login by creating an entry in your user profile's registry. - -Since HASS.Agent is user based, if you want to launch for another user, just install and config HASS.Agent there. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.cs b/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.cs deleted file mode 100644 index 8c47d0f..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace HASSAgent.Controls.Configuration -{ - public partial class Updates : UserControl - { - public Updates() - { - InitializeComponent(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs b/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs deleted file mode 100644 index 68c6867..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Globalization; - -namespace HASSAgent.Controls.Onboarding -{ - partial class Notifications - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.PbHassAgentLogo = new System.Windows.Forms.PictureBox(); - this.TbIntNotifierApiPort = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.CbAcceptNotifications = new System.Windows.Forms.CheckBox(); - this.label1 = new System.Windows.Forms.Label(); - ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntNotifierApiPort)).BeginInit(); - this.SuspendLayout(); - // - // PbHassAgentLogo - // - this.PbHassAgentLogo.Cursor = System.Windows.Forms.Cursors.Hand; - this.PbHassAgentLogo.Image = global::HASSAgent.Properties.Resources.logo_128; - this.PbHassAgentLogo.Location = new System.Drawing.Point(24, 20); - this.PbHassAgentLogo.Name = "PbHassAgentLogo"; - this.PbHassAgentLogo.Size = new System.Drawing.Size(128, 128); - this.PbHassAgentLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; - this.PbHassAgentLogo.TabIndex = 2; - this.PbHassAgentLogo.TabStop = false; - // - // TbIntNotifierApiPort - // - this.TbIntNotifierApiPort.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntNotifierApiPort.BeforeTouchSize = new System.Drawing.Size(92, 25); - this.TbIntNotifierApiPort.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbIntNotifierApiPort.CurrentCultureRefresh = true; - this.TbIntNotifierApiPort.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbIntNotifierApiPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.IntegerValue = ((long)(1883)); - this.TbIntNotifierApiPort.Location = new System.Drawing.Point(183, 274); - this.TbIntNotifierApiPort.MaxValue = ((long)(66000)); - this.TbIntNotifierApiPort.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.MinValue = ((long)(1)); - this.TbIntNotifierApiPort.Name = "TbIntNotifierApiPort"; - this.TbIntNotifierApiPort.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.Size = new System.Drawing.Size(92, 25); - this.TbIntNotifierApiPort.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbIntNotifierApiPort.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbIntNotifierApiPort.TabIndex = 1; - this.TbIntNotifierApiPort.Text = "1,883"; - this.TbIntNotifierApiPort.ThemeName = "Metro"; - this.TbIntNotifierApiPort.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntNotifierApiPort.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntNotifierApiPort.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntNotifierApiPort.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // - // label2 - // - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(180, 232); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(384, 39); - this.label2.TabIndex = 26; - this.label2.Text = "This is the default port, change it only if you changed it in Home Assistant."; - // - // CbAcceptNotifications - // - this.CbAcceptNotifications.AutoSize = true; - this.CbAcceptNotifications.Checked = true; - this.CbAcceptNotifications.CheckState = System.Windows.Forms.CheckState.Checked; - this.CbAcceptNotifications.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbAcceptNotifications.Location = new System.Drawing.Point(183, 153); - this.CbAcceptNotifications.Name = "CbAcceptNotifications"; - this.CbAcceptNotifications.Size = new System.Drawing.Size(165, 21); - this.CbAcceptNotifications.TabIndex = 0; - this.CbAcceptNotifications.Text = "yes, accept notifications"; - this.CbAcceptNotifications.UseVisualStyleBackColor = true; - // - // label1 - // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(180, 20); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(384, 87); - this.label1.TabIndex = 24; - this.label1.Text = "HASS.Agent can receive notifications from Home Assistant, using text and/or image" + - "s.\r\n\r\nDo you want to enable this function?"; - // - // Notifications - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); - this.Controls.Add(this.TbIntNotifierApiPort); - this.Controls.Add(this.label2); - this.Controls.Add(this.CbAcceptNotifications); - this.Controls.Add(this.label1); - this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.Margin = new System.Windows.Forms.Padding(4); - this.Name = "Notifications"; - this.Size = new System.Drawing.Size(610, 364); - this.Load += new System.EventHandler(this.Notifications_Load); - ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntNotifierApiPort)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - private System.Windows.Forms.PictureBox PbHassAgentLogo; - private Syncfusion.Windows.Forms.Tools.IntegerTextBox TbIntNotifierApiPort; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.CheckBox CbAcceptNotifications; - private System.Windows.Forms.Label label1; - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.cs b/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.cs deleted file mode 100644 index 94d6320..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Drawing; -using System.Globalization; -using System.Windows.Forms; -using HASSAgent.Functions; -using Newtonsoft.Json; -using Serilog; -using Syncfusion.Windows.Forms; - -namespace HASSAgent.Controls.Onboarding -{ - public partial class Notifications : UserControl - { - public Notifications() - { - InitializeComponent(); - - TbIntNotifierApiPort.Culture = CultureInfo.InstalledUICulture; - } - - private void Notifications_Load(object sender, EventArgs e) - { - // hide group seperator - TbIntNotifierApiPort.NumberGroupSeparator = ""; - - CbAcceptNotifications.Checked = Variables.AppSettings.NotificationsEnabled; - TbIntNotifierApiPort.IntegerValue = Variables.AppSettings.NotifierApiPort; - } - - internal bool Store() - { - Variables.AppSettings.NotificationsEnabled = CbAcceptNotifications.Checked; - Variables.AppSettings.NotifierApiPort = (int)TbIntNotifierApiPort.IntegerValue; - - return true; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/3-Notifications.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.resx deleted file mode 100644 index 04edc9c..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.resx +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Make sure you follow these steps: - -- Install HASS.Agent-Notifier integration -- Restart Home Assistant -- Configure a notifier entity -- Restart Home Assistant - -Afterwards, you can add the notifier entity in your automations && scripts. - - - To use notifications, you need to install and configure the HASS.Agent-notifier integration in Home Assistant. - -This is very easy using HACS, but you can also install manually. Visit the link below for more information. - - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.resx deleted file mode 100644 index cfd25f4..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.resx +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - To learn which entities you have configured, and to send quick actions, HASS.Agent uses Home Assistant's API. - -Please provide a long-lived access token, and the address of your Home Assistant instance. - -You can get a token through your profile page. Scroll to the bottom and click 'CREATE TOKEN'. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.resx deleted file mode 100644 index 0c1958e..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.resx +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Commands and sensors are sent through MQTT. Please provide credentials for your server. If you're using the HA addon, you can probably use the preset address. - -Leave empty if you're not going to use commands and sensors. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.resx b/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.resx deleted file mode 100644 index 39281df..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.resx +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - All done! - - -HASS.Agent will now restart to activate -your configuration. - -If you've enabled notifications, an elevation request will popup. -This is required to allow HASS.Agent to listen on the specified port. - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.resx b/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.resx deleted file mode 100644 index 29dcb1b..0000000 --- a/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Enums/CommandType.cs b/src/HASS.Agent/HASSAgent/Enums/CommandType.cs deleted file mode 100644 index 22bb3d7..0000000 --- a/src/HASS.Agent/HASSAgent/Enums/CommandType.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Runtime.Serialization; - -namespace HASSAgent.Enums -{ - public enum CommandType - { - [EnumMember(Value = "CustomCommand")] - CustomCommand, - - [EnumMember(Value = "CustomExecutorCommand")] - CustomExecutorCommand, - - [EnumMember(Value = "HibernateCommand")] - HibernateCommand, - - [EnumMember(Value = "KeyCommand")] - KeyCommand, - - [EnumMember(Value = "LaunchUrlCommand")] - LaunchUrlCommand, - - [EnumMember(Value = "LockCommand")] - LockCommand, - - [EnumMember(Value = "LogOffCommand")] - LogOffCommand, - - [EnumMember(Value = "MediaMuteCommand")] - MediaMuteCommand, - - [EnumMember(Value = "MediaNextCommand")] - MediaNextCommand, - - [EnumMember(Value = "MediaPlayPauseCommand")] - MediaPlayPauseCommand, - - [EnumMember(Value = "MediaPreviousCommand")] - MediaPreviousCommand, - - [EnumMember(Value = "MediaVolumeDownCommand")] - MediaVolumeDownCommand, - - [EnumMember(Value = "MediaVolumeUpCommand")] - MediaVolumeUpCommand, - - [EnumMember(Value = "MultipleKeysCommand")] - MultipleKeysCommand, - - [EnumMember(Value = "PowershellCommand")] - PowershellCommand, - - [EnumMember(Value = "PublishAllSensorsCommand")] - PublishAllSensorsCommand, - - [EnumMember(Value = "RestartCommand")] - RestartCommand, - - [EnumMember(Value = "ShutdownCommand")] - ShutdownCommand, - - [EnumMember(Value = "SleepCommand")] - SleepCommand - } -} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Enums/LockState.cs b/src/HASS.Agent/HASSAgent/Enums/LockState.cs deleted file mode 100644 index 5abd3d0..0000000 --- a/src/HASS.Agent/HASSAgent/Enums/LockState.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace HASSAgent.Enums -{ - public enum LockState - { - Locked, - Unknown, - Unlocked - } -} diff --git a/src/HASS.Agent/HASSAgent/Enums/MqttStatus.cs b/src/HASS.Agent/HASSAgent/Enums/MqttStatus.cs deleted file mode 100644 index d24a43d..0000000 --- a/src/HASS.Agent/HASSAgent/Enums/MqttStatus.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace HASSAgent.Enums -{ - public enum MqttStatus - { - ConfigMissing, - Connected, - Connecting, - Disconnected, - Error - } -} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Enums/SensorType.cs b/src/HASS.Agent/HASSAgent/Enums/SensorType.cs deleted file mode 100644 index bf694ff..0000000 --- a/src/HASS.Agent/HASSAgent/Enums/SensorType.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; - -namespace HASSAgent.Enums -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public enum SensorType - { - [EnumMember(Value = "ActiveWindowSensor")] - ActiveWindowSensor, - - [EnumMember(Value = "AudioSensors")] - AudioSensors, - - [EnumMember(Value = "BatterySensors")] - BatterySensors, - - [EnumMember(Value = "CpuLoadSensor")] - CpuLoadSensor, - - [EnumMember(Value = "CurrentClockSpeedSensor")] - CurrentClockSpeedSensor, - - [EnumMember(Value = "CurrentVolumeSensor")] - CurrentVolumeSensor, - - [EnumMember(Value = "DisplaySensors")] - DisplaySensors, - - [EnumMember(Value = "DummySensor")] - DummySensor, - - [EnumMember(Value = "GpuLoadSensor")] - GpuLoadSensor, - - [EnumMember(Value = "GpuTemperatureSensor")] - GpuTemperatureSensor, - - [EnumMember(Value = "LastActiveSensor")] - LastActiveSensor, - - [EnumMember(Value = "LastBootSensor")] - LastBootSensor, - - [EnumMember(Value = "LastSystemStateChangeSensor")] - LastSystemStateChangeSensor, - - [EnumMember(Value = "LoggedUserSensor")] - LoggedUserSensor, - - [EnumMember(Value = "LoggedUsersSensor")] - LoggedUsersSensor, - - [EnumMember(Value = "MemoryUsageSensor")] - MemoryUsageSensor, - - [EnumMember(Value = "MicrophoneActiveSensor")] - MicrophoneActiveSensor, - - [EnumMember(Value = "NamedWindowSensor")] - NamedWindowSensor, - - [EnumMember(Value = "NetworkSensors")] - NetworkSensors, - - [EnumMember(Value = "PerformanceCounterSensor")] - PerformanceCounterSensor, - - [EnumMember(Value = "ProcessActiveSensor")] - ProcessActiveSensor, - - [EnumMember(Value = "ServiceStateSensor")] - ServiceStateSensor, - - [EnumMember(Value = "SessionStateSensor")] - SessionStateSensor, - - [EnumMember(Value = "StorageSensors")] - StorageSensors, - - [EnumMember(Value = "UserNotificationStateSensor")] - UserNotificationStateSensor, - - [EnumMember(Value = "WebcamActiveSensor")] - WebcamActiveSensor, - - [EnumMember(Value = "WindowsUpdatesSensors")] - WindowsUpdatesSensors, - - [EnumMember(Value = "WmiQuerySensor")] - WmiQuerySensor - } -} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Enums/SystemStateEvent.cs b/src/HASS.Agent/HASSAgent/Enums/SystemStateEvent.cs deleted file mode 100644 index effafe6..0000000 --- a/src/HASS.Agent/HASSAgent/Enums/SystemStateEvent.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace HASSAgent.Enums -{ - public enum SystemStateEvent - { - HassAgentStarted, - Logoff, - SystemShutdown, - Resume, - Suspend, - ConsoleConnect, - ConsoleDisconnect, - RemoteConnect, - RemoteDisconnect, - SessionLock, - SessionLogoff, - SessionLogon, - SessionRemoteControl, - SessionUnlock - } -} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Enums/UserNotificationState.cs b/src/HASS.Agent/HASSAgent/Enums/UserNotificationState.cs deleted file mode 100644 index 82075b4..0000000 --- a/src/HASS.Agent/HASSAgent/Enums/UserNotificationState.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace HASSAgent.Enums -{ - public enum UserNotificationState - { - NotPresent = 1, - Busy = 2, - RunningDirect3dFullScreen = 3, - PresentationMode = 4, - AcceptsNotifications = 5, - QuietTime = 6, - RunningWindowsStoreApp = 7 - } -} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Forms/ChildApplications/PostUpdate.cs b/src/HASS.Agent/HASSAgent/Forms/ChildApplications/PostUpdate.cs deleted file mode 100644 index 4222a60..0000000 --- a/src/HASS.Agent/HASSAgent/Forms/ChildApplications/PostUpdate.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Functions; -using HASSAgent.Notifications; -using HASSAgent.Properties; -using HASSAgent.Settings; -using Microsoft.Win32.TaskScheduler; -using Serilog; -using Syncfusion.Windows.Forms; -using Task = System.Threading.Tasks.Task; - -namespace HASSAgent.Forms.ChildApplications -{ - public partial class PostUpdate : MetroForm - { - public PostUpdate() - { - InitializeComponent(); - } - - private void PostUpdate_Load(object sender, EventArgs e) - { - ProcessPostUpdate(); - } - - /// - /// Performs post-update steps to check system state before launch - /// - private async void ProcessPostUpdate() - { - // set initial busy indicator - PbStep1ScheduledTask.Image = Resources.small_loader_32; - - // give the ui time to load - await Task.Delay(TimeSpan.FromSeconds(2)); - - // make sure settings are loaded - await SettingsManager.LoadAsync(false); - - // check leftover legacy tasks - var taskDone = await ProcessLegacyTaskAsync(); - PbStep1ScheduledTask.Image = taskDone ? Resources.done_32 : Resources.failed_32; - - // execute port reservation - var portDone = await ProcessPortReservationAsync(); - PbStep2PortBinding.Image = portDone ? Resources.done_32 : Resources.failed_32; - - // notify the user if something went wrong - if (!taskDone || !portDone) MessageBoxAdv.Show("Not all steps completed succesfully. Please consult the logs for more information.", - "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); - else - { - // wait a bit to show the 'completed' checks - await Task.Delay(750); - } - - // relaunch normally - HelperFunctions.Restart(true); - - // done, the relauncher will close up - } - - /// - /// Attempts to clean up legacy scheduled tasks, if any - /// - /// - private async Task ProcessLegacyTaskAsync() - { - try - { - // set busy indicator - PbStep1ScheduledTask.Image = Resources.small_loader_32; - - // check if it's there - var taskFound = await Task.Run(ScheduledTasks.IsTaskPresent); - if (!taskFound) return true; - - // yep, stop if it's still active - var taskStatus = await Task.Run(ScheduledTasks.TaskStatus); - if (taskStatus == TaskState.Running) - { - var stopped = ScheduledTasks.Stop(); - if (!stopped) Log.Warning("[POSTUPDATE] Unable to stop scheduled task, deletion may fail"); - - await Task.Delay(250); - } - - // try to delete - var deleted = await ScheduledTasks.RemoveAsync(); - if (!deleted) Log.Error("[POSTUPDATE] Unable to remove scheduled task, manual action required"); - else Log.Information("[POSTUPDATE] Legacy scheduled task removed"); - - // set startup-through-reg - var launchOnLoginSet = LaunchManager.EnableLaunchOnUserLogin(); - if (!launchOnLoginSet) Log.Error("[POSTUPDATE] Unable to activate registry based launch-on-login method"); - else Log.Information("[POSTUPDATE] Registry based launch-on-login method activated"); - - // done - return deleted; - } - catch (Exception ex) - { - Log.Fatal(ex, "[POSTUPDATE] Error processing legacy task: {err}", ex.Message); - return false; - } - } - - /// - /// Processes port reservation for the notifier API - /// - /// - private async Task ProcessPortReservationAsync() - { - try - { - // set busy indicator - PbStep2PortBinding.Image = Resources.small_loader_32; - - // is the notifier enabled? - if (!Variables.AppSettings.NotificationsEnabled) return true; - - // yep, set it at the configured port - var portReserved = await NotifierManager.ExecutePortReservationAsync(Variables.AppSettings.NotifierApiPort); - if (!portReserved) Log.Error("[POSTUPDATE] Unable to execute port reservation, notifier api might fail"); - else Log.Information("[POSTUPDATE] Port reservation completed"); - - // done - return portReserved; - } - catch (Exception ex) - { - Log.Fatal(ex, "[POSTUPDATE] Error processing port reservation: {err}", ex.Message); - return false; - } - } - - private void PostUpdate_ResizeEnd(object sender, EventArgs e) - { - if (Variables.ShuttingDown) return; - if (!IsHandleCreated) return; - if (IsDisposed) return; - - try - { - Refresh(); - } - catch - { - // best effort - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Forms/Commands/CommandsConfig.cs b/src/HASS.Agent/HASSAgent/Forms/Commands/CommandsConfig.cs deleted file mode 100644 index 8442c92..0000000 --- a/src/HASS.Agent/HASSAgent/Forms/Commands/CommandsConfig.cs +++ /dev/null @@ -1,250 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Commands; -using HASSAgent.Models.Config; -using HASSAgent.Mqtt; -using HASSAgent.Settings; -using Serilog; -using Syncfusion.Windows.Forms; -using Syncfusion.Windows.Forms.Grid; - -namespace HASSAgent.Forms.Commands -{ - public partial class CommandsConfig : MetroForm - { - private List _commands = new List(); - private readonly List _toBeDeletedCommands = new List(); - - private int _heightDiff; - - public CommandsConfig() - { - InitializeComponent(); - } - - private void CommandsConfig_Load(object sender, EventArgs e) - { - // set the initial height difference for resizing - _heightDiff = Height - LcCommands.Height; - - // catch all key presses - KeyPreview = true; - - // load stored commands - PrepareCommandsList(); - - // set all flags to 'max one row' - LcCommands.Grid.AllowDragSelectedCols = false; - LcCommands.Grid.AllowSelection = GridSelectionFlags.Row; - LcCommands.Grid.AllowDragSelectedRows = false; - LcCommands.Grid.ListBoxSelectionMode = SelectionMode.One; - LcCommands.SelectionMode = SelectionMode.One; - - // fit last column - LcCommands.FillLastColumn = true; - - // we have to refresh after selecting, otherwise a bunch of rows stay highlighted :\ - LcCommands.Grid.SelectionChanged += (o, args) => LcCommands.Grid.Refresh(); - LcCommands.Grid.SelectionChanging += (o, args) => LcCommands.Grid.Refresh(); - } - - /// - /// Load the stored commands into the grid - /// - private void PrepareCommandsList() - { - // make a copy of the current commands - _commands = Variables.Commands.Select(StoredCommands.ConvertAbstractToConfigured).Where(configuredCommand => configuredCommand != null).ToList(); - - // bind to the list - LcCommands.DataSource = _commands; - - // hide id column - LcCommands.Grid.HideCols["Id"] = true; - - // hide command column - LcCommands.Grid.HideCols["Command"] = true; - - // hide keycode column - LcCommands.Grid.HideCols["KeyCode"] = true; - - // hide low integrity column - LcCommands.Grid.HideCols["RunAsLowIntegrity"] = true; - - // force column resize - LcCommands.Grid.ColWidths.ResizeToFit(GridRangeInfo.Table(), GridResizeToFitOptions.IncludeHeaders); - - // set header height - LcCommands.Grid.RowHeights[0] = 25; - - // add extra space - for (var i = 1; i <= LcCommands.Grid.ColCount; i++) LcCommands.Grid.ColWidths[i] += 15; - - // redraw - LcCommands.Refresh(); - } - - /// - /// Reload the commands - /// - private void UpdateCommandsList() - { - // reload data - LcCommands.Grid.ResetVolatileData(); - - // force column resize - LcCommands.Grid.ColWidths.ResizeToFit(GridRangeInfo.Table(), GridResizeToFitOptions.IncludeHeaders); - - // add extra space - for (var i = 1; i <= LcCommands.Grid.ColCount; i++) LcCommands.Grid.ColWidths[i] += 15; - - // redraw - LcCommands.Refresh(); - } - - /// - /// Open a new form to modify the selected command - /// - private void ModifySelectedCommand() - { - // find all (if any) selected rows - var selectedRows = LcCommands.Grid.Selections.GetSelectedRows(true, true); - if (selectedRows.Count == 0) return; - - // we can just modify one, so the first - var selectedRow = selectedRows[0]; - var selectedCommand = (ConfiguredCommand)LcCommands.Items[selectedRow.Top - 1]; - - // show modding form - using (var command = new CommandsMod(selectedCommand)) - { - var res = command.ShowDialog(); - if (res != DialogResult.OK) return; - - // update in temp list - _commands[_commands.FindIndex(x => x.Id == command.Command.Id)] = command.Command; - - // reload the gui list - UpdateCommandsList(); - } - } - - /// - /// Delete all selected commands - /// Note: doesn't actually execute deletion, that's done after the user clicks 'store' - /// - private void DeleteSelectedCommands() - { - // check for selected rows - var selectedRows = LcCommands.Grid.Selections.GetSelectedRows(true, true); - if (selectedRows.Count == 0) return; - - // get selected row indexes - var rowList = new List(); - for (var i = LcCommands.Grid.Model.SelectedRanges.ActiveRange.Top; i <= LcCommands.Grid.Model.SelectedRanges.ActiveRange.Bottom; i++) - { - rowList.Add(i - 1); - } - - // make descending - rowList.Sort(); - rowList.Reverse(); - - foreach (var row in rowList) - { - // get object - var qA = (ConfiguredCommand)LcCommands.Items[row]; - - // add to to-be-deleted list - _toBeDeletedCommands.Add(qA); - - // remove from the list - _commands.RemoveAt(_commands.FindIndex(x => x.Id == qA.Id)); - } - - // reload the gui list - UpdateCommandsList(); - } - - /// - /// Show a form to add a new command - /// - /// - /// - private void BtnAdd_Click(object sender, EventArgs e) - { - using (var command = new CommandsMod()) - { - var res = command.ShowDialog(); - if (res != DialogResult.OK) return; - - // add to the temp list - _commands.Add(command.Command); - - // reload the gui list - UpdateCommandsList(); - } - } - - /// - /// Stores our temporary list, and syncs it to HASS through MQTT - /// - /// - /// - private async void BtnStore_Click(object sender, EventArgs e) - { - // lock interface - LcCommands.Enabled = false; - BtnRemove.Enabled = false; - BtnModify.Enabled = false; - BtnAdd.Enabled = false; - BtnStore.Enabled = false; - BtnStore.Text = "storing and registering, please wait .. "; - - // store - var stored = await CommandsManager.StoreAsync(_commands, _toBeDeletedCommands); - if (!stored) MessageBoxAdv.Show("An error occured while saving the commands, check the logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); - - // done - Close(); - } - - private void BtnModify_Click(object sender, EventArgs e) => ModifySelectedCommand(); - - private void BtnRemove_Click(object sender, EventArgs e) => DeleteSelectedCommands(); - - private void CommandsConfig_KeyUp(object sender, KeyEventArgs e) - { - if (e.KeyCode != Keys.Escape) return; - Close(); - } - - private void CommandsConfig_FormClosing(object sender, FormClosingEventArgs e) - { - // - } - - private void LcCommands_DoubleClick(object sender, EventArgs e) => ModifySelectedCommand(); - - private void CommandsConfig_Resize(object sender, EventArgs e) => LcCommands.Height = Height - _heightDiff; - - private void CommandsConfig_ResizeEnd(object sender, EventArgs e) - { - if (Variables.ShuttingDown) return; - if (!IsHandleCreated) return; - if (IsDisposed) return; - - try - { - Refresh(); - } - catch - { - // best effort - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Forms/QuickActions/QuickActionsConfig.cs b/src/HASS.Agent/HASSAgent/Forms/QuickActions/QuickActionsConfig.cs deleted file mode 100644 index 8660405..0000000 --- a/src/HASS.Agent/HASSAgent/Forms/QuickActions/QuickActionsConfig.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using HASSAgent.Models.Internal; -using HASSAgent.Settings; -using Syncfusion.Windows.Forms; -using Syncfusion.Windows.Forms.Grid; - -namespace HASSAgent.Forms.QuickActions -{ - public partial class QuickActionsConfig : MetroForm - { - private readonly List _quickActions = new List(); - - private int _heightDiff; - - public QuickActionsConfig() - { - InitializeComponent(); - } - - private void QuickActionsConfig_Load(object sender, EventArgs e) - { - // set the initial height difference for resizing - _heightDiff = Height - LcQuickActions.Height; - - // catch all key presses - KeyPreview = true; - - // load stored actions - PrepareQuickActionList(); - - // set all flags to 'max one row' - LcQuickActions.Grid.AllowDragSelectedCols = false; - LcQuickActions.Grid.AllowSelection = GridSelectionFlags.Row; - LcQuickActions.Grid.AllowDragSelectedRows = false; - LcQuickActions.Grid.ListBoxSelectionMode = SelectionMode.One; - LcQuickActions.SelectionMode = SelectionMode.One; - - // we have to refresh after selecting, otherwise a bunch of rows stay highlighted :\ - LcQuickActions.Grid.SelectionChanged += (o, args) => LcQuickActions.Grid.Refresh(); - LcQuickActions.Grid.SelectionChanging += (o, args) => LcQuickActions.Grid.Refresh(); - } - - /// - /// Load the stored quickactions into the grid - /// - private void PrepareQuickActionList() - { - // make a copy of the current actions - foreach (var quickAction in Variables.QuickActions) _quickActions.Add(quickAction); - - // bind to the list - LcQuickActions.DataSource = _quickActions; - - // hide muid column - LcQuickActions.Grid.HideCols["Id"] = true; - - // force column resize - LcQuickActions.Grid.ColWidths.ResizeToFit(GridRangeInfo.Table(), GridResizeToFitOptions.IncludeHeaders); - - // set header height - LcQuickActions.Grid.RowHeights[0] = 25; - - // add extra space - for (var i = 1; i <= LcQuickActions.Grid.ColCount; i++) LcQuickActions.Grid.ColWidths[i] += 15; - - // redraw - LcQuickActions.Refresh(); - } - - /// - /// Reload the quickactions - /// - private void UpdateQuickActionList() - { - // reload data - LcQuickActions.Grid.ResetVolatileData(); - - // force column resize - LcQuickActions.Grid.ColWidths.ResizeToFit(GridRangeInfo.Table(), GridResizeToFitOptions.IncludeHeaders); - - // add extra space - for (var i = 1; i <= LcQuickActions.Grid.ColCount; i++) LcQuickActions.Grid.ColWidths[i] += 15; - - // redraw - LcQuickActions.Refresh(); - } - - /// - /// Open a new form to modify the selected quickaction - /// - private void ModifySelectedAction() - { - // find all (if any) selected rows - var selectedRows = LcQuickActions.Grid.Selections.GetSelectedRows(true, true); - if (selectedRows.Count == 0) return; - - // we can just modify one, so the first - var selectedRow = selectedRows[0]; - var selectedAction = (QuickAction)LcQuickActions.Items[selectedRow.Top - 1]; - - if (selectedAction.Id == Guid.Empty) - { - LcQuickActions.Refresh(); - selectedAction = (QuickAction)LcQuickActions.Items[selectedRow.Top - 1]; - } - - // show modding form - using (var quickAction = new QuickActionsMod(selectedAction)) - { - var res = quickAction.ShowDialog(); - if (res != DialogResult.OK) return; - - // update in temp list - _quickActions[_quickActions.FindIndex(x => x.Id == quickAction.QuickAction.Id)] = quickAction.QuickAction; - - // reload the gui list - UpdateQuickActionList(); - } - } - - /// - /// Delete all selected quickactions - /// Note: doesn't actually execute deletion, that's done after the user clicks 'store' - /// - private void DeleteSelectedActions() - { - // check for selected rows - var selectedRows = LcQuickActions.Grid.Selections.GetSelectedRows(true, true); - if (selectedRows.Count == 0) return; - - // get selected row indexes - var rowList = new List(); - for (var i = LcQuickActions.Grid.Model.SelectedRanges.ActiveRange.Top; i <= LcQuickActions.Grid.Model.SelectedRanges.ActiveRange.Bottom; i++) - { - rowList.Add(i - 1); - } - - // make descending - rowList.Sort(); - rowList.Reverse(); - - foreach (var row in rowList) - { - // get object - var qA = (QuickAction)LcQuickActions.Items[row]; - - // remove from the list - _quickActions.RemoveAt(_quickActions.FindIndex(x => x.Id == qA.Id)); - } - - // reload the gui list - UpdateQuickActionList(); - } - - /// - /// Show a form to add a new quickaction - /// - /// - /// - private void BtnAdd_Click(object sender, EventArgs e) - { - using (var quickAction = new QuickActionsMod()) - { - var res = quickAction.ShowDialog(); - if (res != DialogResult.OK) return; - - // add to the temp list - _quickActions.Add(quickAction.QuickAction); - - // reload the gui list - UpdateQuickActionList(); - } - } - - private void BtnModify_Click(object sender, EventArgs e) - { - ModifySelectedAction(); - } - - /// - /// Stores our temporary list - /// - /// - /// - private void BtnStore_Click(object sender, EventArgs e) - { - // copy our list to the main one - Variables.QuickActions = new List(); - foreach (var quickAction in _quickActions) Variables.QuickActions.Add(quickAction); - - // store to file - StoredQuickActions.Store(); - - // reload hotkey bindings - Variables.HotKeyManager.ReloadQuickActionsHotKeys(); - - // done - Close(); - } - - private void BtnRemove_Click(object sender, EventArgs e) => DeleteSelectedActions(); - - private void LcQuickActions_DoubleClick(object sender, EventArgs e) => ModifySelectedAction(); - - private void BtnPreview_Click(object sender, EventArgs e) - { - using (var quickActions = new QuickActions(_quickActions)) - { - quickActions.ShowDialog(); - } - } - - private void QuickActionsConfig_KeyUp(object sender, KeyEventArgs e) - { - if (e.KeyCode != Keys.Escape) return; - Close(); - } - - private void QuickActionsConfig_Resize(object sender, EventArgs e) - { - LcQuickActions.Height = Height - _heightDiff; - } - - private void QuickActionsConfig_ResizeEnd(object sender, EventArgs e) - { - if (Variables.ShuttingDown) return; - if (!IsHandleCreated) return; - if (IsDisposed) return; - - try - { - Refresh(); - } - catch - { - // best effort - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsConfig.cs b/src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsConfig.cs deleted file mode 100644 index 5a7de34..0000000 --- a/src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsConfig.cs +++ /dev/null @@ -1,255 +0,0 @@ -using Syncfusion.Windows.Forms; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Models.Config; -using HASSAgent.Mqtt; -using HASSAgent.Sensors; -using HASSAgent.Settings; -using Newtonsoft.Json; -using Serilog; -using Syncfusion.Windows.Forms.Grid; - -namespace HASSAgent.Forms.Sensors -{ - public partial class SensorsConfig : MetroForm - { - private List _sensors = new List(); - private readonly List _toBeDeletedSensors = new List(); - - private int _heightDiff; - - public SensorsConfig() - { - InitializeComponent(); - } - - private void SensorsConfig_Load(object sender, EventArgs e) - { - // set the initial height difference for resizing - _heightDiff = Height - LcSensors.Height; - - // catch all key presses - KeyPreview = true; - - // load stored sensors - PrepareSensorsList(); - - // set all flags to 'max one row' - LcSensors.Grid.AllowDragSelectedCols = false; - LcSensors.Grid.AllowSelection = GridSelectionFlags.Row; - LcSensors.Grid.AllowDragSelectedRows = false; - LcSensors.Grid.ListBoxSelectionMode = SelectionMode.One; - LcSensors.SelectionMode = SelectionMode.One; - - // we have to refresh after selecting, otherwise a bunch of rows stay highlighted :\ - LcSensors.Grid.SelectionChanged += (o, args) => LcSensors.Grid.Refresh(); - LcSensors.Grid.SelectionChanging += (o, args) => LcSensors.Grid.Refresh(); - } - - /// - /// Load the stored sensors into the grid - /// - private void PrepareSensorsList() - { - // make a copy of the current sensors - _sensors = Variables.SingleValueSensors.Select(StoredSensors.ConvertAbstractSingleValueToConfigured).Where(configuredSensor => configuredSensor != null).ToList(); - _sensors = _sensors.Concat(Variables.MultiValueSensors.Select(StoredSensors.ConvertAbstractMultiValueToConfigured).Where(configuredSensor => configuredSensor != null)).ToList(); - - // bind to the list - LcSensors.DataSource = _sensors; - - // hide id column - LcSensors.Grid.HideCols["Id"] = true; - - // hide query column - LcSensors.Grid.HideCols["Query"] = true; - - // hide windowname column - LcSensors.Grid.HideCols["WindowName"] = true; - - // hide updateinterval column - LcSensors.Grid.HideCols["UpdateInterval"] = true; - - // hide performancecounter columns - LcSensors.Grid.HideCols["Category"] = true; - LcSensors.Grid.HideCols["Scope"] = true; - LcSensors.Grid.HideCols["Counter"] = true; - LcSensors.Grid.HideCols["Instance"] = true; - - // force column resize - LcSensors.Grid.ColWidths.ResizeToFit(GridRangeInfo.Table(), GridResizeToFitOptions.IncludeHeaders); - - // set header height - LcSensors.Grid.RowHeights[0] = 25; - - // add extra space - for (var i = 1; i <= LcSensors.Grid.ColCount; i++) LcSensors.Grid.ColWidths[i] += 15; - - // redraw - LcSensors.Refresh(); - } - - /// - /// Reload the sensors - /// - private void UpdateSensorsList() - { - // reload data - LcSensors.Grid.ResetVolatileData(); - - // force column resize - LcSensors.Grid.ColWidths.ResizeToFit(GridRangeInfo.Table(), GridResizeToFitOptions.IncludeHeaders); - - // add extra space - for (var i = 1; i <= LcSensors.Grid.ColCount; i++) LcSensors.Grid.ColWidths[i] += 15; - - // redraw - LcSensors.Refresh(); - } - - /// - /// Open a new form to modify the selected sensor - /// - private void ModifySelectedSensor() - { - // find all (if any) selected rows - var selectedRows = LcSensors.Grid.Selections.GetSelectedRows(true, true); - if (selectedRows.Count == 0) return; - - // we can just modify one, so the first - var selectedRow = selectedRows[0]; - var selectedSensor = (ConfiguredSensor)LcSensors.Items[selectedRow.Top - 1]; - - // show modding form - using (var sensor = new SensorsMod(selectedSensor)) - { - var res = sensor.ShowDialog(); - if (res != DialogResult.OK) return; - - // update in temp list - _sensors[_sensors.FindIndex(x => x.Id == sensor.Sensor.Id)] = sensor.Sensor; - - // reload the gui list - UpdateSensorsList(); - } - } - - /// - /// Delete all selected sensors - /// Note: doesn't actually execute deletion, that's done after the user clicks 'store' - /// - private void DeleteSelectedSensors() - { - // check for selected rows - var selectedRows = LcSensors.Grid.Selections.GetSelectedRows(true, true); - if (selectedRows.Count == 0) return; - - // get selected row indexes - var rowList = new List(); - for (var i = LcSensors.Grid.Model.SelectedRanges.ActiveRange.Top; i <= LcSensors.Grid.Model.SelectedRanges.ActiveRange.Bottom; i++) - { - rowList.Add(i - 1); - } - - // make descending - rowList.Sort(); - rowList.Reverse(); - - foreach (var row in rowList) - { - // get object - var qA = (ConfiguredSensor)LcSensors.Items[row]; - - // add to to-be-deleted list - _toBeDeletedSensors.Add(qA); - - // remove from the list - _sensors.RemoveAt(_sensors.FindIndex(x => x.Id == qA.Id)); - } - - // reload the gui list - UpdateSensorsList(); - } - - /// - /// Show a form to add a new sensor - /// - /// - /// - private void BtnAdd_Click(object sender, EventArgs e) - { - using (var sensor = new SensorsMod()) - { - var res = sensor.ShowDialog(); - if (res != DialogResult.OK) return; - - // add to the temp list - _sensors.Add(sensor.Sensor); - - // reload the gui list - UpdateSensorsList(); - } - } - - /// - /// Stores our temporary list, and syncs it to HASS through MQTT - /// - /// - /// - private async void BtnStore_Click(object sender, EventArgs e) - { - // lock interface - LcSensors.Enabled = false; - BtnRemove.Enabled = false; - BtnModify.Enabled = false; - BtnAdd.Enabled = false; - BtnStore.Enabled = false; - BtnStore.Text = "storing and registering, please wait .. "; - - // store - var stored = await SensorsManager.StoreAsync(_sensors, _toBeDeletedSensors); - if (!stored) MessageBoxAdv.Show("An error occured while saving the sensors, check the logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); - - // done - Close(); - } - - private void BtnModify_Click(object sender, EventArgs e) => ModifySelectedSensor(); - - private void BtnRemove_Click(object sender, EventArgs e) => DeleteSelectedSensors(); - - private void SensorsConfig_KeyUp(object sender, KeyEventArgs e) - { - if (e.KeyCode != Keys.Escape) return; - Close(); - } - - private void SensorsConfig_FormClosing(object sender, FormClosingEventArgs e) - { - // - } - - private void LcSensors_DoubleClick(object sender, EventArgs e) => ModifySelectedSensor(); - - private void SensorsConfig_Resize(object sender, EventArgs e) => LcSensors.Height = Height - _heightDiff; - - private void SensorsConfig_ResizeEnd(object sender, EventArgs e) - { - if (Variables.ShuttingDown) return; - if (!IsHandleCreated) return; - if (IsDisposed) return; - - try - { - Refresh(); - } - catch - { - // best effort - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsMod.Designer.cs b/src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsMod.Designer.cs deleted file mode 100644 index 019ad3b..0000000 --- a/src/HASS.Agent/HASSAgent/Forms/Sensors/SensorsMod.Designer.cs +++ /dev/null @@ -1,347 +0,0 @@ - -using System.Globalization; - -namespace HASSAgent.Forms.Sensors -{ - partial class SensorsMod - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SensorsMod)); - this.BtnStore = new Syncfusion.WinForms.Controls.SfButton(); - this.LblSetting1 = new System.Windows.Forms.Label(); - this.TbSetting1 = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.TbName = new System.Windows.Forms.TextBox(); - this.TbIntInterval = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.label3 = new System.Windows.Forms.Label(); - this.label5 = new System.Windows.Forms.Label(); - this.TbDescription = new System.Windows.Forms.RichTextBox(); - this.PnlDescription = new System.Windows.Forms.Panel(); - this.LblSetting2 = new System.Windows.Forms.Label(); - this.TbSetting2 = new System.Windows.Forms.TextBox(); - this.LblSetting3 = new System.Windows.Forms.Label(); - this.TbSetting3 = new System.Windows.Forms.TextBox(); - this.CbType = new System.Windows.Forms.ComboBox(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntInterval)).BeginInit(); - this.PnlDescription.SuspendLayout(); - this.SuspendLayout(); - // - // BtnStore - // - this.BtnStore.AccessibleName = "Button"; - this.BtnStore.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnStore.Dock = System.Windows.Forms.DockStyle.Bottom; - this.BtnStore.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.BtnStore.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnStore.Location = new System.Drawing.Point(0, 342); - this.BtnStore.Name = "BtnStore"; - this.BtnStore.Size = new System.Drawing.Size(765, 38); - this.BtnStore.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnStore.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnStore.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnStore.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnStore.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnStore.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnStore.Style.PressedForeColor = System.Drawing.Color.Black; - this.BtnStore.TabIndex = 5; - this.BtnStore.Text = "store sensor"; - this.BtnStore.UseVisualStyleBackColor = false; - this.BtnStore.Click += new System.EventHandler(this.BtnStore_Click); - // - // LblSetting1 - // - this.LblSetting1.AutoSize = true; - this.LblSetting1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblSetting1.Location = new System.Drawing.Point(9, 174); - this.LblSetting1.Name = "LblSetting1"; - this.LblSetting1.Size = new System.Drawing.Size(58, 17); - this.LblSetting1.TabIndex = 12; - this.LblSetting1.Text = "setting 1"; - this.LblSetting1.Visible = false; - // - // TbSetting1 - // - this.TbSetting1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbSetting1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbSetting1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbSetting1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbSetting1.Location = new System.Drawing.Point(12, 194); - this.TbSetting1.Name = "TbSetting1"; - this.TbSetting1.Size = new System.Drawing.Size(328, 25); - this.TbSetting1.TabIndex = 2; - this.TbSetting1.Visible = false; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(9, 15); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(33, 17); - this.label1.TabIndex = 3; - this.label1.Text = "type"; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label4.Location = new System.Drawing.Point(9, 71); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(40, 17); - this.label4.TabIndex = 10; - this.label4.Text = "name"; - // - // TbName - // - this.TbName.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbName.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbName.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbName.Location = new System.Drawing.Point(12, 91); - this.TbName.Name = "TbName"; - this.TbName.Size = new System.Drawing.Size(328, 25); - this.TbName.TabIndex = 1; - // - // TbIntInterval - // - this.TbIntInterval.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntInterval.BeforeTouchSize = new System.Drawing.Size(61, 25); - this.TbIntInterval.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntInterval.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbIntInterval.CurrentCultureRefresh = true; - this.TbIntInterval.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntInterval.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbIntInterval.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntInterval.IntegerValue = ((long)(5)); - this.TbIntInterval.Location = new System.Drawing.Point(99, 131); - this.TbIntInterval.MaxValue = ((long)(43200)); - this.TbIntInterval.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntInterval.MinValue = ((long)(1)); - this.TbIntInterval.Name = "TbIntInterval"; - this.TbIntInterval.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntInterval.Size = new System.Drawing.Size(61, 25); - this.TbIntInterval.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbIntInterval.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbIntInterval.TabIndex = 14; - this.TbIntInterval.Text = "5"; - this.TbIntInterval.ThemeName = "Metro"; - this.TbIntInterval.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntInterval.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntInterval.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntInterval.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntInterval.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntInterval.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntInterval.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(9, 134); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(84, 17); - this.label2.TabIndex = 13; - this.label2.Text = "update every"; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(166, 134); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(56, 17); - this.label3.TabIndex = 15; - this.label3.Text = "seconds"; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label5.Location = new System.Drawing.Point(398, 15); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(116, 17); - this.label5.TabIndex = 17; - this.label5.Text = "sensor description"; - // - // TbDescription - // - this.TbDescription.AutoWordSelection = true; - this.TbDescription.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbDescription.BorderStyle = System.Windows.Forms.BorderStyle.None; - this.TbDescription.Dock = System.Windows.Forms.DockStyle.Fill; - this.TbDescription.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbDescription.Location = new System.Drawing.Point(0, 0); - this.TbDescription.Name = "TbDescription"; - this.TbDescription.ReadOnly = true; - this.TbDescription.Size = new System.Drawing.Size(352, 288); - this.TbDescription.TabIndex = 18; - this.TbDescription.Text = ""; - this.TbDescription.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.TbDescription_LinkClicked); - // - // PnlDescription - // - this.PnlDescription.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.PnlDescription.Controls.Add(this.TbDescription); - this.PnlDescription.Location = new System.Drawing.Point(401, 35); - this.PnlDescription.Name = "PnlDescription"; - this.PnlDescription.Size = new System.Drawing.Size(354, 290); - this.PnlDescription.TabIndex = 19; - // - // LblSetting2 - // - this.LblSetting2.AutoSize = true; - this.LblSetting2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblSetting2.Location = new System.Drawing.Point(9, 227); - this.LblSetting2.Name = "LblSetting2"; - this.LblSetting2.Size = new System.Drawing.Size(54, 17); - this.LblSetting2.TabIndex = 21; - this.LblSetting2.Text = "setting2"; - this.LblSetting2.Visible = false; - // - // TbSetting2 - // - this.TbSetting2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbSetting2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbSetting2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbSetting2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbSetting2.Location = new System.Drawing.Point(12, 247); - this.TbSetting2.Name = "TbSetting2"; - this.TbSetting2.Size = new System.Drawing.Size(328, 25); - this.TbSetting2.TabIndex = 3; - this.TbSetting2.Visible = false; - // - // LblSetting3 - // - this.LblSetting3.AutoSize = true; - this.LblSetting3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblSetting3.Location = new System.Drawing.Point(9, 280); - this.LblSetting3.Name = "LblSetting3"; - this.LblSetting3.Size = new System.Drawing.Size(58, 17); - this.LblSetting3.TabIndex = 23; - this.LblSetting3.Text = "setting 3"; - this.LblSetting3.Visible = false; - // - // TbSetting3 - // - this.TbSetting3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbSetting3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbSetting3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbSetting3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbSetting3.Location = new System.Drawing.Point(12, 300); - this.TbSetting3.Name = "TbSetting3"; - this.TbSetting3.Size = new System.Drawing.Size(328, 25); - this.TbSetting3.TabIndex = 4; - this.TbSetting3.Visible = false; - // - // CbType - // - this.CbType.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.CbType.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; - this.CbType.DropDownHeight = 300; - this.CbType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CbType.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbType.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.CbType.FormattingEnabled = true; - this.CbType.IntegralHeight = false; - this.CbType.Location = new System.Drawing.Point(12, 36); - this.CbType.Name = "CbType"; - this.CbType.Size = new System.Drawing.Size(328, 26); - this.CbType.TabIndex = 24; - this.CbType.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.CbType_DrawItem); - this.CbType.SelectedIndexChanged += new System.EventHandler(this.CbType_SelectedIndexChanged); - // - // SensorsMod - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); - this.CaptionBarColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.CaptionFont = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CaptionForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.ClientSize = new System.Drawing.Size(765, 380); - this.Controls.Add(this.CbType); - this.Controls.Add(this.LblSetting3); - this.Controls.Add(this.TbSetting3); - this.Controls.Add(this.LblSetting2); - this.Controls.Add(this.TbSetting2); - this.Controls.Add(this.PnlDescription); - this.Controls.Add(this.label5); - this.Controls.Add(this.LblSetting1); - this.Controls.Add(this.BtnStore); - this.Controls.Add(this.TbSetting1); - this.Controls.Add(this.label1); - this.Controls.Add(this.label3); - this.Controls.Add(this.label4); - this.Controls.Add(this.label2); - this.Controls.Add(this.TbName); - this.Controls.Add(this.TbIntInterval); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.MetroColor = System.Drawing.Color.FromArgb(((int)(((byte)(129)))), ((int)(((byte)(129)))), ((int)(((byte)(131))))); - this.Name = "SensorsMod"; - this.ShowMaximizeBox = false; - this.ShowMinimizeBox = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Sensor"; - this.Load += new System.EventHandler(this.SensorMod_Load); - this.ResizeEnd += new System.EventHandler(this.SensorsMod_ResizeEnd); - this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.SensorsMod_KeyUp); - ((System.ComponentModel.ISupportInitialize)(this.TbIntInterval)).EndInit(); - this.PnlDescription.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private Syncfusion.WinForms.Controls.SfButton BtnStore; - private System.Windows.Forms.Label LblSetting1; - private System.Windows.Forms.TextBox TbSetting1; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.TextBox TbName; - private System.Windows.Forms.Label label3; - private Syncfusion.Windows.Forms.Tools.IntegerTextBox TbIntInterval; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label5; - private System.Windows.Forms.RichTextBox TbDescription; - private System.Windows.Forms.Panel PnlDescription; - private System.Windows.Forms.Label LblSetting2; - private System.Windows.Forms.TextBox TbSetting2; - private System.Windows.Forms.Label LblSetting3; - private System.Windows.Forms.TextBox TbSetting3; - private System.Windows.Forms.ComboBox CbType; - } -} - diff --git a/src/HASS.Agent/HASSAgent/Functions/CommandLineManager.cs b/src/HASS.Agent/HASSAgent/Functions/CommandLineManager.cs deleted file mode 100644 index 860ec7a..0000000 --- a/src/HASS.Agent/HASSAgent/Functions/CommandLineManager.cs +++ /dev/null @@ -1,1031 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CliWrap; -using CliWrap.Buffered; -using HASSAgent.Models.Internal; -using Microsoft.Win32.SafeHandles; -using Serilog; -// ReSharper disable InconsistentNaming - -namespace HASSAgent.Functions -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - internal static class CommandLineManager - { - /// - /// Executes the file within a command prompt, parses & returns the output - /// Uses default timeout of 5 minutes - /// - /// - /// - /// - internal static async Task ExecuteCommandAsync(string file, string args) - { - return await ExecuteCommandAsync(file, args, TimeSpan.FromMinutes(5)); - } - - /// - /// Executes the file within a command prompt, parses & returns the output - /// - /// - /// - /// - /// - internal static async Task ExecuteCommandAsync(string file, string args, TimeSpan timout) - { - var consoleResult = new ConsoleResult(); - - try - { - using (var cts = new CancellationTokenSource()) - { - cts.CancelAfter(timout); - - var result = await Cli.Wrap(file) - .WithArguments(args) - .WithValidation(CommandResultValidation.None) - .ExecuteBufferedAsync(cts.Token); - - var exitCode = result.ExitCode; - var stdOut = result.StandardOutput; - var stdErr = result.StandardError; - - if (cts.IsCancellationRequested) - { - // timeout elapsed - Log.Error("[CLI] Execution didn't finish within timeout limit (exitcode: {exitCode}): {file}", exitCode, file); - } - else - { - // executed within timeout - if (exitCode != 0) Log.Warning("[PROCESS] Execution returned non-ok exitcode (exitcode: {exitCode}): {file}", exitCode, file); - } - - // add console output to the console result - if (!string.IsNullOrEmpty(stdOut)) - { - var output = stdOut.Trim(); - output = output.Replace(@"\r\n", Environment.NewLine); - output = output.Replace(@"\n", Environment.NewLine); - - var consoleOutput = new StringBuilder(); - - foreach (var row in output.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) - { - consoleOutput.AppendLine(row); - } - - consoleResult.Output = consoleOutput.ToString(); - } - else consoleResult.Output = string.Empty; - - // add console error output to the console result - if (!string.IsNullOrEmpty(stdErr)) - { - var err = stdErr.Trim(); - err = err.Replace(@"\r\n", Environment.NewLine); - err = err.Replace(@"\n", Environment.NewLine); - - var errorOutput = new StringBuilder(); - - foreach (var row in err.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) - { - errorOutput.AppendLine(row); - } - - consoleResult.ErrorOutput = errorOutput.ToString(); - } - else consoleResult.ErrorOutput = string.Empty; - - // complete the console result - var success = exitCode == 0 && string.IsNullOrEmpty(stdErr); - - consoleResult.Error = !success; - consoleResult.ExitCode = exitCode; - - // done - return consoleResult; - } - } - catch (Win32Exception we) - { - // win32 file-not-found error - if (we.NativeErrorCode == FileNotFoundError || we.NativeErrorCode == 2) - { - Log.Error("[CLI] File not found, unable to execute: {file}", file); - return consoleResult.SetError("file not found"); - } - - // this error means a x64 file has been run on an x86 environment (probably) - if (we.NativeErrorCode == 193) - { - var os32 = Environment.Is64BitOperatingSystem ? "NO" : "YES"; - Log.Error("[CLI] File isn't compatible with the current platform (OS is 32bit: {os32})", os32); - return consoleResult.SetError("file incompatible with platform"); - } - - // code unknown - Log.Error("[CLI] Unknown WIN32 error encountered (code: {code}): {file}", we.NativeErrorCode, file); - return consoleResult.SetError("unknown error"); - } - catch (Exception ex) - { - Log.Fatal(ex, "[CLI] Fatal error when executing file: {file}", file); - return consoleResult.SetError("fatal error"); - } - } - - /// - /// Execute a command without waiting for or checking results - /// - /// - /// - internal static bool ExecuteHeadless(string command) - { - try - { - using (var process = new Process()) - { - var startInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - CreateNoWindow = true, - FileName = "cmd.exe", - Arguments = $"/C {command}" - }; - - process.StartInfo = startInfo; - var start = process.Start(); - - if (!start) - { - Log.Error("[CLI] Unable to start executing command: {command}", command); - return false; - } - - // done - return true; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[CLI] Fatal error when executing command: {command}", command); - return true; - } - } - - /// - /// Executes the file without elevation, no feedback - /// Source: https://stackoverflow.com/a/58579679 - /// - /// - /// - [SuppressMessage("ReSharper", "SuspiciousTypeConversion.Global")] - internal static void ExecuteProcessUnElevated(string file, string args = "") - { - var shellWindows = (IShellWindows)new CShellWindows(); - - // get the desktop window - object loc = CSIDL_Desktop; - var unused = new object(); - var serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(ref loc, ref unused, SWC_DESKTOP, out _, SWFO_NEEDDISPATCH); - - // get the shell browser - var serviceGuid = SID_STopLevelBrowser; - var interfaceGuid = typeof(IShellBrowser).GUID; - var shellBrowser = (IShellBrowser)serviceProvider.QueryService(ref serviceGuid, ref interfaceGuid); - - // get the shell dispatch - var dispatch = typeof(IDispatch).GUID; - var folderView = (IShellFolderViewDual)shellBrowser.QueryActiveShellView().GetItemObject(SVGIO_BACKGROUND, ref dispatch); - var shellDispatch = (IShellDispatch2)folderView.Application; - - // use the dispatch (which is unelevated) to launch the process for us - shellDispatch.ShellExecute(file, args, Variables.StartupPath, string.Empty, SW_SHOWNORMAL); - } - - /// - /// Launches the application with low integrity - /// Both application and arguments need to be in the commandLine variable - /// Source: https://github.com/edetoc/samples/tree/18cdf198694a4398b9ac9c605fc14a6b39706f12/CSCreateLowIntegrityProcess/CSCreateLowIntegrityProcess - /// - /// - /// - internal static void LaunchAsLowIntegrity(string commandLine) - { - SafeTokenHandle hToken = null; - SafeTokenHandle hNewToken = null; - var pIntegritySid = IntPtr.Zero; - var pTokenInfo = IntPtr.Zero; - var si = new STARTUPINFO(); - var pi = new PROCESS_INFORMATION(); - int cbTokenInfo; - - try - { - // open the primary access token of the process - if (!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle, NativeMethod.TOKEN_DUPLICATE | NativeMethod.TOKEN_ADJUST_DEFAULT | NativeMethod.TOKEN_QUERY | NativeMethod.TOKEN_ASSIGN_PRIMARY, out hToken)) - { - Log.Fatal(new Win32Exception(), "[CLI] Error while launching as low integrity: unable to open current process' access token"); - return; - } - - // duplicate the primary token of the current process - if (!NativeMethod.DuplicateTokenEx(hToken, 0, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out hNewToken)) - { - Log.Fatal(new Win32Exception(), "[CLI] Error while launching as low integrity: unable to duplicate current process' primary token"); - return; - } - - // create the low integrity SID - if (!NativeMethod.AllocateAndInitializeSid(ref NativeMethod.SECURITY_MANDATORY_LABEL_AUTHORITY, 1, - NativeMethod.SECURITY_MANDATORY_LOW_RID, 0, 0, 0, 0, 0, 0, 0, out pIntegritySid)) - { - Log.Fatal(new Win32Exception(), "[CLI] Error while launching as low integrity: unable to create the low integrity SID"); - return; - } - - TOKEN_MANDATORY_LABEL tml; - tml.Label.Attributes = NativeMethod.SE_GROUP_INTEGRITY; - tml.Label.Sid = pIntegritySid; - - // marshal the TOKEN_MANDATORY_LABEL struct to the native memory - cbTokenInfo = Marshal.SizeOf(tml); - pTokenInfo = Marshal.AllocHGlobal(cbTokenInfo); - Marshal.StructureToPtr(tml, pTokenInfo, false); - - // set the integrity level in the access token to low - if (!NativeMethod.SetTokenInformation(hNewToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenInfo, cbTokenInfo + NativeMethod.GetLengthSid(pIntegritySid))) - { - Log.Fatal(new Win32Exception(), "[CLI] Error while launching as low integrity: unable to set integrity level to low"); - return; - } - - // create the new process at the Low integrity level - si.cb = Marshal.SizeOf(si); - if (!NativeMethod.CreateProcessAsUser(hNewToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref si, out pi)) - { - Log.Fatal(new Win32Exception(), "[CLI] Error while launching as low integrity: unable to create the new process at low integrity"); - } - - // all done, no feedback - } - catch (Win32Exception ex) - { - Log.Fatal(ex, "[CLI] Error while launching as low integrity (W32): {err}", ex.Message); - } - catch (Exception ex) - { - Log.Fatal(ex, "[CLI] Error while launching as low integrity: {err}", ex.Message); - } - finally - { - // centralized cleanup for all allocated resources - if (hToken != null) - { - hToken.Close(); - hToken = null; - } - - if (hNewToken != null) - { - hNewToken.Close(); - hNewToken = null; - } - - if (pIntegritySid != IntPtr.Zero) - { - NativeMethod.FreeSid(pIntegritySid); - pIntegritySid = IntPtr.Zero; - } - - if (pTokenInfo != IntPtr.Zero) - { - Marshal.FreeHGlobal(pTokenInfo); - pTokenInfo = IntPtr.Zero; - cbTokenInfo = 0; - } - - if (pi.hProcess != IntPtr.Zero) - { - NativeMethod.CloseHandle(pi.hProcess); - pi.hProcess = IntPtr.Zero; - } - - if (pi.hThread != IntPtr.Zero) - { - NativeMethod.CloseHandle(pi.hThread); - pi.hThread = IntPtr.Zero; - } - } - } - - #region Launch Unelevated - /// - /// Interop definitions - /// - private const int CSIDL_Desktop = 0; - private const int SWC_DESKTOP = 8; - private const int SWFO_NEEDDISPATCH = 1; - private const int SW_SHOWNORMAL = 1; - private const int SVGIO_BACKGROUND = 0; - private static readonly Guid SID_STopLevelBrowser = new Guid("4C96BE40-915C-11CF-99D3-00AA004AE837"); - - [ComImport] - [Guid("9BA05972-F6A8-11CF-A442-00A0C90A8F39")] - [ClassInterfaceAttribute(ClassInterfaceType.None)] - private class CShellWindows - { - // - } - - [ComImport] - [Guid("85CB6900-4D95-11CF-960C-0080C7F4EE85")] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - private interface IShellWindows - { - [return: MarshalAs(UnmanagedType.IDispatch)] - object FindWindowSW([MarshalAs(UnmanagedType.Struct)] ref object pvarloc, [MarshalAs(UnmanagedType.Struct)] ref object pvarlocRoot, int swClass, out int pHWND, int swfwOptions); - } - - [ComImport] - [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IServiceProvider - { - [return: MarshalAs(UnmanagedType.Interface)] - object QueryService(ref Guid guidService, ref Guid riid); - } - - [ComImport] - [Guid("000214E2-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IShellBrowser - { - void VTableGap01(); // GetWindow - void VTableGap02(); // ContextSensitiveHelp - void VTableGap03(); // InsertMenusSB - void VTableGap04(); // SetMenuSB - void VTableGap05(); // RemoveMenusSB - void VTableGap06(); // SetStatusTextSB - void VTableGap07(); // EnableModelessSB - void VTableGap08(); // TranslateAcceleratorSB - void VTableGap09(); // BrowseObject - void VTableGap10(); // GetViewStateStream - void VTableGap11(); // GetControlWindow - void VTableGap12(); // SendControlMsg - IShellView QueryActiveShellView(); - } - - [ComImport] - [Guid("000214E3-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IShellView - { - void VTableGap01(); // GetWindow - void VTableGap02(); // ContextSensitiveHelp - void VTableGap03(); // TranslateAcceleratorA - void VTableGap04(); // EnableModeless - void VTableGap05(); // UIActivate - void VTableGap06(); // Refresh - void VTableGap07(); // CreateViewWindow - void VTableGap08(); // DestroyViewWindow - void VTableGap09(); // GetCurrentInfo - void VTableGap10(); // AddPropertySheetPages - void VTableGap11(); // SaveViewState - void VTableGap12(); // SelectItem - - [return: MarshalAs(UnmanagedType.Interface)] - object GetItemObject(uint aspectOfView, ref Guid riid); - } - - [ComImport] - [Guid("00020400-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - private interface IDispatch - { - // - } - - [ComImport] - [Guid("E7A1AF80-4D96-11CF-960C-0080C7F4EE85")] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - private interface IShellFolderViewDual - { - object Application { [return: MarshalAs(UnmanagedType.IDispatch)] get; } - } - - [ComImport] - [Guid("A4C6892C-3BA9-11D2-9DEA-00C04FB16162")] - [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] - public interface IShellDispatch2 - { - void ShellExecute([MarshalAs(UnmanagedType.BStr)] string File, [MarshalAs(UnmanagedType.Struct)] object vArgs, [MarshalAs(UnmanagedType.Struct)] object vDir, [MarshalAs(UnmanagedType.Struct)] object vOperation, [MarshalAs(UnmanagedType.Struct)] object vShow); - } - - // ReSharper disable once ConvertToConstant.Local - private static readonly uint FileNotFoundUint = 0x80004005; - private static readonly int FileNotFoundError = (int)FileNotFoundUint; - #endregion - } - - #region Launch with Low Integrity - // Source: https://github.com/edetoc/samples/tree/18cdf198694a4398b9ac9c605fc14a6b39706f12/CSCreateLowIntegrityProcess/CSCreateLowIntegrityProcess - - /// - /// The TOKEN_INFORMATION_CLASS enumeration type contains values that - /// specify the type of information being assigned to or retrieved from - /// an access token. - /// - internal enum TOKEN_INFORMATION_CLASS - { - TokenUser = 1, - TokenGroups, - TokenPrivileges, - TokenOwner, - TokenPrimaryGroup, - TokenDefaultDacl, - TokenSource, - TokenType, - TokenImpersonationLevel, - TokenStatistics, - TokenRestrictedSids, - TokenSessionId, - TokenGroupsAndPrivileges, - TokenSessionReference, - TokenSandBoxInert, - TokenAuditPolicy, - TokenOrigin, - TokenElevationType, - TokenLinkedToken, - TokenElevation, - TokenHasRestrictions, - TokenAccessInformation, - TokenVirtualizationAllowed, - TokenVirtualizationEnabled, - TokenIntegrityLevel, - TokenUIAccess, - TokenMandatoryPolicy, - TokenLogonSid, - MaxTokenInfoClass - } - - /// - /// The SECURITY_IMPERSONATION_LEVEL enumeration type contains values - /// that specify security impersonation levels. Security impersonation - /// levels govern the degree to which a server process can act on behalf - /// of a client process. - /// - internal enum SECURITY_IMPERSONATION_LEVEL - { - SecurityAnonymous, - SecurityIdentification, - SecurityImpersonation, - SecurityDelegation - } - - /// - /// The TOKEN_TYPE enumeration type contains values that differentiate - /// between a primary token and an impersonation token. - /// - internal enum TOKEN_TYPE - { - TokenPrimary = 1, - TokenImpersonation - } - - /// - /// The structure represents a security identifier (SID) and its - /// attributes. SIDs are used to uniquely identify users or groups. - /// - [StructLayout(LayoutKind.Sequential)] - internal struct SID_AND_ATTRIBUTES - { - public IntPtr Sid; - public uint Attributes; - } - - /// - /// The SID_IDENTIFIER_AUTHORITY structure represents the top-level - /// authority of a security identifier (SID). - /// - [StructLayout(LayoutKind.Sequential)] - internal struct SID_IDENTIFIER_AUTHORITY - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)] - public byte[] Value; - - public SID_IDENTIFIER_AUTHORITY(byte[] value) - { - Value = value; - } - } - - /// - /// The structure specifies the mandatory integrity level for a token. - /// - [StructLayout(LayoutKind.Sequential)] - internal struct TOKEN_MANDATORY_LABEL - { - public SID_AND_ATTRIBUTES Label; - } - - /// - /// Specifies the window station, desktop, standard handles, and - /// appearance of the main window for a process at creation time. - /// - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct STARTUPINFO - { - public int cb; - public string lpReserved; - public string lpDesktop; - public string lpTitle; - public int dwX; - public int dwY; - public int dwXSize; - public int dwYSize; - public int dwXCountChars; - public int dwYCountChars; - public int dwFillAttribute; - public int dwFlags; - public short wShowWindow; - public short cbReserved2; - public IntPtr lpReserved2; - public IntPtr hStdInput; - public IntPtr hStdOutput; - public IntPtr hStdError; - } - - /// - /// Contains information about a newly created process and its primary - /// thread. - /// - [StructLayout(LayoutKind.Sequential)] - internal struct PROCESS_INFORMATION - { - public IntPtr hProcess; - public IntPtr hThread; - public int dwProcessId; - public int dwThreadId; - } - - /// - /// Represents a wrapper class for a token handle. - /// - internal class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private SafeTokenHandle() - : base(true) - { - } - - internal SafeTokenHandle(IntPtr handle) - : base(true) - { - SetHandle(handle); - } - - protected override bool ReleaseHandle() - { - return NativeMethod.CloseHandle(handle); - } - } - - internal class NativeMethod - { - // Token Specific Access Rights - public const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000; - public const uint STANDARD_RIGHTS_READ = 0x00020000; - public const uint TOKEN_ASSIGN_PRIMARY = 0x0001; - public const uint TOKEN_DUPLICATE = 0x0002; - public const uint TOKEN_IMPERSONATE = 0x0004; - public const uint TOKEN_QUERY = 0x0008; - public const uint TOKEN_QUERY_SOURCE = 0x0010; - public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; - public const uint TOKEN_ADJUST_GROUPS = 0x0040; - public const uint TOKEN_ADJUST_DEFAULT = 0x0080; - public const uint TOKEN_ADJUST_SESSIONID = 0x0100; - public const uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); - public const uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | - TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | - TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | - TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID); - - public const int ERROR_INSUFFICIENT_BUFFER = 122; - - // Integrity Levels - public static SID_IDENTIFIER_AUTHORITY SECURITY_MANDATORY_LABEL_AUTHORITY = new SID_IDENTIFIER_AUTHORITY(new byte[] { 0, 0, 0, 0, 0, 16 }); - public const int SECURITY_MANDATORY_UNTRUSTED_RID = 0x00000000; - public const int SECURITY_MANDATORY_LOW_RID = 0x00001000; - public const int SECURITY_MANDATORY_MEDIUM_RID = 0x00002000; - public const int SECURITY_MANDATORY_HIGH_RID = 0x00003000; - public const int SECURITY_MANDATORY_SYSTEM_RID = 0x00004000; - - // Group related SID Attributes - public const uint SE_GROUP_MANDATORY = 0x00000001; - public const uint SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002; - public const uint SE_GROUP_ENABLED = 0x00000004; - public const uint SE_GROUP_OWNER = 0x00000008; - public const uint SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010; - public const uint SE_GROUP_INTEGRITY = 0x00000020; - public const uint SE_GROUP_INTEGRITY_ENABLED = 0x00000040; - public const uint SE_GROUP_LOGON_ID = 0xC0000000; - public const uint SE_GROUP_RESOURCE = 0x20000000; - public const uint SE_GROUP_VALID_ATTRIBUTES = (SE_GROUP_MANDATORY | - SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_OWNER | - SE_GROUP_USE_FOR_DENY_ONLY | SE_GROUP_LOGON_ID | SE_GROUP_RESOURCE | - SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED); - - /// - /// The function opens the access token associated with a process. - /// - /// - /// A handle to the process whose access token is opened. - /// - /// - /// Specifies an access mask that specifies the requested types of - /// access to the access token. - /// - /// - /// Outputs a handle that identifies the newly opened access token - /// when the function returns. - /// - /// - [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool OpenProcessToken( - IntPtr hProcess, - uint desiredAccess, - out SafeTokenHandle hToken); - - /// - /// The DuplicateTokenEx function creates a new access token that - /// duplicates an existing token. This function can create either a - /// primary token or an impersonation token. - /// - /// - /// A handle to an access token opened with TOKEN_DUPLICATE access. - /// - /// - /// Specifies the requested access rights for the new token. - /// - /// - /// A pointer to a SECURITY_ATTRIBUTES structure that specifies a - /// security descriptor for the new token and determines whether - /// child processes can inherit the token. If lpTokenAttributes is - /// NULL, the token gets a default security descriptor and the handle - /// cannot be inherited. - /// - /// - /// Specifies the impersonation level of the new token. - /// - /// - /// TokenPrimary - The new token is a primary token that you can use - /// in the CreateProcessAsUser function. - /// TokenImpersonation - The new token is an impersonation token. - /// - /// - /// Receives the new token. - /// - /// - [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DuplicateTokenEx( - SafeTokenHandle hExistingToken, - uint desiredAccess, - IntPtr pTokenAttributes, - SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, - TOKEN_TYPE TokenType, - out SafeTokenHandle hNewToken); - - /// - /// The function retrieves a specified type of information about an - /// access token. The calling process must have appropriate access - /// rights to obtain the information. - /// - /// - /// A handle to an access token from which information is retrieved. - /// - /// - /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated - /// type to identify the type of information the function retrieves. - /// - /// - /// A pointer to a buffer the function fills with the requested - /// information. - /// - /// - /// Specifies the size, in bytes, of the buffer pointed to by the - /// TokenInformation parameter. - /// - /// - /// A pointer to a variable that receives the number of bytes needed - /// for the buffer pointed to by the TokenInformation parameter. - /// - /// - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool GetTokenInformation( - SafeTokenHandle hToken, - TOKEN_INFORMATION_CLASS tokenInfoClass, - IntPtr pTokenInfo, - int tokenInfoLength, - out int returnLength); - - /// - /// The function sets various types of information for a specified - /// access token. The information that this function sets replaces - /// existing information. The calling process must have appropriate - /// access rights to set the information. - /// - /// - /// A handle to the access token for which information is to be set. - /// - /// - /// A value from the TOKEN_INFORMATION_CLASS enumerated type that - /// identifies the type of information the function sets. - /// - /// - /// A pointer to a buffer that contains the information set in the - /// access token. - /// - /// - /// Specifies the length, in bytes, of the buffer pointed to by - /// TokenInformation. - /// - /// - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetTokenInformation( - SafeTokenHandle hToken, - TOKEN_INFORMATION_CLASS tokenInfoClass, - IntPtr pTokenInfo, - int tokenInfoLength); - - /// - /// The function returns a pointer to a specified subauthority in a - /// security identifier (SID). The subauthority value is a relative - /// identifier (RID). - /// - /// - /// A pointer to the SID structure from which a pointer to a - /// subauthority is to be returned. - /// - /// - /// Specifies an index value identifying the subauthority array - /// element whose address the function will return. - /// - /// - /// If the function succeeds, the return value is a pointer to the - /// specified SID subauthority. To get extended error information, - /// call GetLastError. If the function fails, the return value is - /// undefined. The function fails if the specified SID structure is - /// not valid or if the index value specified by the nSubAuthority - /// parameter is out of bounds. - /// - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr GetSidSubAuthority( - IntPtr pSid, - uint nSubAuthority); - - /// - /// The AllocateAndInitializeSid function allocates and initializes a - /// security identifier (SID) with up to eight subauthorities. - /// - /// - /// A reference of a SID_IDENTIFIER_AUTHORITY structure. This - /// structure provides the top-level identifier authority value to - /// set in the SID. - /// - /// - /// Specifies the number of subauthorities to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Subauthority value to place in the SID. - /// - /// - /// Outputs the allocated and initialized SID structure. - /// - /// - /// If the function succeeds, the return value is true. If the - /// function fails, the return value is false. To get extended error - /// information, call GetLastError. - /// - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool AllocateAndInitializeSid( - ref SID_IDENTIFIER_AUTHORITY pIdentifierAuthority, - byte nSubAuthorityCount, - int dwSubAuthority0, int dwSubAuthority1, - int dwSubAuthority2, int dwSubAuthority3, - int dwSubAuthority4, int dwSubAuthority5, - int dwSubAuthority6, int dwSubAuthority7, - out IntPtr pSid); - - /// - /// The FreeSid function frees a security identifier (SID) previously - /// allocated by using the AllocateAndInitializeSid function. - /// - /// - /// A pointer to the SID structure to free. - /// - /// - /// If the function succeeds, the function returns NULL. If the - /// function fails, it returns a pointer to the SID structure - /// represented by the pSid parameter. - /// - [DllImport("advapi32.dll")] - public static extern IntPtr FreeSid(IntPtr pSid); - - /// - /// The function returns the length, in bytes, of a valid security - /// identifier (SID). - /// - /// - /// A pointer to the SID structure whose length is returned. - /// - /// - /// If the SID structure is valid, the return value is the length, in - /// bytes, of the SID structure. - /// - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern int GetLengthSid(IntPtr pSID); - - /// - /// Creates a new process and its primary thread. The new process - /// runs in the security context of the user represented by the - /// specified token. - /// - /// - /// A handle to the primary token that represents a user. - /// - /// - /// The name of the module to be executed. - /// - /// - /// The command line to be executed. The maximum length of this - /// string is 32K characters. - /// - /// - /// A pointer to a SECURITY_ATTRIBUTES structure that specifies a - /// security descriptor for the new process object and determines - /// whether child processes can inherit the returned handle to the - /// process. - /// - /// - /// A pointer to a SECURITY_ATTRIBUTES structure that specifies a - /// security descriptor for the new thread object and determines - /// whether child processes can inherit the returned handle to the - /// thread. - /// - /// - /// If this parameter is true, each inheritable handle in the calling - /// process is inherited by the new process. If the parameter is - /// false, the handles are not inherited. - /// - /// - /// The flags that control the priority class and the creation of the - /// process. - /// - /// - /// A pointer to an environment block for the new process. - /// - /// - /// The full path to the current directory for the process. - /// - /// - /// References a STARTUPINFO structure. - /// - /// - /// Outputs a PROCESS_INFORMATION structure that receives - /// identification information about the new process. - /// - /// - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool CreateProcessAsUser( - SafeTokenHandle hToken, - string applicationName, - string commandLine, - IntPtr pProcessAttributes, - IntPtr pThreadAttributes, - bool bInheritHandles, - uint dwCreationFlags, - IntPtr pEnvironment, - string currentDirectory, - ref STARTUPINFO startupInfo, - out PROCESS_INFORMATION processInformation); - - /// - /// Closes an open object handle. - /// - /// A valid handle to an open object. - /// - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool CloseHandle(IntPtr handle); - - // edetoc - [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] - public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); - } - - /// - /// Well-known folder paths - /// - internal class KnownFolder - { - private static readonly Guid LocalAppDataGuid = new Guid("F1B32785-6FBA-4FCF-9D55-7B8E7F157091"); - public static string LocalAppData => SHGetKnownFolderPath(LocalAppDataGuid); - - private static readonly Guid LocalAppDataLowGuid = new Guid("A520A1A4-1780-4FF6-BD18-167343C5AF16"); - public static string LocalAppDataLow => SHGetKnownFolderPath(LocalAppDataLowGuid); - - /// - /// Retrieves the full path of a known folder identified by the - /// folder's KNOWNFOLDERID. - /// - /// - /// A reference to the KNOWNFOLDERID that identifies the folder. - /// - /// - public static string SHGetKnownFolderPath(Guid rfid) - { - var pPath = IntPtr.Zero; - string path; - try - { - var hr = SHGetKnownFolderPath(rfid, 0, IntPtr.Zero, out pPath); - if (hr != 0) throw Marshal.GetExceptionForHR(hr); - path = Marshal.PtrToStringUni(pPath); - } - finally - { - if (pPath != IntPtr.Zero) - { - Marshal.FreeCoTaskMem(pPath); - pPath = IntPtr.Zero; - } - } - return path; - } - - /// - /// Retrieves the full path of a known folder identified by the - /// folder's KNOWNFOLDERID. - /// - /// - /// A reference to the KNOWNFOLDERID that identifies the folder. - /// - /// - /// Flags that specify special retrieval options. - /// - /// - /// An access token that represents a particular user. If this - /// parameter is NULL, which is the most common usage, the function - /// requests the known folder for the current user. - /// - /// - /// When this method returns, contains the address of a pointer to a - /// null-terminated Unicode string that specifies the path of the - /// known folder. The calling process is responsible for freeing this - /// resource once it is no longer needed by calling CoTaskMemFree. - /// - /// HRESULT - [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)] - private static extern int SHGetKnownFolderPath( - [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, - uint dwFlags, - IntPtr hToken, - out IntPtr pszPath); - } -#endregion -} diff --git a/src/HASS.Agent/HASSAgent/Functions/PerformanceCounters.cs b/src/HASS.Agent/HASSAgent/Functions/PerformanceCounters.cs deleted file mode 100644 index c9d790c..0000000 --- a/src/HASS.Agent/HASSAgent/Functions/PerformanceCounters.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using Microsoft.Win32; - -namespace HASSAgent.Functions -{ - /// - /// Source: https://wojciechkulik.pl/csharp/get-a-performancecounter-using-english-name - /// - internal static class PerformanceCounters - { - [DllImport("pdh.dll", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern uint PdhLookupPerfNameByIndex(string szMachineName, uint dwNameIndex, StringBuilder szNameBuffer, ref uint pcchNameBufferSize); - - /// - /// Retrieve the counter based on its English category & -name - /// - /// - /// - /// - internal static PerformanceCounter GetSingleInstanceCounter(string englishCategoryName, string englishCounterName) - { - try - { - // try first with english names - return new PerformanceCounter(englishCategoryName, englishCounterName); - } - catch - { - // too bad - } - - const string perfCountersKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009"; - - // get list of counters & check them - if (!(Registry.GetValue(perfCountersKey, "Counter", null) is string[] englishNames)) return null; - if (!englishNames.Any()) return null; - - // filter the null values - englishNames = englishNames.Select(x => x).Where(x => !string.IsNullOrEmpty(x)).ToArray(); - - // anything left? - if (!englishNames.Any()) return null; - - // get localized category name - var localizedCategoryId = FindNameId(englishNames, englishCategoryName); - var localizedCategoryName = GetNameByIndex(localizedCategoryId); - - // get localized counter name - var localizedCounterId = FindNameId(englishNames, englishCounterName); - var localizedCounterName = GetNameByIndex(localizedCounterId); - - return GetCounterIfExists(localizedCategoryName, localizedCounterName) ?? - GetCounterIfExists(localizedCategoryName, englishCounterName) ?? - GetCounterIfExists(englishCategoryName, localizedCounterName); - } - - /// - /// Returns the counter if it's found, otherwise null - /// - /// - /// - /// - private static PerformanceCounter GetCounterIfExists(string categoryName, string counterName) - { - try - { - return new PerformanceCounter(categoryName, counterName); - } - catch - { - return null; - } - } - - /// - /// Retrieve the counter's ID based on its English name - /// - /// - /// - /// - - private static int FindNameId(IReadOnlyList englishNames, string name) - { - // englishNames contains alternately id and name, so only check odd lines - for (var i = 1; i < englishNames.Count; i += 2) - { - if (englishNames[i] == name) - { - return int.Parse(englishNames[i - 1]); - } - } - - return -1; - } - - /// - /// Retrieve the counter's name based on its ID - /// - /// - /// - private static string GetNameByIndex(int id) - { - if (id < 0) return null; - - var buffer = new StringBuilder(1024); - var bufSize = (uint)buffer.Capacity; - var ret = PdhLookupPerfNameByIndex(null, (uint)id, buffer, ref bufSize); - - return ret == 0 && buffer.Length != 0 ? buffer.ToString() : null; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Functions/PowershellManager.cs b/src/HASS.Agent/HASSAgent/Functions/PowershellManager.cs deleted file mode 100644 index f0f2c7b..0000000 --- a/src/HASS.Agent/HASSAgent/Functions/PowershellManager.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Serilog; - -namespace HASSAgent.Functions -{ - internal static class PowershellManager - { - /// - /// Execute a Powershell command without waiting for or checking results - /// - /// - /// - internal static bool ExecuteCommandHeadless(string command) => ExecuteHeadless(command, false); - - /// - /// Executes a Powershell script without waiting for or checking results - /// - /// - /// - internal static bool ExecuteScriptHeadless(string script) => ExecuteHeadless(script, true); - - private static bool ExecuteHeadless(string command, bool isScript) - { - var descriptor = isScript ? "script" : "command"; - - try - { - var workingDir = Variables.StartupPath; - if (isScript) - { - // try to get the script's startup path - var scriptDir = Path.GetDirectoryName(command); - workingDir = !string.IsNullOrEmpty(scriptDir) ? scriptDir : Variables.StartupPath; - } - - // find the powershell executable - var psExec = GetPsExecutable(); - if (string.IsNullOrEmpty(psExec)) return false; - - // prepare the executing process - var processInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - CreateNoWindow = true, - FileName = psExec, - WorkingDirectory = workingDir - }; - - // set the right type of arguments - processInfo.Arguments = isScript ? - $@"& '{command}'" - : $@"& {{{command}}}"; - - // launch - using (var process = new Process()) - { - process.StartInfo = processInfo; - var start = process.Start(); - - if (!start) - { - Log.Error("[POWERSHELL] Unable to start processing {descriptor}: {command}", descriptor, command); - return false; - } - - // done - return true; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[POWERSHELL] Fatal error when executing {descriptor}: {command}", descriptor, command); - return false; - } - } - - /// - /// Execute a Powershell command, logs the output if it fails - /// - /// - /// - /// - internal static bool ExecuteCommand(string command, TimeSpan timeout) => Execute(command, false, timeout); - - /// - /// Executes a Powershell script, logs the output if it fails - /// - /// - /// - /// - internal static bool ExecuteScript(string script, TimeSpan timeout) => Execute(script, true, timeout); - - private static bool Execute(string command, bool isScript, TimeSpan timeout) - { - var descriptor = isScript ? "script" : "command"; - - try - { - var workingDir = Variables.StartupPath; - if (isScript) - { - // try to get the script's startup path - var scriptDir = Path.GetDirectoryName(command); - workingDir = !string.IsNullOrEmpty(scriptDir) ? scriptDir : Variables.StartupPath; - } - - // find the powershell executable - var psExec = GetPsExecutable(); - if (string.IsNullOrEmpty(psExec)) return false; - - // prepare the executing process - var processInfo = new ProcessStartInfo - { - FileName = psExec, - RedirectStandardError = true, - RedirectStandardOutput = true, - UseShellExecute = false, - WorkingDirectory = workingDir - }; - - // set the right type of arguments - processInfo.Arguments = isScript ? - $@"& '{command}'" - : $@"& {{{command}}}"; - - // launch - using (var process = new Process()) - { - process.StartInfo = processInfo; - var start = process.Start(); - - if (!start) - { - Log.Error("[POWERSHELL] Unable to start processing {descriptor}: {script}", descriptor, command); - return false; - } - - // execute and wait - process.WaitForExit(Convert.ToInt32(timeout.TotalMilliseconds)); - - if (process.ExitCode == 0) - { - // done, all good - return true; - } - - // non-zero exitcode, process as failed - Log.Error("[POWERSHELL] The {descriptor} returned non-zero exitcode: {code}", descriptor, process.ExitCode); - - var errors = process.StandardError.ReadToEnd(); - if (!string.IsNullOrEmpty(errors)) Log.Error("[POWERSHELL] Error output:\r\n{output}", errors); - else - { - var console = process.StandardOutput.ReadToEnd(); - if (!string.IsNullOrEmpty(console)) Log.Error("[POWERSHELL] No error output, console output:\r\n{output}", errors); - else Log.Error("[POWERSHELL] No error and no console output"); - } - - // done - return false; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[POWERSHELL] Fatal error when executing {descriptor}: {command}", descriptor, command); - return false; - } - } - - /// - /// Attempt to locate powershell.exe - /// - /// - internal static string GetPsExecutable() - { - // try regular location - var psExec = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "WindowsPowerShell\\v1.0\\powershell.exe"); - if (File.Exists(psExec)) return psExec; - - // try specific - psExec = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "WindowsPowerShell\\v1.0\\powershell.exe"); - if (File.Exists(psExec)) return psExec; - - // not found - Log.Error("[POWERSHELL] PS executable not found, make sure you have powershell installed on your system"); - return string.Empty; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Functions/ScheduledTasks.cs b/src/HASS.Agent/HASSAgent/Functions/ScheduledTasks.cs deleted file mode 100644 index dcf0f3e..0000000 --- a/src/HASS.Agent/HASSAgent/Functions/ScheduledTasks.cs +++ /dev/null @@ -1,324 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; -using System.Threading.Tasks; -using Microsoft.Win32.TaskScheduler; -using Serilog; -using Task = System.Threading.Tasks.Task; - -namespace HASSAgent.Functions -{ - /// - /// Functions to check and create Windows 'Scheduled Tasks' - /// - internal static class ScheduledTasks - { - internal const string TaskName = "HASS.Agent"; - - /// - /// Depcrecated: Check whether the task is present - /// - /// - internal static bool IsTaskPresent() - { - try - { - using (var ts = new TaskService()) - { - var task = ts.FindTask(TaskName); - return task != null; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SCHEDULEDTASK] Error while checking task exists: {err}", ex.Message); - return false; - } - } - - /// - /// Depcrecated: Check our task status - /// - /// - internal static TaskState TaskStatus() - { - try - { - using (var ts = new TaskService()) - { - var task = ts.FindTask(TaskName); - return task?.State ?? TaskState.Unknown; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SCHEDULEDTASK] Error while getting task status: {err}", ex.Message); - return TaskState.Unknown; - } - } - - /// - /// Depcrecated: Install a launch-on-login task - /// - /// - /// - /// - internal static bool InstallLaunchOnLoginTask(string username, SecureString password) - { - try - { - using (var ts = new TaskService()) - { - // determine supported scheduler version - var supported = true; - var xp = false; - if (ts.HighestSupportedVersion.Major < 2) - { - supported = false; - xp = true; - } - else if (ts.HighestSupportedVersion.Minor < 1) supported = false; - - // prepare task definition - var taskDefinition = ts.NewTask(); - taskDefinition.RegistrationInfo.Description = "HASS.Agent launch-on-login task"; - taskDefinition.RegistrationInfo.Author = username; - - // prepare logon trigger - var logonTrigger = new LogonTrigger - { - Enabled = true, - UserId = username - }; - - // bind the trigger - taskDefinition.Triggers.Add(logonTrigger); - - // configure the task, based on supported version - if (!xp) - { - if (supported) taskDefinition.Settings.DisallowStartOnRemoteAppSession = false; - - taskDefinition.Principal.UserId = username; - taskDefinition.Principal.LogonType = TaskLogonType.InteractiveToken; - taskDefinition.Principal.RunLevel = TaskRunLevel.Highest; - - taskDefinition.Settings.AllowDemandStart = true; - taskDefinition.Settings.RestartCount = 3; - } - - taskDefinition.Settings.MultipleInstances = TaskInstancesPolicy.IgnoreNew; - - taskDefinition.Settings.StopIfGoingOnBatteries = false; - taskDefinition.Settings.DisallowStartIfOnBatteries = false; - - taskDefinition.Settings.Enabled = true; - taskDefinition.Settings.ExecutionTimeLimit = new TimeSpan(0); - - // add executable - taskDefinition.Actions.Add(new ExecAction(Variables.ApplicationExecutable)); - - // prepare password - var passwordBstr = Marshal.SecureStringToBSTR(password); - - // register task - ts.RootFolder.RegisterTaskDefinition(TaskName, taskDefinition, TaskCreation.CreateOrUpdate, username, Marshal.PtrToStringAuto(passwordBstr), TaskLogonType.InteractiveToken); - - // elevate the new task - var elevated = Elevate(); - if (!elevated) return false; - - // done - Log.Information("[SCHEDULEDTASK] Launch-on-login task created"); - return true; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SCHEDULEDTASK] Error while creating task: {err}", ex.Message); - return false; - } - } - - /// - /// Depcrecated: Enable 'run with highest privileges' - /// This has to be done after the task is created - /// - /// - private static bool Elevate() - { - try - { - using (var ts = new TaskService()) - { - var task = ts.FindTask(TaskName); - if (task == null) return false; - - if (task.Definition.Principal.RunLevel == TaskRunLevel.Highest) return true; - - task.Definition.Principal.RunLevel = TaskRunLevel.Highest; - task.RegisterChanges(); - - return true; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SCHEDULEDTASK] Error while elevating task: {err}", ex.Message); - return false; - } - } - - /// - /// Depcrecated: Sets the Scheduled Task to enabled - /// - /// - internal static bool Enable() - { - try - { - using (var ts = new TaskService()) - { - var task = ts.FindTask(TaskName); - if (task == null) return false; - - if (task.State != TaskState.Disabled) return true; - - task.Definition.Settings.Enabled = true; - task.RegisterChanges(); - - return true; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SCHEDULEDTASK] Error while reenabling task: {err}", ex.Message); - return false; - } - } - - /// - /// Checks and prepares the Scheduled Task, and finally removes it - /// - /// - internal static async Task RemoveAsync() - { - try - { - // check if task exists - using (var ts = new TaskService()) - { - var task = ts.FindTask(TaskName); - if (task == null) return true; - - // task found, get current state - Log.Information("[SCHEDULEDTASK] HASS.Agent task found, checking state .."); - - var taskState = TaskStatus(); - switch (taskState) - { - case TaskState.Running: - { - Log.Information("[SCHEDULEDTASK] Task still active, attempting to stop .."); - var stopped = Stop(); - if (!stopped) Log.Warning("[SCHEDULEDTASK] Stopping task failed, removal might fail"); - else Log.Information("[SCHEDULEDTASK] Task succesfully stopped, ready for removal"); - - // wait a bit - await Task.Delay(250); - break; - } - - case TaskState.Ready: - Log.Information("[SCHEDULEDTASK] Task is stopped, ready for removal"); - break; - - default: - Log.Information("[SCHEDULEDTASK] Task in unexpected state, removal might fail: {state}", - taskState.ToString()); - break; - } - - // remove the task - // remove the task from the containing folder - task.Folder.DeleteTask(TaskName, false); - - // give it some time - await Task.Delay(TimeSpan.FromSeconds(5)); - - // check if it's really gone - task = ts.FindTask(TaskName); - if (task != null) - { - Log.Error("[SCHEDULEDTASK] Task removal failed, still present"); - return false; - } - - // done - Log.Information("[SCHEDULEDTASK] Task succesfully removed"); - return true; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SCHEDULEDTASK] Error while processing scheduled task: {msg}", ex.Message); - return false; - } - } - - /// - /// Attempts to stop the Scheduled Task - /// - /// - internal static bool Stop() - { - try - { - using (var ts = new TaskService()) - { - var task = ts.FindTask(TaskName); - - if (task == null) return true; - - switch (task.State) - { - case TaskState.Running: - task.Stop(); - return true; - - case TaskState.Disabled: - task.Stop(); - Log.Warning("[SCHEDULEDTASK] Task is DISABLED, attempted to stop"); - return true; - - case TaskState.Queued: - task.Stop(); - Log.Warning("[SCHEDULEDTASK] Task is QUEUED, attempted to stop"); - return false; - - case TaskState.Ready: - return true; - - case TaskState.Unknown: - task.Stop(); - Log.Information("[SCHEDULEDTASK] Task state is UNKNOWN, attempted to stop"); - return true; - } - - return false; - } - } - catch (Exception ex) - { - if (ex.Message.Contains("0x80070534")) - { - Log.Error("[SCHEDULEDTASK] Task is corrupt, manual removal required"); - return false; - } - - Log.Fatal(ex, ex.Message); - return false; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Functions/SessionInfo.cs b/src/HASS.Agent/HASSAgent/Functions/SessionInfo.cs deleted file mode 100644 index 15b98cb..0000000 --- a/src/HASS.Agent/HASSAgent/Functions/SessionInfo.cs +++ /dev/null @@ -1,256 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using HASSAgent.Enums; -using Serilog; - -namespace HASSAgent.Functions -{ - /// - /// Sources: - /// - https://stackoverflow.com/a/36596656 - /// - https://github.com/murrayju/CreateProcessAsUser/blob/master/ProcessExtensions/ProcessExtensions.cs - /// - [SuppressMessage("ReSharper", "UnusedMember.Local")] - [SuppressMessage("ReSharper", "InconsistentNaming")] - internal static class SessionInfo - { - private const int FALSE = 0; - - private static readonly IntPtr WTS_CURRENT_SERVER = IntPtr.Zero; - - private const int WTS_SESSIONSTATE_LOCK = 0; - private const int WTS_SESSIONSTATE_UNLOCK = 1; - - private static readonly bool OsIsWin7 = false; - - static SessionInfo() - { - var osVersion = Environment.OSVersion; - OsIsWin7 = (osVersion.Platform == PlatformID.Win32NT && osVersion.Version.Major == 6 && osVersion.Version.Minor == 1); - } - - [DllImport("wtsapi32.dll")] - private static extern int WTSQuerySessionInformation( - IntPtr hServer, - [MarshalAs(UnmanagedType.U4)] uint SessionId, - [MarshalAs(UnmanagedType.U4)] WTS_INFO_CLASS WTSInfoClass, - out IntPtr ppBuffer, - [MarshalAs(UnmanagedType.U4)] out uint pBytesReturned - ); - - [DllImport("wtsapi32.dll")] - private static extern void WTSFreeMemoryEx( - WTS_TYPE_CLASS WTSTypeClass, - IntPtr pMemory, - uint NumberOfEntries - ); - - private enum WTS_INFO_CLASS - { - WTSInitialProgram = 0, - WTSApplicationName = 1, - WTSWorkingDirectory = 2, - WTSOEMId = 3, - WTSSessionId = 4, - WTSUserName = 5, - WTSWinStationName = 6, - WTSDomainName = 7, - WTSConnectState = 8, - WTSClientBuildNumber = 9, - WTSClientName = 10, - WTSClientDirectory = 11, - WTSClientProductId = 12, - WTSClientHardwareId = 13, - WTSClientAddress = 14, - WTSClientDisplay = 15, - WTSClientProtocolType = 16, - WTSIdleTime = 17, - WTSLogonTime = 18, - WTSIncomingBytes = 19, - WTSOutgoingBytes = 20, - WTSIncomingFrames = 21, - WTSOutgoingFrames = 22, - WTSClientInfo = 23, - WTSSessionInfo = 24, - WTSSessionInfoEx = 25, - WTSConfigInfo = 26, - WTSValidationInfo = 27, - WTSSessionAddressV4 = 28, - WTSIsRemoteSession = 29 - } - - private enum WTS_TYPE_CLASS - { - WTSTypeProcessInfoLevel0, - WTSTypeProcessInfoLevel1, - WTSTypeSessionInfoLevel1 - } - - private enum WTS_CONNECTSTATE_CLASS - { - WTSActive, - WTSConnected, - WTSConnectQuery, - WTSShadow, - WTSDisconnected, - WTSIdle, - WTSListen, - WTSReset, - WTSDown, - WTSInit - } - - [StructLayout(LayoutKind.Sequential)] - private struct WTSINFOEX - { - public readonly uint Level; - private readonly uint Reserved; - public readonly WTSINFOEX_LEVEL Data; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WTSINFOEX_LEVEL - { - public readonly WTSINFOEX_LEVEL1 WTSInfoExLevel1; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WTSINFOEX_LEVEL1 - { - private readonly uint SessionId; - private readonly WTS_CONNECTSTATE_CLASS SessionState; - public readonly int SessionFlags; - } - - [DllImport("wtsapi32.dll", ExactSpelling = true, SetLastError = false)] - private static extern void WTSFreeMemory(IntPtr memory); - - [DllImport("wtsapi32.dll", SetLastError = true)] - private static extern int WTSEnumerateSessions( - IntPtr hServer, - int Reserved, - int Version, - ref IntPtr ppSessionInfo, - ref int pCount); - - private const uint INVALID_SESSION_ID = 0xFFFFFFFF; - private static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; - - [StructLayout(LayoutKind.Sequential)] - private struct WTS_SESSION_INFO - { - public readonly uint SessionID; - [MarshalAs(UnmanagedType.LPStr)] - private readonly string pWinStationName; - public readonly WTS_CONNECTSTATE_CLASS State; - } - - /// - /// Retrieves the active session's lockstate - /// - /// - public static LockState GetActiveSessionLockState() - { - try - { - var activeSessionId = GetActiveUserId(); - if (activeSessionId == INVALID_SESSION_ID) return LockState.Unknown; - - var result = WTSQuerySessionInformation( - WTS_CURRENT_SERVER, - activeSessionId, - WTS_INFO_CLASS.WTSSessionInfoEx, - out var ppBuffer, - out _ - ); - - if (result == FALSE) return LockState.Unknown; - - var sessionInfoEx = Marshal.PtrToStructure(ppBuffer); - - if (sessionInfoEx.Level != 1) - { - WTSFreeMemory(ppBuffer); - return LockState.Unknown; - } - - var lockState = sessionInfoEx.Data.WTSInfoExLevel1.SessionFlags; - WTSFreeMemory(ppBuffer); - - if (OsIsWin7) - { - /* Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ee621019(v=vs.85).aspx - * Windows Server 2008 R2 and Windows 7: Due to a code defect, the usage of the WTS_SESSIONSTATE_LOCK - * and WTS_SESSIONSTATE_UNLOCK flags is reversed. That is, WTS_SESSIONSTATE_LOCK indicates that the - * session is unlocked, and WTS_SESSIONSTATE_UNLOCK indicates the session is locked. - * */ - switch (lockState) - { - case WTS_SESSIONSTATE_LOCK: - return LockState.Unlocked; - - case WTS_SESSIONSTATE_UNLOCK: - return LockState.Locked; - - default: - return LockState.Unknown; - } - } - - switch (lockState) - { - case WTS_SESSIONSTATE_LOCK: - return LockState.Locked; - - case WTS_SESSIONSTATE_UNLOCK: - return LockState.Unlocked; - - default: - return LockState.Unknown; - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SESSION] Error retrieving the active session state: {err}", ex.Message); - return LockState.Unknown; - } - } - - private static uint GetActiveUserId() - { - var activeSessionId = INVALID_SESSION_ID; - - try - { - var pSessionInfo = IntPtr.Zero; - var sessionCount = 0; - - // get a handle to the user access token for the current active session - if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref sessionCount) == 0) return activeSessionId; - - var arrayElementSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); - var current = pSessionInfo; - - for (var i = 0; i < sessionCount; i++) - { - var si = (WTS_SESSION_INFO)Marshal.PtrToStructure(current, typeof(WTS_SESSION_INFO)); - current += arrayElementSize; - - // we only want the active session - if (si.State != WTS_CONNECTSTATE_CLASS.WTSActive) continue; - - activeSessionId = si.SessionID; - break; - } - - return activeSessionId; - } - catch (Exception ex) - { - Log.Fatal(ex, "[SESSION] Error retrieving the active user ID: {err}", ex.Message); - return activeSessionId; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Functions/WindowsUpdatesManager.cs b/src/HASS.Agent/HASSAgent/Functions/WindowsUpdatesManager.cs deleted file mode 100644 index c0f0183..0000000 --- a/src/HASS.Agent/HASSAgent/Functions/WindowsUpdatesManager.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using HASSAgent.Models.Internal; -using Serilog; -using WUApiLib; - -namespace HASSAgent.Functions -{ - internal static class WindowsUpdatesManager - { - private static DateTime _lastCheck = DateTime.MinValue; - - private static List _driverUpdates = new List(); - private static List _softwareUpdates = new List(); - - /// - /// Attempts to look for available driver- and software updates (max once per 10 minutes) - /// - /// - internal static (List driverUpdates, List softwareUpdates) GetAvailableUpdates() - { - try - { - if ((DateTime.Now - _lastCheck).TotalMinutes < 10) return (_driverUpdates, _softwareUpdates); - _lastCheck = DateTime.Now; - - // reset the current lists - _driverUpdates = new List(); - _softwareUpdates = new List(); - - // fetch a new list - var updateList = GetUpdateList(); - if (!updateList.Any()) - { - // nothing, easy - return (_driverUpdates, _softwareUpdates); - } - - // split the returns - if (updateList.Any(x => x.Type == "Driver")) - { - // fetch all driver updates - _driverUpdates = updateList.Select(x => x).Where(x => x.Type == "Driver").ToList(); - } - - if (updateList.Any(x => x.Type == "Software")) - { - // fetch all software updates - _softwareUpdates = updateList.Select(x => x).Where(x => x.Type == "Software").ToList(); - } - - // all done! - return (_driverUpdates, _softwareUpdates); - } - catch (Exception ex) - { - Log.Fatal(ex, "[WUPDATE] Error while checking for available updates: {err}", ex.Message); - return (_driverUpdates, _softwareUpdates); - } - } - - private static List GetUpdateList() - { - try - { - var updateList = new List(); - - // prepare an updater session - var uSession = new UpdateSessionClass(); - - // prepare an updater searcher - var uSearcher = uSession.CreateUpdateSearcher(); - if (uSearcher == null) - { - Log.Error("[WUPDATE] Unable to create an update searcher, possibly corrupt?"); - return updateList; - } - - // we want all updates - uSearcher.ServerSelection = ServerSelection.ssOthers; - uSearcher.ServiceID = "7971f918-a847-4430-9279-4a52d1efe18d"; - - // search for all non-installed updates - var uResult = uSearcher.Search("IsInstalled=0"); - if (uResult == null) - { - Log.Error("[WUPDATE] Unable to search for updates, possibly corrupt?"); - return updateList; - } - - // process not-ok result codes - if (uResult.ResultCode != OperationResultCode.orcSucceeded) - { - switch (uResult.ResultCode) - { - case OperationResultCode.orcNotStarted: - Log.Error("[WUPDATE] Updater returned 'not started', is the service running?"); - break; - case OperationResultCode.orcInProgress: - Log.Warning("[WUPDATE] Updater returned 'in progress', try again later"); - break; - case OperationResultCode.orcSucceededWithErrors: - Log.Warning("[WUPDATE] Updater returned 'succeeded with errors', not all updates may be found"); - break; - case OperationResultCode.orcFailed: - Log.Error("[WUPDATE] Updater returned 'failed'"); - break; - case OperationResultCode.orcAborted: - Log.Error("[WUPDATE] Updater returned 'aborted', try again later"); - break; - } - } - - // check if there are warnings we need to log - if (uResult.Warnings != null && uResult.Warnings.Count > 0) - { - foreach (IUpdateException warning in uResult.Warnings) Log.Warning("[WUPDATE] Updater provided a warning (code: {code}): {msg}", warning.HResult, warning.Message ?? "-"); - } - - // check the update objects - if (uResult.Updates == null) - { - Log.Error("[WUPDATE] Searching for updates failed, returned null"); - return updateList; - } - - if (uResult.Updates.Count == 0) - { - // no updates found - return updateList; - } - - // start processing the updates - foreach (IUpdate update in uResult.Updates) - { - // prepare the category list - var categories = new List(); - if (update.Categories != null && update.Categories.Count > 0) - { - for (var i = 0; i < update.Categories.Count; i++) categories.Add(update.Categories[i].Name); - } - - // prepare the kb article list - var kbArticleIds = new List(); - if (update.KBArticleIDs != null && update.KBArticleIDs.Count > 0) - { - for (var i = 0; i < update.KBArticleIDs.Count; i++) kbArticleIds.Add(update.KBArticleIDs[i]); - } - - // prepare a readble type - var type = update.Type == UpdateType.utDriver ? "Driver" : "Software"; - - // fill the update info object - var wuInfo = new WindowsUpdateInfo() - { - Title = update.Title, - Description = update.Description, - KbArticleIDs = kbArticleIds, - Hidden = update.IsHidden, - SupportUrl = update.SupportUrl, - Type = type, - Categories = categories - }; - - // add to the list - updateList.Add(wuInfo); - } - - // done - return updateList; - } - catch (Exception ex) - { - var stackTrace = ex.StackTrace ?? ""; - - Log.Fatal(ex, stackTrace.Contains("WUApiLib") - ? "[WUPDATE] Unable to query update status, Windows update seems to be corrupt: {err}" - : "[WUPDATE] Error while searching for updates: {err}", ex.Message); - - return new List(); - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/HASSAgent.csproj b/src/HASS.Agent/HASSAgent/HASSAgent.csproj deleted file mode 100644 index bd1ae35..0000000 --- a/src/HASS.Agent/HASSAgent/HASSAgent.csproj +++ /dev/null @@ -1,695 +0,0 @@ - - - - - Debug - AnyCPU - {407FFF5A-97EA-429E-BD5E-81D93240A1BD} - WinExe - HASSAgent - HASS.Agent - v4.8 - 512 - true - true - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - hassagent.ico - - - app.manifest - - - true - bin\x64\Debug\ - DEBUG;TRACE - full - x64 - 7.3 - prompt - true - - - bin\x64\Release\ - TRACE - true - pdbonly - x64 - 7.3 - prompt - true - - - - False - Libraries\CustomGroupBox.dll - - - False - Libraries\HADotNet.Core.dll - - - False - Libraries\HotkeyListener.dll - - - - - - - - - - - - - - - - - - - - - UserControl - - - ExternalTools.cs - - - UserControl - - - Logging.cs - - - UserControl - - - LocalStorage.cs - - - UserControl - - - Updates.cs - - - UserControl - - - HotKey.cs - - - UserControl - - - Startup.cs - - - UserControl - - - MQTT.cs - - - UserControl - - - Notifications.cs - - - UserControl - - - HomeAssistantApi.cs - - - UserControl - - - General.cs - - - UserControl - - - 9-Done.cs - - - UserControl - - - 8-Updates.cs - - - UserControl - - - 7-HotKey.cs - - - UserControl - - - 6-MQTT.cs - - - UserControl - - - 5-API.cs - - - UserControl - - - 4-Integration.cs - - - UserControl - - - 3-Notifications.cs - - - UserControl - - - 2-Startup.cs - - - UserControl - - - 1-Welcome.cs - - - - - - - - Form - - - Restart.cs - - - Form - - - Help.cs - - - Form - - - About.cs - - - Form - - - CommandsMod.cs - - - Form - - - Configuration.cs - - - Form - - - Onboarding.cs - - - Form - - - PortReservation.cs - - - Form - - - ExitDialog.cs - - - Form - - - SensorsMod.cs - - - Form - - - PostUpdate.cs - - - Form - - - UpdatePending.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UserControl - - - QuickActionControl.cs - - - - - - - - - - Form - - - CommandsConfig.cs - - - Form - - - QuickActions.cs - - - Form - - - QuickActionsMod.cs - - - Form - - - QuickActionsConfig.cs - - - - Form - - - SensorsConfig.cs - - - - - - - - - - - - - - - - Form - - - Main.cs - - - - - - - - - - - - - - - - - - - ExternalTools.cs - - - Logging.cs - - - LocalStorage.cs - - - Updates.cs - - - HotKey.cs - - - Startup.cs - - - MQTT.cs - - - Notifications.cs - - - HomeAssistantApi.cs - - - General.cs - - - 9-Done.cs - - - 8-Updates.cs - - - 7-HotKey.cs - - - 6-MQTT.cs - - - 5-API.cs - - - 4-Integration.cs - - - 3-Notifications.cs - - - 2-Startup.cs - - - 1-Welcome.cs - - - QuickActionControl.cs - - - Restart.cs - - - Help.cs - - - About.cs - - - CommandsConfig.cs - - - CommandsMod.cs - - - Configuration.cs - Designer - - - Main.cs - - - Onboarding.cs - - - PortReservation.cs - - - ExitDialog.cs - - - QuickActions.cs - - - QuickActionsMod.cs - - - QuickActionsConfig.cs - - - SensorsConfig.cs - - - SensorsMod.cs - - - PostUpdate.cs - - - UpdatePending.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - PreserveNewest - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2.1.1 - - - 2.0.0.60 - - - 3.4.1 - - - 1.0.1 - - - 2.0.2 - - - 1.12.0 - - - 5.0.0-rc.8 - - - 0.8.9 - - - 7.1.2 - - - 3.1.2 - - - 3.1.2 - - - 13.0.1 - - - 0.50.0 - - - 3.1.0 - - - 1.5.0 - - - 5.0.0 - - - 19.2.0.62 - - - 19.2.0.62 - - - 19.2.0.62 - - - 19.2.0.62 - - - 2.10.1 - - - - - {B596CC9F-56E5-419E-A622-E01BB457431E} - 2 - 0 - 0 - tlbimp - False - False - - - - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Libraries/CustomGroupBox.dll b/src/HASS.Agent/HASSAgent/Libraries/CustomGroupBox.dll deleted file mode 100644 index f5af995d74594e0c4b66a1e25f6438503d1b4bc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5120 zcmeHLYit}>6+ScL*p8iUyX&OQqfN(g0$V3p?6ql=CM15W*L51_v1>a{z;dFcjj(JpLmfpB5J^M>lV=)nC0kWcxP}L;?RTN3enZ2*V^Au zc3*2Bn>9VX=sJ1VDCk+kwjE#32;D8&x@qf)y=lGR`t^!)LbWT2K`ta9rMLWAN18$0LVDjir=7k=tM_i zuIFY!v2T4qWT8TM>P8>DkGaBfpeR#DNAO5n5j=IHk7%HdWb_4@R}AT!N=s;}ohY%C zNMY`O4%Vutu(Y9bovMA3k>}JX(%+)$KY_715DkMFg_Dh))Yi3xq!jvL)q&G3s?#RL z%K=(6X9cF#h_WGiFOUdD@58k6&}4L_B*9))&psGk4N`N~05+*n*lb)Cy`Ndq&a#NQ zA^HH2`zNDoF-24ud=N-fuTs){oe|Y(2g6$j(Cl;o2Da-RRUNc*MJ2icsPiF!&Vlr< z0i}{jS(oFzv94H8S5Nm=5XiL!xJe`Gc#7x(=HE#??YpL(_oT+zrl8y%<7xUdaM{Kk z!{Z|f%ojj^6~T23SWZSNV<4N#ffcVQC?C<^l^#OAphAd~+d<;8eV|8hkWd1aOTK(0 zU(Rp?!%`(KPu8cDxYkI2VE8)3cT)-~jr1#eUTvfqMZ#f*KWF#_hHoztweo$$rP5iZ z-lnVC`AUXDGSPIOx|H5Wj>3SAvn-Or+#{so<&@j=)>^nQU!leQ=s!F zb%=gO7u8+huYl$yS_7R|X;PJV2A*G`?;!ejvDYE`5lxW+&J}R}NT1V8aC+1t>2!*| zth6(XQ7gSdF>0eP0j{C90Xyg#;6_-9Q4hmy^d9g*=08sV0G?+4A%yTMluXoj#8Phz%E11uJhK zb#f(3?4Xp$`i7miM3VBtpPnR-p~Md|evp!`Q|Nc|87g>L$FTT!8C*yXu3sgmuR1tIsuJ{i+8{W|G!!zu|%n@<9iJzo@J75!Kx zV$_xru5luGGgp-)M@rI;W#$Ilk~hoMK49kjS#F&G8!UOgQy6xgQgOgJ8OvD~3U2$Z zV^s~M#EgYDMDBQ(pfzX=*MpR>(PzSC!%4?Q1ZX*?WY5)6a}CK`*EJ}`vVLXFuxk`& z&8%15IAI!j+wuH5RyFbw+ZV1=Obhq8nH9AaRdKatYx1Bqkq#UzsP8jO+aEeEY#%45 zw)%i+=bRH>43QK(j^Z&PE66TaP^UOOQYczx*7U1+Vq>(|4rX~YlSm-1mr0^gVR$81 zFg`!qeAWSed*YpoO`Fc{dVb>%;ulh%{UJ5ziqfpUzYvp%qOuhF2s?Qo|lak&216^@FB|Krc*;%3u3hA|@qrY`YpRb_DyW-tM z4=J=hZsdBqXSRyXVoNT*xpyWrvpMt8+{2r@;=S=la>kbKOzsg}Nfc_8YhvB;Sa+<8 zXhfmau{}d$wU^1J$|?F7Za-TPQD}KhlrX)bWt8{ewG)wR^qNG6ZbR?^NBy2UcjnKs zmNMWoc&_6veqCOu>IPr&>*!QEk#37Wu&wKBoBF=-(%~y_eY5AhG?;vJD&b^H1@xvj zg;!_Eu=KQF%9)Oicg;~8L~p8cK!MCVybDPub94$XFSMUnAc_@p89GzBSxcv0k+?3g z#iM!y4_Z4Y0B>)Ws(MYmU4r5#e5adcFzSi$o~zBEHm< zza1v~5G8+gB}d}DfD`!kPXi873fKsKY3%_$0+@X3dk34Z=I zmael-7vc{7dMP7wfIFGY#~|z#@F%bu@34yH9dvh1R^n|#qmU`A z_3+3zvV_x#k>vH&s1mG^Wgm<4Vi=?n*81$jFys#CA}l*}lI?6kMwMDj6R_h#e=Y}c z_MscMvu^kzVT@x-;&!KSHho@W!#k@kf;;USqa1YQuNnfT!_IEl$g>5Rts<2wG6W*ar7^S)cjq7gnhn>B1WI@!EbwC%dPBuC$O@9VcRb Zl|N{`+`l&T;QtIRZ>w?skNgj1;NRBNcH;m5 diff --git a/src/HASS.Agent/HASSAgent/Libraries/CustomGroupBox.pdb b/src/HASS.Agent/HASSAgent/Libraries/CustomGroupBox.pdb deleted file mode 100644 index 2ba666b85a9bf379a8e242ac824ec1a25c0259be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19968 zcmeHNeQX@X6`ylVhzU+|b}+>G-~tXMPJBN5?8FX%B=*H2fSZ6_8jz`bciu}bv2UH- zb)0~NEJPBcRxJ=DKmq~c50Kgjs)n{|L5*k?sU@mVkx>3aE~wl|pZkPztksVdp~F$++P`+|LBMH4>W!B-aks#zxbbujlb+P@?opY$1&u}|1aHEaq8b? zN8e~{`R}_o|G(#pGf!<@wEOt(gAGTl!CAI#=cDcNVNAL5|F#)lE$DrH+dE$ku6?NB zg#$fjm)+;If0(#s>)}W0PImtOKt9+iAIC8J?==D30fd;R5QOJqp`HT}?Ac_QeZ5WQ-t5_M5&?kJnvSmF*7vxr+ivTX;^mJ%-p!AF5D2_VB1DdqI=&4$Fb6h zKF6@BM-B%`JuIz9#&A-@dhGG)5m$P|&(R}?_JHeq4a-Rzc84DG=1j`W@n|sxbT4{D zY1PYYHR*q%=y6QgTJ^tFrz(q~>{XS%R8gONw*?ly7YUs3h;c7CA7F%FCXn@NR7LvY zdZgL*>0|F7+JQ8EL;sQI4F=PXS~m6OpAS=({-rE=URnBD%ig%1;BsF2iazyG@Jb z1z_v?11tc{a*2Fm3D0DEa!T1_*AJ`y>(snk>ZyXNSQQJP-F?zx=E8d^ZY!~I8vLB~2U1q->ZZWMM{vko#Yeiw<-`0J6?6-Hlz4_H; zMFoHQ)sdfqC0a!cJRu696K%xxfw3rLJ=bRQSqM1p68VJu%m`9)I9oDX3g}KEdh`1czFrwf;(^>bNN)k%Xf^uj>~n&7#`0U(ZJ@6h+{&zZZe7{Q|?br~Xd?2{7b931}(k0?_%Ol)nOW6X=zo zcY}gA5C<&>?FC&3dOzqQ(4T`Y27MlM3FsT3SA!Odo1jZrVH7k8TnStZtW@b+LEELi z++VpSXb(b2K3&S#`!*o^=A5SfM}QX#80#-Dsy@9Q9adl>-33ZL_ba+v(WQ#MqUh6# zHY&dBwOHj)H;V6+gn@TI4>#J%sCyYyM_n zJJ5&8V}T`NnLKmo*1#ACe3@A8;YU_Q2sPXf-Fh)u@0$m^uIKVqy;>nkRJ{jfJ@-J@ zvTm7@jq<#7`{0=w5F-bvmUqjQeBI=+=~U8WUKVBb*^ouVXH9Vn(8v8nH36P`bH$=x z%oC+f5UcGIRDhVD#LvD&~F{Sfv=^SyDI>S5UI(AF-^V}$6 z_}r{mwXvZ-+OP_H0YSGrc0a|U&=r&C&ZujHSR0FHws+%=U^u{8Sz8;8)F??E^Lf?l~my(dja^Ceu z19`mjE*;H4o;;qB$H(9m;Eki00+7<L*0*sM_ zfU|L)Fc#5?Kn$sd6DU7{%=N$>9t - /// Returns the name of the commandtype - /// - /// - /// - public static string GetCommandName(this CommandType commandType) - { - var commandName = commandType.ToString().ToLower().Replace("command", ""); - return $"{HelperFunctions.GetSafeConfiguredDeviceName()}_{commandName}"; - } - } - - public class ConfiguredCommand - { - [JsonConverter(typeof(StringEnumConverter))] - public CommandType Type { get; set; } - public Guid Id { get; set; } = Guid.Empty; - public string Command { get; set; } - public byte KeyCode { get; set; } - public bool RunAsLowIntegrity { get; set; } = false; - public string Name { get; set; } - public List Keys { get; set; } = new List(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/Config/ConfiguredSensor.cs b/src/HASS.Agent/HASSAgent/Models/Config/ConfiguredSensor.cs deleted file mode 100644 index 2022810..0000000 --- a/src/HASS.Agent/HASSAgent/Models/Config/ConfiguredSensor.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using HASSAgent.Enums; -using HASSAgent.Functions; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace HASSAgent.Models.Config -{ - public static class SensorExtensions - { - /// - /// Returns TRUE if the configured sensor is single-value - /// - /// - /// - public static bool IsSingleValue(this ConfiguredSensor configuredSensor) => configuredSensor.Type.IsSingleValue(); - - /// - /// Returns TRUE if the sensor-type is single-value - /// - /// - /// - public static bool IsSingleValue(this SensorType sensorType) - { - return sensorType != SensorType.StorageSensors - && sensorType != SensorType.NetworkSensors - && sensorType != SensorType.WindowsUpdatesSensors - && sensorType != SensorType.BatterySensors - && sensorType != SensorType.DisplaySensors - && sensorType != SensorType.AudioSensors; - } - - /// - /// Returns the name of the sensortype - /// - /// - /// - public static string GetSensorName(this SensorType sensorType) - { - var sensorName = sensorType.ToString().ToLower().Replace("sensors", "").Replace("sensor", ""); - return $"{HelperFunctions.GetSafeConfiguredDeviceName()}_{sensorName}"; - } - } - - public class ConfiguredSensor - { - [JsonConverter(typeof(StringEnumConverter))] - public SensorType Type { get; set; } - public Guid Id { get; set; } = Guid.Empty; - public int? UpdateInterval { get; set; } - public string Query { get; set; } - public string Scope { get; set; } - public string WindowName { get; set; } - public string Category { get; set; } - public string Counter { get; set; } - public string Instance { get; set; } - public string Name { get; set; } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/AbstractDiscoverable.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/AbstractDiscoverable.cs deleted file mode 100644 index 809abd7..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/AbstractDiscoverable.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Text.RegularExpressions; - -namespace HASSAgent.Models.HomeAssistant -{ - public abstract class AbstractDiscoverable - { - public abstract string Domain { get; } - public string Name { get; set; } - public string TopicName { get; set; } - - private string _objectId; - public string ObjectId - { - get - { - if (!string.IsNullOrEmpty(_objectId)) return _objectId; - - _objectId = Regex.Replace(Name, "[^a-zA-Z0-9_-]", "_"); - return _objectId; - } - - set => _objectId = Regex.Replace(value, "[^a-zA-Z0-9_-]", "_"); - } - - - public string Id { get; set; } - - public abstract DiscoveryConfigModel GetAutoDiscoveryConfig(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/AbstractCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/AbstractCommand.cs deleted file mode 100644 index 143fad8..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/AbstractCommand.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Threading.Tasks; -using HASSAgent.Mqtt; -using MQTTnet; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Commands -{ - public abstract class AbstractCommand : AbstractDiscoverable - { - public int UpdateIntervalSeconds => 1; - public DateTime? LastUpdated { get; set; } - public string PreviousPublishedState { get; set; } - public override string Domain => "switch"; - - internal AbstractCommand(string name, string id = default) - { - Id = id == Guid.Empty.ToString() ? Guid.NewGuid().ToString() : id; - Name = name; - } - - protected CommandDiscoveryConfigModel AutoDiscoveryConfigModel; - protected CommandDiscoveryConfigModel SetAutoDiscoveryConfigModel(CommandDiscoveryConfigModel config) - { - AutoDiscoveryConfigModel = config; - return config; - } - - public abstract string GetState(); - - public async Task PublishStateAsync(bool respectChecks = true) - { - try - { - var state = GetState(); - - if (respectChecks) - { - if (LastUpdated.HasValue && LastUpdated.Value.AddSeconds(UpdateIntervalSeconds) > DateTime.Now) return; - if (PreviousPublishedState == state) return; - } - - var message = new MqttApplicationMessageBuilder() - .WithTopic(GetAutoDiscoveryConfig().State_topic) - .WithPayload(state) - .WithExactlyOnceQoS() - .WithRetainFlag() - .Build(); - - await MqttManager.PublishAsync(message); - - PreviousPublishedState = state; - LastUpdated = DateTime.Now; - } - catch (Exception ex) - { - Log.Fatal("[COMMAND] [{name}] Error publishing state: {err}", Name, ex.Message); - } - } - - public async Task PublishAutoDiscoveryConfigAsync() - { - await MqttManager.AnnounceAutoDiscoveryConfigAsync(this, Domain); - } - - public async Task UnPublishAutoDiscoveryConfigAsync() - { - await MqttManager.AnnounceAutoDiscoveryConfigAsync(this, Domain, true); - } - - public abstract void TurnOn(); - public abstract void TurnOff(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommand.cs deleted file mode 100644 index 86a5423..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommand.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using HASSAgent.Functions; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Commands -{ - public class CustomCommand : AbstractCommand - { - public string Command { get; protected set; } - public string State { get; protected set; } - public bool RunAsLowIntegrity { get; protected set; } - public Process Process { get; set; } = null; - - public CustomCommand(string command, bool runAsLowIntegrity, string name = "Custom", string id = default) : base(name ?? "Custom", id) - { - Command = command; - RunAsLowIntegrity = runAsLowIntegrity; - State = "OFF"; - } - - public override void TurnOn() - { - State = "ON"; - - if (RunAsLowIntegrity) CommandLineManager.LaunchAsLowIntegrity(Command); - else - { - var executed = CommandLineManager.ExecuteHeadless(Command); - - if (!executed) - { - Log.Error("[COMMAND] Launching command '{name}' failed", Name); - State = "FAILED"; - return; - } - } - - State = "OFF"; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return new CommandDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability", - Command_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/set", - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Device = Variables.DeviceConfig, - }; - } - - public override string GetState() - { - return State; - } - - public override void TurnOff() - { - Process?.Kill(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/HibernateCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/HibernateCommand.cs deleted file mode 100644 index ace5ce1..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/HibernateCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.CustomCommands -{ - internal class HibernateCommand : CustomCommand - { - internal HibernateCommand(string name = "Hibernate", string id = default) : base("shutdown /h", false, name ?? "Hibernate", id) - { - State = "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LockCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LockCommand.cs deleted file mode 100644 index 3fd1052..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LockCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.CustomCommands -{ - internal class LockCommand : CustomCommand - { - internal LockCommand(string name = "Lock", string id = default) : base("Rundll32.exe user32.dll,LockWorkStation", false, name ?? "Lock", id) - { - State = "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LogOffCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LogOffCommand.cs deleted file mode 100644 index a581493..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/LogOffCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.CustomCommands -{ - internal class LogOffCommand : CustomCommand - { - internal LogOffCommand(string name = "LogOff", string id = default) : base("shutdown /l", false, name ?? "LogOff", id) - { - State = "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/RestartCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/RestartCommand.cs deleted file mode 100644 index 50e2e82..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/RestartCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.CustomCommands -{ - internal class RestartCommand : CustomCommand - { - internal RestartCommand(string name = "Restart", string id = default) : base("shutdown /r", false, name ?? "Restart", id) - { - State = "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/ShutdownCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/ShutdownCommand.cs deleted file mode 100644 index f3fa394..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/ShutdownCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.CustomCommands -{ - internal class ShutdownCommand : CustomCommand - { - internal ShutdownCommand(string name = "Shutdown", string id = default) : base("shutdown /s", false, name ?? "Shutdown", id) - { - State = "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/SleepCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/SleepCommand.cs deleted file mode 100644 index b08ed65..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/CustomCommands/SleepCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.CustomCommands -{ - internal class SleepCommand : CustomCommand - { - internal SleepCommand(string name = "Sleep", string id = default) : base("Rundll32.exe powrprof.dll,SetSuspendState 0,1,0", false, name ?? "Sleep", id) - { - State = "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommand.cs deleted file mode 100644 index 5dc945f..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommand.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using HASSAgent.Functions; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Commands -{ - public class InternalCommand : AbstractCommand - { - public string State { get; protected set; } - public string CommandConfig { get; protected set; } - - public InternalCommand(string name = "Internal", string commandConfig = "", string id = default) : base(name ?? "Internal", id) - { - State = "OFF"; - CommandConfig = commandConfig; - } - - public override void TurnOn() - { - State = "ON"; - - // to be overriden - - State = "OFF"; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return new CommandDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability", - Command_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/set", - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Device = Variables.DeviceConfig, - }; - } - - public override string GetState() - { - return State; - } - - public override void TurnOff() - { - // - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/CustomExecutorCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/CustomExecutorCommand.cs deleted file mode 100644 index 3802f63..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/CustomExecutorCommand.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using HASSAgent.Functions; -using HASSAgent.Models.Internal; -using HASSAgent.Sensors; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Commands.InternalCommands -{ - internal class CustomExecutorCommand : InternalCommand - { - internal CustomExecutorCommand(string name = "CustomExecutor", string command = "", string id = default) : base(name ?? "CustomExecutor", command, id) - { - CommandConfig = command; - State = "OFF"; - } - - public override void TurnOn() - { - State = "ON"; - - try - { - // is there a custom executor provided? - if (string.IsNullOrEmpty(Variables.AppSettings.CustomExecutorBinary)) - { - Log.Warning("[CUSTOMEXECUTOR] No custom executor provided, unable to execute"); - return; - } - - // does the binary still exist? - if (!File.Exists(Variables.AppSettings.CustomExecutorBinary)) - { - Log.Error("[CUSTOMEXECUTOR] Provided custom executor not found: {file}", Variables.AppSettings.CustomExecutorBinary); - return; - } - - // all good, launch - using (var process = new Process()) - { - var startInfo = new ProcessStartInfo - { - WindowStyle = ProcessWindowStyle.Hidden, - CreateNoWindow = true, - FileName = Variables.AppSettings.CustomExecutorBinary, - Arguments = CommandConfig - }; - - process.StartInfo = startInfo; - var start = process.Start(); - - // check if the start went ok - if (!start) - { - Log.Error("[CUSTOMEXECUTOR] Unable to start executing command: {command}", CommandConfig); - return; - } - - // yep, done - } - } - catch (Exception ex) - { - Log.Error("[CUSTOMEXECUTOR] Error while processing custom executor: {err}", ex.Message); - } - finally - { - State = "OFF"; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommand.cs deleted file mode 100644 index 74bf82a..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommand.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; - -namespace HASSAgent.Models.HomeAssistant.Commands -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public class KeyCommand : AbstractCommand - { - internal const int KEYEVENTF_EXTENTEDKEY = 1; - internal const int KEYEVENTF_KEYUP = 0; - internal const int VK_MEDIA_NEXT_TRACK = 0xB0; - internal const int VK_MEDIA_PLAY_PAUSE = 0xB3; - internal const int VK_MEDIA_PREV_TRACK = 0xB1; - internal const int VK_VOLUME_MUTE = 0xAD; - internal const int VK_VOLUME_UP = 0xAF; - internal const int VK_VOLUME_DOWN = 0xAE; - - public byte KeyCode { get; set; } - - internal KeyCommand(byte keyCode, string name = "Key", string id = default) : base(name ?? "Key", id) - { - KeyCode = keyCode; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return new CommandDiscoveryConfigModel - { - Name = Name, - Unique_id = Id, - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability", - Command_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/set", - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Device = Variables.DeviceConfig - }; - } - - [DllImport("user32.dll")] - internal static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo); - - public override string GetState() - { - return "OFF"; - } - - public override void TurnOff() - { - // - } - - public override void TurnOn() - { - keybd_event(KeyCode, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaMuteCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaMuteCommand.cs deleted file mode 100644 index 12d04ff..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaMuteCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.KeyCommands -{ - internal class MediaMuteCommand : KeyCommand - { - internal MediaMuteCommand(string name = "Mute", string id = default) : base(VK_VOLUME_MUTE, name ?? "Mute", id) { } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaNextCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaNextCommand.cs deleted file mode 100644 index 144b98a..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaNextCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.KeyCommands -{ - internal class MediaNextCommand : KeyCommand - { - internal MediaNextCommand(string name = "Next", string id = default) : base(VK_MEDIA_NEXT_TRACK, name ?? "Next", id) { } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPlayPauseCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPlayPauseCommand.cs deleted file mode 100644 index 3c137a6..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPlayPauseCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.KeyCommands -{ - internal class MediaPlayPauseCommand : KeyCommand - { - internal MediaPlayPauseCommand(string name = "PlayPause", string id = default) : base(VK_MEDIA_PLAY_PAUSE, name ?? "PlayPause", id) { } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPreviousCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPreviousCommand.cs deleted file mode 100644 index 4071e7a..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaPreviousCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.KeyCommands -{ - internal class MediaPreviousCommand : KeyCommand - { - internal MediaPreviousCommand(string name = "Previous", string id = default) : base(VK_MEDIA_PREV_TRACK, name ?? "Previous", id) { } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeDownCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeDownCommand.cs deleted file mode 100644 index 1949228..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeDownCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.KeyCommands -{ - internal class MediaVolumeDownCommand : KeyCommand - { - internal MediaVolumeDownCommand(string name = "VolumeDown", string id = default) : base(VK_VOLUME_DOWN, name ?? "VolumeDown", id) { } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeUpCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeUpCommand.cs deleted file mode 100644 index 98b0f8a..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/KeyCommands/MediaVolumeUpCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Commands.KeyCommands -{ - internal class MediaVolumeUpCommand : KeyCommand - { - internal MediaVolumeUpCommand(string name = "VolumeUp", string id = default) : base(VK_VOLUME_UP, name ?? "VolumeUp", id) { } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/MultipleKeysCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/MultipleKeysCommand.cs deleted file mode 100644 index fde81eb..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/MultipleKeysCommand.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Serilog; -using System.Windows.Forms; - -namespace HASSAgent.Models.HomeAssistant.Commands -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public class MultipleKeysCommand : AbstractCommand - { - public List Keys { get; set; } - - internal MultipleKeysCommand(List keys, string name = "MultipleKeys", string id = default) : base(name ?? "MultipleKeys", id) - { - Keys = keys; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return new CommandDiscoveryConfigModel - { - Name = Name, - Unique_id = Id, - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability", - Command_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/set", - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Device = Variables.DeviceConfig - }; - } - - public override string GetState() => "OFF"; - - public override void TurnOff() - { - // - } - - public override async void TurnOn() - { - try - { - foreach (var key in Keys) - { - SendKeys.SendWait(key); - SendKeys.Flush(); - await Task.Delay(50); - } - } - catch (Exception ex) - { - Log.Error("[COMMAND] Launching command '{name}' failed: {ex}", Name, ex.Message); - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/PowershellCommand.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/PowershellCommand.cs deleted file mode 100644 index 3a02abc..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/PowershellCommand.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using HASSAgent.Functions; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Commands -{ - public class PowershellCommand : AbstractCommand - { - public string Command { get; protected set; } - public string State { get; protected set; } - public Process Process { get; set; } - - private readonly bool _isScript = false; - private readonly string _descriptor = "command"; - - public PowershellCommand(string command, string name = "Powershell", string id = default) : base(name ?? "Powershell", id) - { - Command = command; - if (Command.ToLower().EndsWith(".ps1")) - { - _isScript = true; - _descriptor = "script"; - } - - State = "OFF"; - } - - public override void TurnOn() - { - State = "ON"; - - var executed = _isScript - ? PowershellManager.ExecuteScriptHeadless(Command) - : PowershellManager.ExecuteCommandHeadless(Command); - - if (!executed) - { - Log.Error("[COMMAND] Launching PS {descriptor} '{name}' failed", _descriptor, Name); - State = "FAILED"; - } - else State = "OFF"; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return new CommandDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability", - Command_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/set", - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Device = Variables.DeviceConfig, - }; - } - - public override string GetState() - { - return State; - } - - public override void TurnOff() - { - Process.Kill(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/DiscoveryConfigModel.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/DiscoveryConfigModel.cs deleted file mode 100644 index b4d398e..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/DiscoveryConfigModel.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -namespace HASSAgent.Models.HomeAssistant -{ - [SuppressMessage("ReSharper", "InconsistentNaming")] - public abstract class DiscoveryConfigModel - { - /// - /// (Optional) Information about the device this sensor is a part of to tie it into the device registry. Only works through MQTT discovery and when unique_id is set. - /// - /// - public DeviceConfigModel Device { get; set; } - /// - /// (Optional) The name of the MQTT sensor. Defaults to MQTT Sensor in hass. - /// - /// - public string Name { get; set; } - /// - /// The MQTT topic subscribed to receive sensor values. - /// - /// - public string State_topic { get; set; } - } - - [SuppressMessage("ReSharper", "InconsistentNaming")] - public class SensorDiscoveryConfigModel : DiscoveryConfigModel - { - /// - /// (Optional) The MQTT topic subscribed to receive availability (online/offline) updates. - /// - /// - public string Availability_topic { get; set; } - /// - /// (Optional) The type/class of the sensor to set the icon in the frontend. See https://www.home-assistant.io/integrations/sensor/#device-class for options. - /// - /// - public string Device_class { get; set; } - /// - /// (Optional) Defines the number of seconds after the sensor’s state expires, if it’s not updated. After expiry, the sensor’s state becomes unavailable. Defaults to 0 in hass. - /// - /// - public int? Expire_after { get; set; } - /// - /// Sends update events even if the value hasn’t changed. Useful if you want to have meaningful value graphs in history. - /// - /// - public bool? Force_update { get; set; } - - /// - /// (Optional) The icon for the sensor. - /// - /// - public string Icon { get; set; } - /// - /// (Optional) Defines a template to extract the JSON dictionary from messages received on the json_attributes_topic. - /// - /// - public string Json_attributes_template { get; set; } - /// - /// (Optional) The MQTT topic subscribed to receive a JSON dictionary payload and then set as sensor attributes. Implies force_update of the current sensor state when a message is received on this topic. - /// - /// - public string Json_attributes_topic { get; set; } - /// - /// (Optional) The payload that represents the available state. - /// - /// - public string Payload_available { get; set; } - /// - /// (Optional) The payload that represents the unavailable state. - /// - /// - public string Payload_not_available { get; set; } - /// - /// (Optional) The maximum QoS level of the state topic. - /// - /// - public int? Qos { get; set; } - /// - /// (Optional) An ID that uniquely identifies this sensor. If two sensors have the same unique ID, Home Assistant will raise an exception. - /// - /// - public string Unique_id { get; set; } - /// - /// (Optional) Defines the units of measurement of the sensor, if any. - /// - /// - public string Unit_of_measurement { get; set; } - /// - /// (Optional) Defines a template to extract the value. - /// - /// - public string Value_template { get; set; } - } - - [SuppressMessage("ReSharper", "InconsistentNaming")] - public class CommandDiscoveryConfigModel : DiscoveryConfigModel - { - /// - /// (Optional) The MQTT topic subscribed to receive availability (online/offline) updates. - /// - /// - public string Availability_topic { get; set; } - /// - /// (Optional) The MQTT topic to set the command - /// - /// - public string Command_topic { get; set; } - /// - /// (Optional) The type/class of the sensor to set the icon in the frontend. See https://www.home-assistant.io/integrations/sensor/#device-class for options. - /// - /// - public string Device_class { get; set; } - - /// - /// Sends update events even if the value hasn’t changed. Useful if you want to have meaningful value graphs in history. - /// - /// - public bool? Force_update { get; set; } - - /// - /// (Optional) The icon for the sensor. - /// - /// - public string Icon { get; set; } - /// - /// (Optional) Defines a template to extract the JSON dictionary from messages received on the json_attributes_topic. - /// - /// - public string Json_attributes_template { get; set; } - /// - /// (Optional) The MQTT topic subscribed to receive a JSON dictionary payload and then set as sensor attributes. Implies force_update of the current sensor state when a message is received on this topic. - /// - /// - public string Json_attributes_topic { get; set; } - /// - /// (Optional) The payload that represents the available state. - /// - /// - public string Payload_available { get; set; } - /// - /// (Optional) The payload that represents the unavailable state. - /// - /// - public string Payload_not_available { get; set; } - /// - /// (Optional) The maximum QoS level of the state topic. - /// - /// - public int? Qos { get; set; } - /// - /// (Optional) An ID that uniquely identifies this sensor. If two sensors have the same unique ID, Home Assistant will raise an exception. - /// - /// - public string Unique_id { get; set; } - /// - /// (Optional) Defines a template to extract the value. - /// - /// - public string Value_template { get; set; } - } - - /// - /// This information will be used when announcing this device on the mqtt topic - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - public class DeviceConfigModel - { - /// - /// (Optional) A list of connections of the device to the outside world as a list of tuples [connection_type, connection_identifier]. For example the MAC address of a network interface: "connections": [["mac", "02:5b:26:a8:dc:12"]]. - /// - /// - public ICollection> Connections { get; set; } - /// - /// (Optional) An Id to identify the device. For example a serial number. - /// - /// - public string Identifiers { get; set; } - /// - /// (Optional) The manufacturer of the device. - /// - /// - public string Manufacturer { get; set; } - /// - /// (Optional) The model of the device. - /// - /// - public string Model { get; set; } - /// - /// (Optional) The name of the device. - /// - /// - public string Name { get; set; } - /// - /// (Optional) The firmware version of the device. - /// - /// - public string Sw_version { get; set; } - /// - /// (Optional) Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs, or parent devices of a sub-device. This is used to show device topology in Home Assistant. - /// - /// - public string Via_device { get; set; } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractMultiValueSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractMultiValueSensor.cs deleted file mode 100644 index 9f3d279..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractMultiValueSensor.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors -{ - public abstract class AbstractMultiValueSensor : AbstractDiscoverable - { - public int UpdateIntervalSeconds { get; protected set; } - public DateTime? LastUpdated { get; protected set; } - public override string Domain => "sensor"; - - public abstract Dictionary Sensors { get; protected set; } - - internal AbstractMultiValueSensor(string name, int updateIntervalSeconds = 10, string id = default) - { - Id = id == Guid.Empty.ToString() ? Guid.NewGuid().ToString() : id; - Name = name; - UpdateIntervalSeconds = updateIntervalSeconds; - } - - public abstract void UpdateSensorValues(); - - public void ResetChecks() - { - LastUpdated = DateTime.MinValue; - foreach (var sensor in Sensors) sensor.Value.ResetChecks(); - } - - public async Task PublishStatesAsync(bool respectChecks = true) - { - try - { - if (respectChecks) - { - if (LastUpdated.HasValue && LastUpdated.Value.AddSeconds(UpdateIntervalSeconds) > DateTime.Now) return; - } - - if (Sensors == null || !Sensors.Any()) return; - - // fetch new values for all sensors - UpdateSensorValues(); - - // update their values - foreach (var sensor in Sensors) await sensor.Value.PublishStateAsync(respectChecks); - - LastUpdated = DateTime.Now; - } - catch (Exception ex) - { - Log.Fatal("[SENSOR] [{name}] Error publishing state: {err}", Name, ex.Message); - } - } - - public async Task PublishAutoDiscoveryConfigAsync() - { - foreach (var sensor in Sensors) await sensor.Value.PublishAutoDiscoveryConfigAsync(); - } - - public async Task UnPublishAutoDiscoveryConfigAsync() - { - foreach (var sensor in Sensors) await sensor.Value.UnPublishAutoDiscoveryConfigAsync(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractSingleValueSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractSingleValueSensor.cs deleted file mode 100644 index 1a48c8b..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/AbstractSingleValueSensor.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using HASSAgent.Mqtt; -using MQTTnet; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors -{ - public abstract class AbstractSingleValueSensor : AbstractDiscoverable - { - public int UpdateIntervalSeconds { get; protected set; } - public DateTime? LastUpdated { get; protected set; } - public string PreviousPublishedState { get; protected set; } - public override string Domain => "sensor"; - - internal AbstractSingleValueSensor(string name, int updateIntervalSeconds = 10, string id = default) - { - Id = id == Guid.Empty.ToString() ? Guid.NewGuid().ToString() : id; - Name = name; - UpdateIntervalSeconds = updateIntervalSeconds; - } - - protected SensorDiscoveryConfigModel AutoDiscoveryConfigModel; - protected SensorDiscoveryConfigModel SetAutoDiscoveryConfigModel(SensorDiscoveryConfigModel config) - { - AutoDiscoveryConfigModel = config; - return config; - } - - public abstract string GetState(); - - public void ResetChecks() - { - LastUpdated = DateTime.MinValue; - PreviousPublishedState = string.Empty; - } - - public async Task PublishStateAsync(bool respectChecks = true) - { - try - { - if (respectChecks) - { - if (LastUpdated.HasValue && LastUpdated.Value.AddSeconds(UpdateIntervalSeconds) > DateTime.Now) return; - } - - var state = GetState(); - - if (respectChecks) - { - if (PreviousPublishedState == state) return; - } - - var message = new MqttApplicationMessageBuilder() - .WithTopic(GetAutoDiscoveryConfig().State_topic) - .WithPayload(state) - .Build(); - - await MqttManager.PublishAsync(message); - - // only store the state if the checks are respected - // otherwise, we might stay in 'unknown' state untill the value changes - if (!respectChecks) return; - - PreviousPublishedState = state; - LastUpdated = DateTime.Now; - } - catch (Exception ex) - { - Log.Fatal("[SENSOR] [{name}] Error publishing state: {err}", Name, ex.Message); - } - } - - public async Task PublishAutoDiscoveryConfigAsync() - { - await MqttManager.AnnounceAutoDiscoveryConfigAsync(this, Domain); - } - - public async Task UnPublishAutoDiscoveryConfigAsync() - { - await MqttManager.AnnounceAutoDiscoveryConfigAsync(this, Domain, true); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/AudioSensors.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/AudioSensors.cs deleted file mode 100644 index 08f1309..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/AudioSensors.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using CoreAudio; -using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes; -using HASSAgent.Models.Internal; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue -{ - public class AudioSensors : AbstractMultiValueSensor - { - private static readonly Dictionary ApplicationNames = new Dictionary(); - private bool _errorPrinted = false; - - private readonly int _updateInterval; - - public sealed override Dictionary Sensors { get; protected set; } = new Dictionary(); - - public AudioSensors(int? updateInterval = null, string name = "audio", string id = default) : base(name ?? "audio", updateInterval ?? 20, id) - { - _updateInterval = updateInterval ?? 20; - - UpdateSensorValues(); - } - - public sealed override void UpdateSensorValues() - { - try - { - // lowercase and safe name of the multivalue sensor - var parentSensorSafeName = HelperFunctions.GetSafeValue(Name); - - // get the default audio device - using (var audioDevice = Variables.AudioDeviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)) - { - // default device name - var defaultDeviceId = $"{parentSensorSafeName}_default_device"; - var defaultDeviceSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Default Device", defaultDeviceId, string.Empty, "mdi:speaker", string.Empty, Name); - defaultDeviceSensor.SetState(audioDevice.FriendlyName); - - if (!Sensors.ContainsKey(defaultDeviceId)) Sensors.Add(defaultDeviceId, defaultDeviceSensor); - else Sensors[defaultDeviceId] = defaultDeviceSensor; - - // default device state - var defaultDeviceStateId = $"{parentSensorSafeName}_default_device_state"; - var defaultDeviceStateSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Default Device State", defaultDeviceStateId, string.Empty, "mdi:speaker", string.Empty, Name); - defaultDeviceStateSensor.SetState(GetReadableState(audioDevice.State)); - - if (!Sensors.ContainsKey(defaultDeviceStateId)) Sensors.Add(defaultDeviceStateId, defaultDeviceStateSensor); - else Sensors[defaultDeviceStateId] = defaultDeviceStateSensor; - - // default device volume - var masterVolume = (int)(audioDevice.AudioEndpointVolume?.MasterVolumeLevelScalar * 100 ?? 0); - var defaultDeviceVolumeId = $"{parentSensorSafeName}_default_device_volume"; - var defaultDeviceVolumeSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Default Device Volume", defaultDeviceVolumeId, string.Empty, "mdi:speaker", string.Empty, Name); - defaultDeviceVolumeSensor.SetState(masterVolume); - - if (!Sensors.ContainsKey(defaultDeviceVolumeId)) Sensors.Add(defaultDeviceVolumeId, defaultDeviceVolumeSensor); - else Sensors[defaultDeviceVolumeId] = defaultDeviceVolumeSensor; - - // get session and volume info - var sessionInfos = GetSessions(out var peakVolume); - - // peak value sensor - var peakVolumeId = $"{parentSensorSafeName}_peak_volume"; - var peakVolumeSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Peak Volume", peakVolumeId, string.Empty, "mdi:volume-high", string.Empty, Name); - peakVolumeSensor.SetState(peakVolume.ToString(CultureInfo.CurrentCulture)); - - if (!Sensors.ContainsKey(peakVolumeId)) Sensors.Add(peakVolumeId, peakVolumeSensor); - else Sensors[peakVolumeId] = peakVolumeSensor; - - // sessions sensor - var sessions = JsonConvert.SerializeObject(sessionInfos, Formatting.Indented); - var sessionsId = $"{parentSensorSafeName}_audio_sessions"; - var sessionsSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Audio Sessions", sessionsId, string.Empty, "mdi:music-box-multiple-outline", string.Empty, Name); - sessionsSensor.SetState(sessions); - - if (!Sensors.ContainsKey(sessionsId)) Sensors.Add(sessionsId, sessionsSensor); - else Sensors[sessionsId] = sessionsSensor; - } - - // optionally reset error flag - if (_errorPrinted) _errorPrinted = false; - } - catch (Exception ex) - { - // only worry if we're active - if (Variables.ShuttingDown) return; - - // something went wrong, only print once - if (_errorPrinted) return; - _errorPrinted = true; - - Log.Fatal(ex, "[AUDIO] Error while fetching audio info: {err}", ex.Message); - } - } - - private List GetSessions(out float peakVolume) - { - var sessionInfos = new List(); - peakVolume = 0f; - - try - { - var errors = false; - - foreach (var device in Variables.AudioDeviceEnumerator.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE)) - { - // process sessions (and get peak volume) - foreach (var session in device.AudioSessionManager2?.Sessions.Where(x => x != null)) - { - try - { - // filter inactive sessions - if (session.State != AudioSessionState.AudioSessionStateActive) continue; - - // prepare sessioninfo - var sessionInfo = new AudioSessionInfo(); - - // get displayname - string displayName; - var procId = (int)session.GetProcessID; - if (procId <= 0) - { - // faulty process id, use the provided displayname - displayName = session.DisplayName; - } - else - { - if (ApplicationNames.ContainsKey(procId)) displayName = ApplicationNames[procId]; - else - { - // we don't know this app yet, get process info - using (var p = Process.GetProcessById(procId)) - { - displayName = p.ProcessName; - ApplicationNames.Add(procId, displayName); - } - } - } - - // set displayname - if (displayName.Length > 30) displayName = $"{displayName.Substring(0, 30)}.."; - sessionInfo.Application = displayName; - - // get muted state - sessionInfo.Muted = session.SimpleAudioVolume?.Mute ?? false; - - // set master volume - sessionInfo.MasterVolume = session.SimpleAudioVolume?.MasterVolume * 100 ?? 0f; - - // set peak volume - sessionInfo.PeakVolume = session.AudioMeterInformation?.MasterPeakValue * 100 ?? 0f; - - // new max? - if (sessionInfo.PeakVolume > peakVolume) peakVolume = sessionInfo.PeakVolume; - - // store the session info - sessionInfos.Add(sessionInfo); - } - catch (Exception ex) - { - if (!_errorPrinted) Log.Fatal(ex, "[AUDIO] [{app}] Exception while retrieving info: {err}", session.DisplayName, ex.Message); - errors = true; - } - finally - { - session?.Dispose(); - device?.Dispose(); - } - } - } - - // only print errors once - if (errors && !_errorPrinted) - { - _errorPrinted = true; - return sessionInfos; - } - - // optionally reset error flag - if (_errorPrinted) _errorPrinted = false; - } - catch (Exception ex) - { - // something went wrong, only print once - if (_errorPrinted) return sessionInfos; - _errorPrinted = true; - - Log.Fatal(ex, "[AUDIO] Fatal exception while getting sessions: {err}", ex.Message); - } - - return sessionInfos; - } - - /// - /// Converts the audio device's state to a better readable form - /// - /// - /// - private static string GetReadableState(DEVICE_STATE state) - { - switch (state) - { - case DEVICE_STATE.DEVICE_STATE_ACTIVE: - return "ACTIVE"; - case DEVICE_STATE.DEVICE_STATE_DISABLED: - return "DISABLED"; - case DEVICE_STATE.DEVICE_STATE_NOTPRESENT: - return "NOT PRESENT"; - case DEVICE_STATE.DEVICE_STATE_UNPLUGGED: - return "UNPLUGGED"; - case DEVICE_STATE.DEVICE_STATEMASK_ALL: - return "STATEMASK_ALL"; - default: - return "UNKNOWN"; - } - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() => null; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/BatterySensors.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/BatterySensors.cs deleted file mode 100644 index 51fde10..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/BatterySensors.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security; -using System.Windows.Forms; -using ByteSizeLib; -using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue -{ - public class BatterySensors : AbstractMultiValueSensor - { - private readonly int _updateInterval; - - public sealed override Dictionary Sensors { get; protected set; } = new Dictionary(); - - public BatterySensors(int? updateInterval = null, string name = "battery", string id = default) : base(name ?? "battery", updateInterval ?? 30, id) - { - _updateInterval = updateInterval ?? 30; - - UpdateSensorValues(); - } - - public sealed override void UpdateSensorValues() - { - // lowercase and safe name of the multivalue sensor - var parentSensorSafeName = HelperFunctions.GetSafeValue(Name); - - // fetch the latest battery state - var powerStatus = SystemInformation.PowerStatus; - - // prepare the data - var lifetimeMinutes = powerStatus.BatteryFullLifetime; - if (lifetimeMinutes != -1) lifetimeMinutes = Convert.ToInt32(Math.Round(TimeSpan.FromSeconds(lifetimeMinutes).TotalMinutes)); - - var remainingMinutes = powerStatus.BatteryLifeRemaining; - if (remainingMinutes != -1) remainingMinutes = Convert.ToInt32(Math.Round(TimeSpan.FromSeconds(remainingMinutes).TotalMinutes)); - - // charge status sensor - var chargeStatus = powerStatus.BatteryChargeStatus.ToString(); - - var chargeStatusId = $"{parentSensorSafeName}_charge_status"; - var chargeStatusSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Charge Status", chargeStatusId, string.Empty, "mdi:battery-charging", string.Empty, Name); - chargeStatusSensor.SetState(chargeStatus); - - if (!Sensors.ContainsKey(chargeStatusId)) Sensors.Add(chargeStatusId, chargeStatusSensor); - else Sensors[chargeStatusId] = chargeStatusSensor; - - // full charge lifetime sensor - var fullChargeLifetimeMinutes = lifetimeMinutes; - - var fullChargeLifetimeId = $"{parentSensorSafeName}_full_charge_lifetime"; - var fullChargeLifetimeSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Full Charge Lifetime", fullChargeLifetimeId, string.Empty, "mdi:battery-high", string.Empty, Name); - fullChargeLifetimeSensor.SetState(fullChargeLifetimeMinutes); - - if (!Sensors.ContainsKey(fullChargeLifetimeId)) Sensors.Add(fullChargeLifetimeId, fullChargeLifetimeSensor); - else Sensors[fullChargeLifetimeId] = fullChargeLifetimeSensor; - - // charge remaining percentage sensor - var chargeRemainingPercentage = Convert.ToInt32(powerStatus.BatteryLifePercent * 100); - - var chargeRemainingPercentageId = $"{parentSensorSafeName}_charge_remaining_percentage"; - var chargeRemainingPercentageSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Charge Remaining Percentage", chargeRemainingPercentageId, string.Empty, "mdi:battery-high", "%", Name); - chargeRemainingPercentageSensor.SetState(chargeRemainingPercentage); - - if (!Sensors.ContainsKey(chargeRemainingPercentageId)) Sensors.Add(chargeRemainingPercentageId, chargeRemainingPercentageSensor); - else Sensors[chargeRemainingPercentageId] = chargeRemainingPercentageSensor; - - // charge remaining minutes sensor - var chargeRemainingMinutes = remainingMinutes; - - var chargeRemainingMinutesId = $"{parentSensorSafeName}_charge_remaining"; - var chargeRemainingMinutesSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Charge Remaining", chargeRemainingMinutesId, string.Empty, "mdi:battery-high", string.Empty, Name); - chargeRemainingMinutesSensor.SetState(chargeRemainingMinutes); - - if (!Sensors.ContainsKey(chargeRemainingMinutesId)) Sensors.Add(chargeRemainingMinutesId, chargeRemainingMinutesSensor); - else Sensors[chargeRemainingMinutesId] = chargeRemainingMinutesSensor; - - // powerline status sensor - var powerlineStatus = powerStatus.PowerLineStatus.ToString(); - - var powerlineStatusId = $"{parentSensorSafeName}_powerline_status"; - var powerlineStatusSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Powerline Status", powerlineStatusId, string.Empty, "mdi:power-plug", string.Empty, Name); - powerlineStatusSensor.SetState(powerlineStatus); - - if (!Sensors.ContainsKey(powerlineStatusId)) Sensors.Add(powerlineStatusId, powerlineStatusSensor); - else Sensors[powerlineStatusId] = powerlineStatusSensor; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() => null; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeBoolSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeBoolSensor.cs deleted file mode 100644 index 43c7b5e..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeBoolSensor.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Globalization; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes -{ - public class DataTypeBoolSensor : AbstractSingleValueSensor - { - private readonly string _deviceClass; - private readonly string _icon; - - private bool _value = false; - - public DataTypeBoolSensor(int? updateInterval, string name, string id, string deviceClass, string icon, string multiValueSensorName) : base(name, updateInterval ?? 30, id) - { - TopicName = multiValueSensorName; - - _deviceClass = deviceClass; - _icon = icon; - - ObjectId = id; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - if (AutoDiscoveryConfigModel != null) return AutoDiscoveryConfigModel; - - var model = new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{TopicName}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }; - - if (!string.IsNullOrWhiteSpace(_deviceClass)) model.Device_class = _deviceClass; - if (!string.IsNullOrWhiteSpace(_icon)) model.Icon = _icon; - - return SetAutoDiscoveryConfigModel(model); - } - - public void SetState(bool value) => _value = value; - - public override string GetState() => _value.ToString(CultureInfo.CurrentCulture); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeDoubleSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeDoubleSensor.cs deleted file mode 100644 index 241dc13..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeDoubleSensor.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Globalization; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes -{ - public class DataTypeDoubleSensor : AbstractSingleValueSensor - { - private readonly string _deviceClass; - private readonly string _unitOfMeasurement; - private readonly string _icon; - - private double _value = 0d; - - public DataTypeDoubleSensor(int? updateInterval, string name, string id, string deviceClass, string icon, string unitOfMeasurement, string multiValueSensorName) : base(name, updateInterval ?? 30, id) - { - TopicName = multiValueSensorName; - - _deviceClass = deviceClass; - _unitOfMeasurement = unitOfMeasurement; - _icon = icon; - - ObjectId = id; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - if (AutoDiscoveryConfigModel != null) return AutoDiscoveryConfigModel; - - var model = new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{TopicName}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }; - - if (!string.IsNullOrWhiteSpace(_deviceClass)) model.Device_class = _deviceClass; - if (!string.IsNullOrWhiteSpace(_unitOfMeasurement)) model.Unit_of_measurement = _unitOfMeasurement; - if (!string.IsNullOrWhiteSpace(_icon)) model.Icon = _icon; - - return SetAutoDiscoveryConfigModel(model); - } - - public void SetState(double value) => _value = value; - - public override string GetState() => _value.ToString(CultureInfo.CurrentCulture); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeIntSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeIntSensor.cs deleted file mode 100644 index 4b153ce..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeIntSensor.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes -{ - public class DataTypeIntSensor : AbstractSingleValueSensor - { - private readonly string _deviceClass; - private readonly string _unitOfMeasurement; - private readonly string _icon; - - private int _value = 0; - - public DataTypeIntSensor(int? updateInterval, string name, string id, string deviceClass, string icon, string unitOfMeasurement, string multiValueSensorName) : base(name, updateInterval ?? 30, id) - { - TopicName = multiValueSensorName; - - _deviceClass = deviceClass; - _unitOfMeasurement = unitOfMeasurement; - _icon = icon; - - ObjectId = id; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - if (AutoDiscoveryConfigModel != null) return AutoDiscoveryConfigModel; - - var model = new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{TopicName}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }; - - if (!string.IsNullOrWhiteSpace(_deviceClass)) model.Device_class = _deviceClass; - if (!string.IsNullOrWhiteSpace(_unitOfMeasurement)) model.Unit_of_measurement = _unitOfMeasurement; - if (!string.IsNullOrWhiteSpace(_icon)) model.Icon = _icon; - - return SetAutoDiscoveryConfigModel(model); - } - - public void SetState(int value) => _value = value; - - public override string GetState() => _value.ToString(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeStringSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeStringSensor.cs deleted file mode 100644 index d1a67bf..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DataTypes/DataTypeStringSensor.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes -{ - public class DataTypeStringSensor : AbstractSingleValueSensor - { - private readonly string _deviceClass; - private readonly string _unitOfMeasurement; - private readonly string _icon; - - private string _value = string.Empty; - - public DataTypeStringSensor(int? updateInterval, string name, string id, string deviceClass, string icon, string unitOfMeasurement, string multiValueSensorName) : base(name, updateInterval ?? 30, id) - { - TopicName = multiValueSensorName; - - _deviceClass = deviceClass; - _unitOfMeasurement = unitOfMeasurement; - _icon = icon; - - ObjectId = id; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - if (AutoDiscoveryConfigModel != null) return AutoDiscoveryConfigModel; - - var model = new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{TopicName}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }; - - if (!string.IsNullOrWhiteSpace(_deviceClass)) model.Device_class = _deviceClass; - if (!string.IsNullOrWhiteSpace(_unitOfMeasurement)) model.Unit_of_measurement = _unitOfMeasurement; - if (!string.IsNullOrWhiteSpace(_icon)) model.Icon = _icon; - - return SetAutoDiscoveryConfigModel(model); - } - - public void SetState(string value) => _value = value; - - public override string GetState() => _value; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DisplaySensors.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DisplaySensors.cs deleted file mode 100644 index f029380..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/DisplaySensors.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security; -using System.Windows.Forms; -using ByteSizeLib; -using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue -{ - public class DisplaySensors : AbstractMultiValueSensor - { - private readonly int _updateInterval; - - public sealed override Dictionary Sensors { get; protected set; } = new Dictionary(); - - public DisplaySensors(int? updateInterval = null, string name = "display", string id = default) : base(name ?? "display", updateInterval ?? 30, id) - { - _updateInterval = updateInterval ?? 30; - - UpdateSensorValues(); - } - - public sealed override void UpdateSensorValues() - { - // lowercase and safe name of the multivalue sensor - var parentSensorSafeName = HelperFunctions.GetSafeValue(Name); - - // fetch the latest battery state - var displayInfo = Screen.AllScreens; - - // prepare the data - var primaryDisplayStr = string.Empty; - var primaryDisplay = displayInfo.FirstOrDefault(x => x.Primary); - if (primaryDisplay != null) primaryDisplayStr = primaryDisplay.DeviceName; - - // display count sensor - var displayCount = displayInfo.Length; - - var displayCountId = $"{parentSensorSafeName}_display_count"; - var displayCountSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Display Count", displayCountId, string.Empty, "mdi:monitor", string.Empty, Name); - displayCountSensor.SetState(displayCount); - - if (!Sensors.ContainsKey(displayCountId)) Sensors.Add(displayCountId, displayCountSensor); - else Sensors[displayCountId] = displayCountSensor; - - // nothing to do if there aren't any displays - if (displayCount == 0) return; - - // primary display sensor - var primaryDisplayId = $"{parentSensorSafeName}_primary_display"; - var primaryDisplaySensor = new DataTypeStringSensor(_updateInterval, $"{Name} Primay Display", primaryDisplayId, string.Empty, "mdi:monitor", string.Empty, Name); - primaryDisplaySensor.SetState(primaryDisplayStr); - - if (!Sensors.ContainsKey(primaryDisplayId)) Sensors.Add(primaryDisplayId, primaryDisplaySensor); - else Sensors[primaryDisplayId] = primaryDisplaySensor; - - // process all monitors - foreach (var display in displayInfo) - { - // id - var id = HelperFunctions.GetSafeValue(display.DeviceName); - if (string.IsNullOrWhiteSpace(id)) continue; - - // name - var name = display.DeviceName; - - var nameId = $"{parentSensorSafeName}_{id}_name"; - var nameSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} Name", nameId, string.Empty, "mdi:monitor", string.Empty, Name); - nameSensor.SetState(name); - - if (!Sensors.ContainsKey(nameId)) Sensors.Add(nameId, nameSensor); - else Sensors[nameId] = nameSensor; - - // resolution - var resolution = $"{display.Bounds.Width}x{display.Bounds.Height}"; - - var resolutionId = $"{parentSensorSafeName}_{id}_resolution"; - var resolutionSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} Resolution", resolutionId, string.Empty, "mdi:monitor", string.Empty, Name); - resolutionSensor.SetState(resolution); - - if (!Sensors.ContainsKey(resolutionId)) Sensors.Add(resolutionId, resolutionSensor); - else Sensors[resolutionId] = resolutionSensor; - - // bit - var bit = display.BitsPerPixel; - - var bitId = $"{parentSensorSafeName}_{id}_bit"; - var bitSensor = new DataTypeIntSensor(_updateInterval, $"{Name} {name} Bits Per Pixel", bitId, string.Empty, "mdi:monitor", string.Empty, Name); - bitSensor.SetState(bit); - - if (!Sensors.ContainsKey(bitId)) Sensors.Add(bitId, bitSensor); - else Sensors[bitId] = bitSensor; - } - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() => null; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/NetworkSensors.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/NetworkSensors.cs deleted file mode 100644 index 85b8a1a..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/NetworkSensors.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.NetworkInformation; -using ByteSizeLib; -using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue -{ - public class NetworkSensors : AbstractMultiValueSensor - { - private readonly int _updateInterval; - - public sealed override Dictionary Sensors { get; protected set; } = new Dictionary(); - - public NetworkSensors(int? updateInterval = null, string name = "network", string id = default) : base(name ?? "network", updateInterval ?? 30, id) - { - _updateInterval = updateInterval ?? 30; - - UpdateSensorValues(); - } - - public sealed override void UpdateSensorValues() - { - // lowercase and safe name of the multivalue sensor - var parentSensorSafeName = HelperFunctions.GetSafeValue(Name); - - // get nic info - var nicCount = 0; - var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); - - foreach (var nic in networkInterfaces) - { - try - { - if (nic == null) continue; - - // id - var id = nic.Id.Replace("{", "").Replace("}", "").Replace("-", "").ToLower(); - if (string.IsNullOrWhiteSpace(id)) continue; - - // name - var name = nic.Name; - var nameId = $"{parentSensorSafeName}_{id}_name"; - - var nameSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} Name", nameId, string.Empty, "mdi:lan", string.Empty, Name); - nameSensor.SetState(name); - - if (!Sensors.ContainsKey(nameId)) Sensors.Add(nameId, nameSensor); - else Sensors[nameId] = nameSensor; - - // interfacetype - var interfaceType = nic.NetworkInterfaceType.ToString(); - var interfaceTypeId = $"{parentSensorSafeName}_{id}_interface_type"; - - var interfaceTypeSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} Interface Type", interfaceTypeId, string.Empty, "mdi:lan", string.Empty, Name); - interfaceTypeSensor.SetState(interfaceType); - - if (!Sensors.ContainsKey(interfaceTypeId)) Sensors.Add(interfaceTypeId, interfaceTypeSensor); - else Sensors[interfaceTypeId] = interfaceTypeSensor; - - // speed - var speed = nic.Speed; - var speedId = $"{parentSensorSafeName}_{id}_speed"; - - var speedIdSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Speed", speedId, string.Empty, "mdi:lan", string.Empty, Name); - speedIdSensor.SetState(speed); - - if (!Sensors.ContainsKey(speedId)) Sensors.Add(speedId, speedIdSensor); - else Sensors[speedId] = speedIdSensor; - - // operational status - var operationalStatus = nic.OperationalStatus.ToString(); - var operationalStatusId = $"{parentSensorSafeName}_{id}_operational_status"; - - var operationalStatusSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} Operational Status", operationalStatusId, string.Empty, "mdi:lan", string.Empty, Name); - operationalStatusSensor.SetState(operationalStatus); - - if (!Sensors.ContainsKey(operationalStatusId)) Sensors.Add(operationalStatusId, operationalStatusSensor); - else Sensors[operationalStatusId] = operationalStatusSensor; - - // get interface stats - var interfaceStats = nic.GetIPv4Statistics(); - - // data received - var dataReceivedMb = Math.Round(ByteSize.FromBytes(interfaceStats.BytesReceived).MegaBytes); - var dataReceivedMbId = $"{parentSensorSafeName}_{id}_data_received"; - - var dataReceivedMbSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Received", dataReceivedMbId, string.Empty, "mdi:lan", "MB", Name); - dataReceivedMbSensor.SetState(dataReceivedMb); - - if (!Sensors.ContainsKey(dataReceivedMbId)) Sensors.Add(dataReceivedMbId, dataReceivedMbSensor); - else Sensors[dataReceivedMbId] = dataReceivedMbSensor; - - // data sent - var dataSentMb = Math.Round(ByteSize.FromBytes(interfaceStats.BytesSent).MegaBytes); - var dataSentMbId = $"{parentSensorSafeName}_{id}_data_sent"; - - var dataSentMbSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Sent", dataSentMbId, string.Empty, "mdi:lan", "MB", Name); - dataSentMbSensor.SetState(dataSentMb); - - if (!Sensors.ContainsKey(dataSentMbId)) Sensors.Add(dataSentMbId, dataSentMbSensor); - else Sensors[dataSentMbId] = dataSentMbSensor; - - // incoming discarded packets - var incomingPacketsDiscarded = interfaceStats.IncomingPacketsDiscarded; - var incomingPacketsDiscardedId = $"{parentSensorSafeName}_{id}_incoming_discarded_packets"; - - var incomingPacketsDiscardedSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Incoming Packets Discarded", incomingPacketsDiscardedId, string.Empty, "mdi:lan", string.Empty, Name); - incomingPacketsDiscardedSensor.SetState(incomingPacketsDiscarded); - - if (!Sensors.ContainsKey(incomingPacketsDiscardedId)) Sensors.Add(incomingPacketsDiscardedId, incomingPacketsDiscardedSensor); - else Sensors[incomingPacketsDiscardedId] = incomingPacketsDiscardedSensor; - - // incoming discarded packets - var incomingPacketsWithErrors = interfaceStats.IncomingPacketsWithErrors; - var incomingPacketsWithErrorsId = $"{parentSensorSafeName}_{id}_incoming_error_packets"; - - var incomingPacketsWithErrorsSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Incoming Packets With Errors", incomingPacketsWithErrorsId, string.Empty, "mdi:lan", string.Empty, Name); - incomingPacketsWithErrorsSensor.SetState(incomingPacketsWithErrors); - - if (!Sensors.ContainsKey(incomingPacketsWithErrorsId)) Sensors.Add(incomingPacketsWithErrorsId, incomingPacketsWithErrorsSensor); - else Sensors[incomingPacketsWithErrorsId] = incomingPacketsWithErrorsSensor; - - // incoming discarded packets - var incomingPacketsWithUnknownProtocol = interfaceStats.IncomingUnknownProtocolPackets; - var incomingPacketsWithUnknownProtocolId = $"{parentSensorSafeName}_{id}_incoming_unknown_protocol_packets"; - - var incomingPacketsWithUnknownProtocolSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Incoming Unknown Protocol Packets", incomingPacketsWithUnknownProtocolId, string.Empty, "mdi:lan", string.Empty, Name); - incomingPacketsWithUnknownProtocolSensor.SetState(incomingPacketsWithUnknownProtocol); - - if (!Sensors.ContainsKey(incomingPacketsWithUnknownProtocolId)) Sensors.Add(incomingPacketsWithUnknownProtocolId, incomingPacketsWithUnknownProtocolSensor); - else Sensors[incomingPacketsWithUnknownProtocolId] = incomingPacketsWithUnknownProtocolSensor; - - // outgoing discarded packets - var outgoingPacketsDiscarded = interfaceStats.OutgoingPacketsDiscarded; - var outgoingPacketsDiscardedId = $"{parentSensorSafeName}_{id}_outgoing_discarded_packets"; - - var outgoingPacketsDiscardedSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Outgoing Packets Discarded", outgoingPacketsDiscardedId, string.Empty, "mdi:lan", string.Empty, Name); - outgoingPacketsDiscardedSensor.SetState(outgoingPacketsDiscarded); - - if (!Sensors.ContainsKey(outgoingPacketsDiscardedId)) Sensors.Add(outgoingPacketsDiscardedId, outgoingPacketsDiscardedSensor); - else Sensors[outgoingPacketsDiscardedId] = outgoingPacketsDiscardedSensor; - - // outgoing discarded packets - var outgoingPacketsWithErrors = interfaceStats.OutgoingPacketsWithErrors; - var outgoingPacketsWithErrorsId = $"{parentSensorSafeName}_{id}_outgoing_error_packets"; - - var outgoingPacketsWithErrorsSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {name} Outgoing Packets With Errors", outgoingPacketsWithErrorsId, string.Empty, "mdi:lan", string.Empty, Name); - outgoingPacketsWithErrorsSensor.SetState(outgoingPacketsWithErrors); - - if (!Sensors.ContainsKey(outgoingPacketsWithErrorsId)) Sensors.Add(outgoingPacketsWithErrorsId, outgoingPacketsWithErrorsSensor); - else Sensors[outgoingPacketsWithErrorsId] = outgoingPacketsWithErrorsSensor; - - // get nic properties - var nicProperties = nic.GetIPProperties(); - - // ip's and mac addresses - var ips = new List(); - var macs = new List(); - foreach (var unicast in nicProperties.UnicastAddresses) - { - var ip = unicast.Address.ToString(); - if (!string.IsNullOrEmpty(ip) && !ips.Contains(ip)) ips.Add(ip); - - var mac = nic.GetPhysicalAddress().ToString(); - if (!string.IsNullOrEmpty(mac) && !macs.Contains(mac)) macs.Add(mac); - } - - var ipList = JsonConvert.SerializeObject(ips); - var ipListId = $"{parentSensorSafeName}_{id}_ip_addresses"; - - var ipListSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} IP Addresses", ipListId, string.Empty, "mdi:lan", string.Empty, Name); - ipListSensor.SetState(ipList); - - if (!Sensors.ContainsKey(ipListId)) Sensors.Add(ipListId, ipListSensor); - else Sensors[ipListId] = ipListSensor; - - var macList = JsonConvert.SerializeObject(macs); - var macListId = $"{parentSensorSafeName}_{id}_mac_addresses"; - - var macListSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} MAC Addresses", macListId, string.Empty, "mdi:lan", string.Empty, Name); - macListSensor.SetState(macList); - - if (!Sensors.ContainsKey(macListId)) Sensors.Add(macListId, macListSensor); - else Sensors[macListId] = macListSensor; - - // gateways - var gateways = new List(); - foreach (var gateway in nicProperties.GatewayAddresses) - { - var gatewayAddress = gateway.Address.ToString(); - if (!string.IsNullOrEmpty(gatewayAddress) && !gateways.Contains(gatewayAddress)) gateways.Add(gatewayAddress); - } - - var gatewayList = JsonConvert.SerializeObject(gateways); - var gatewayListId = $"{parentSensorSafeName}_{id}_gateway_addresses"; - - var gatewayListSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} Gateway Addresses", gatewayListId, string.Empty, "mdi:lan", string.Empty, Name); - gatewayListSensor.SetState(gatewayList); - - if (!Sensors.ContainsKey(gatewayListId)) Sensors.Add(gatewayListId, gatewayListSensor); - else Sensors[gatewayListId] = gatewayListSensor; - - // dhcp enabled - var dhcpEnabled = nicProperties.GetIPv4Properties().IsDhcpEnabled ? "TRUE" : "FALSE"; - var dhcpEnabledId = $"{parentSensorSafeName}_{id}_dhcp_enabled"; - - var dhcpEnabledSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} DHCP Enabled", dhcpEnabledId, string.Empty, "mdi:lan", string.Empty, Name); - dhcpEnabledSensor.SetState(dhcpEnabled); - - if (!Sensors.ContainsKey(dhcpEnabledId)) Sensors.Add(dhcpEnabledId, dhcpEnabledSensor); - else Sensors[dhcpEnabledId] = dhcpEnabledSensor; - - // dhcp - var dhcps = new List(); - foreach (var dhcp in nicProperties.DhcpServerAddresses) - { - var dhcpAddress = dhcp.ToString(); - if (!string.IsNullOrEmpty(dhcpAddress) && !dhcps.Contains(dhcpAddress)) dhcps.Add(dhcpAddress); - } - - var dhcpList = JsonConvert.SerializeObject(dhcps); - var dhcpListId = $"{parentSensorSafeName}_{id}_dhcp_addresses"; - - var dhcpListSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} DHCP Addresses", dhcpListId, string.Empty, "mdi:lan", string.Empty, Name); - dhcpListSensor.SetState(dhcpList); - - if (!Sensors.ContainsKey(dhcpListId)) Sensors.Add(dhcpListId, dhcpListSensor); - else Sensors[dhcpListId] = dhcpListSensor; - - // dns enabled - var dnsEnabled = nicProperties.IsDnsEnabled ? "TRUE" : "FALSE"; - var dnsEnabledId = $"{parentSensorSafeName}_{id}_dns_enabled"; - - var dnsEnabledSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} DNS Enabled", dnsEnabledId, string.Empty, "mdi:lan", string.Empty, Name); - dnsEnabledSensor.SetState(dnsEnabled); - - if (!Sensors.ContainsKey(dnsEnabledId)) Sensors.Add(dnsEnabledId, dnsEnabledSensor); - else Sensors[dnsEnabledId] = dnsEnabledSensor; - - // dns suffix - var dnsSuffix = nicProperties.DnsSuffix; - var dnsSuffixId = $"{parentSensorSafeName}_{id}_dns_suffix"; - - var dnsSuffixSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} DNS Suffix", dnsSuffixId, string.Empty, "mdi:lan", string.Empty, Name); - dnsSuffixSensor.SetState(dnsSuffix); - - if (!Sensors.ContainsKey(dnsSuffixId)) Sensors.Add(dnsSuffixId, dnsSuffixSensor); - else Sensors[dnsSuffixId] = dnsSuffixSensor; - - // dns - var dnses = new List(); - foreach (var dns in nicProperties.DnsAddresses) - { - var dnsAddress = dns.ToString(); - if (!string.IsNullOrEmpty(dnsAddress) && !dnses.Contains(dnsAddress)) dnses.Add(dnsAddress); - } - - var dnsList = JsonConvert.SerializeObject(dnses); - var dnsListId = $"{parentSensorSafeName}_{id}_dns_addresses"; - - var dnsListSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {name} DNS Addresses", dnsListId, string.Empty, "mdi:lan", string.Empty, Name); - dnsListSensor.SetState(dnsList); - - if (!Sensors.ContainsKey(dnsListId)) Sensors.Add(dnsListId, dnsListSensor); - else Sensors[dnsListId] = dnsListSensor; - - // nic count - nicCount++; - } - catch (Exception ex) - { - Log.Fatal(ex, "[NETWORK] Error querying NIC: {msg}", ex.Message); - } - } - - // nic count - var nicCountId = $"{parentSensorSafeName}_total_network_card_count"; - var nicCountSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Network Card Count", nicCountId, string.Empty, "mdi:harddisk", string.Empty, Name); - nicCountSensor.SetState(nicCount); - - if (!Sensors.ContainsKey(nicCountId)) Sensors.Add(nicCountId, nicCountSensor); - else Sensors[nicCountId] = nicCountSensor; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() => null; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/StorageSensors.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/StorageSensors.cs deleted file mode 100644 index 0a8c8a0..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/StorageSensors.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security; -using ByteSizeLib; -using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue -{ - public class StorageSensors : AbstractMultiValueSensor - { - private readonly int _updateInterval; - - public sealed override Dictionary Sensors { get; protected set; } = new Dictionary(); - - public StorageSensors(int? updateInterval = null, string name = "storage", string id = default) : base(name ?? "storage", updateInterval ?? 30, id) - { - _updateInterval = updateInterval ?? 30; - - UpdateSensorValues(); - } - - public sealed override void UpdateSensorValues() - { - var driveCount = 0; - - // lowercase and safe name of the multivalue sensor - var parentSensorSafeName = HelperFunctions.GetSafeValue(Name); - - foreach (var drive in DriveInfo.GetDrives()) - { - try - { - if (drive == null || !drive.IsReady || drive.DriveType != DriveType.Fixed) continue; - if (string.IsNullOrWhiteSpace(drive.Name)) continue; - - // name (letter) - var driveName = $"{drive.Name.Substring(0, 1).ToUpper()}"; - var driveNameLower = driveName.ToLower(); - - // label - var driveLabel = string.IsNullOrEmpty(drive.VolumeLabel) ? "-" : drive.VolumeLabel; - var driveLabelId = $"{parentSensorSafeName}_{driveNameLower}_label"; - - var labelSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {driveName} Label", driveLabelId, string.Empty, "mdi:harddisk", string.Empty, Name); - labelSensor.SetState(driveLabel); - - if (!Sensors.ContainsKey(driveLabelId)) Sensors.Add(driveLabelId, labelSensor); - else Sensors[driveLabelId] = labelSensor; - - // total size - var totalSizeMb = Math.Round(ByteSize.FromBytes(drive.TotalSize).MegaBytes); - var totalSizeId = $"{parentSensorSafeName}_{driveNameLower}_total_size"; - - var totalSizeSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {driveName} Total Size", totalSizeId, string.Empty, "mdi:harddisk", "MB", Name); - totalSizeSensor.SetState(totalSizeMb); - - if (!Sensors.ContainsKey(totalSizeId)) Sensors.Add(totalSizeId, totalSizeSensor); - else Sensors[totalSizeId] = totalSizeSensor; - - // available space - var availableSpaceMb = Math.Round(ByteSize.FromBytes(drive.AvailableFreeSpace).MegaBytes); - var availableSpaceId = $"{parentSensorSafeName}_{driveNameLower}_available_space"; - - var availableSpaceSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {driveName} Available Space", availableSpaceId, string.Empty, "mdi:harddisk", "MB", Name); - availableSpaceSensor.SetState(availableSpaceMb); - - if (!Sensors.ContainsKey(availableSpaceId)) Sensors.Add(availableSpaceId, availableSpaceSensor); - else Sensors[availableSpaceId] = availableSpaceSensor; - - // used space - var usedSpaceMb = totalSizeMb - availableSpaceMb; - var usedSpaceId = $"{parentSensorSafeName}_{driveNameLower}_used_space"; - - var usedSpaceSensor = new DataTypeDoubleSensor(_updateInterval, $"{Name} {driveName} Used Space", usedSpaceId, string.Empty, "mdi:harddisk", "MB", Name); - usedSpaceSensor.SetState(usedSpaceMb); - - if (!Sensors.ContainsKey(usedSpaceId)) Sensors.Add(usedSpaceId, usedSpaceSensor); - else Sensors[usedSpaceId] = usedSpaceSensor; - - // file system - var fileSystem = drive.DriveFormat; - var fileSystemId = $"{parentSensorSafeName}_{driveNameLower}_filesystem"; - - var fileSystemSensor = new DataTypeStringSensor(_updateInterval, $"{Name} {driveName} File System", fileSystemId, string.Empty, "mdi:harddisk", string.Empty, Name); - fileSystemSensor.SetState(fileSystem); - - if (!Sensors.ContainsKey(fileSystemId)) Sensors.Add(fileSystemId, fileSystemSensor); - else Sensors[fileSystemId] = fileSystemSensor; - - // drive count - driveCount++; - } - catch (Exception ex) - { - switch (ex) - { - case UnauthorizedAccessException _: - case SecurityException _: - Log.Fatal(ex, "[STORAGE] Disk access denied: {msg}", ex.Message); - continue; - case DriveNotFoundException _: - Log.Fatal(ex, "[STORAGE] Disk not found: {msg}", ex.Message); - continue; - case IOException _: - Log.Fatal(ex, "[STORAGE] Disk IO error: {msg}", ex.Message); - continue; - } - - Log.Fatal(ex, "[STORAGE] Error querying disk: {msg}", ex.Message); - } - } - - // drive count - var driveCountId = $"{parentSensorSafeName}_total_disk_count"; - var driveCountSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Total Disk Count", driveCountId, string.Empty, "mdi:harddisk", string.Empty, Name); - driveCountSensor.SetState(driveCount); - - if (!Sensors.ContainsKey(driveCountId)) Sensors.Add(driveCountId, driveCountSensor); - else Sensors[driveCountId] = driveCountSensor; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() => null; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/WindowsUpdatesSensors.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/WindowsUpdatesSensors.cs deleted file mode 100644 index f388f47..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/MultiValue/WindowsUpdatesSensors.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security; -using ByteSizeLib; -using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue.DataTypes; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue -{ - public class WindowsUpdatesSensors : AbstractMultiValueSensor - { - private readonly int _updateInterval; - - public sealed override Dictionary Sensors { get; protected set; } = new Dictionary(); - - public WindowsUpdatesSensors(int? updateInterval = null, string name = "windowsupdates", string id = default) : base(name ?? "windowsupdates", updateInterval ?? 900, id) - { - _updateInterval = updateInterval ?? 900; - - UpdateSensorValues(); - } - - public sealed override void UpdateSensorValues() - { - // lowercase and safe name of the multivalue sensor - var parentSensorSafeName = HelperFunctions.GetSafeValue(Name); - - // fetch the latest updates - var (driverUpdates, softwareUpdates) = WindowsUpdatesManager.GetAvailableUpdates(); - - // driver update count - var driverUpdateCount = driverUpdates.Count; - - var driverUpdateCountId = $"{parentSensorSafeName}_driver_updates_pending"; - var driverUpdateCountSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Driver Updates Pending", driverUpdateCountId, string.Empty, "mdi:microsoft-windows", string.Empty, Name); - driverUpdateCountSensor.SetState(driverUpdateCount); - - if (!Sensors.ContainsKey(driverUpdateCountId)) Sensors.Add(driverUpdateCountId, driverUpdateCountSensor); - else Sensors[driverUpdateCountId] = driverUpdateCountSensor; - - // software update count - var softwareUpdateCount = softwareUpdates.Count; - - var softwareUpdateCountId = $"{parentSensorSafeName}_software_updates_pending"; - var softwareUpdateCountSensor = new DataTypeIntSensor(_updateInterval, $"{Name} Software Updates Pending", softwareUpdateCountId, string.Empty, "mdi:microsoft-windows", string.Empty, Name); - softwareUpdateCountSensor.SetState(softwareUpdateCount); - - if (!Sensors.ContainsKey(softwareUpdateCountId)) Sensors.Add(softwareUpdateCountId, softwareUpdateCountSensor); - else Sensors[softwareUpdateCountId] = softwareUpdateCountSensor; - - // driver updates array - // todo - //var driverUpdatesStr = JsonConvert.SerializeObject(driverUpdates, Formatting.Indented); - - //var driverUpdatesId = $"{parentSensorSafeName}_driver_updates"; - - //var driverUpdatesSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Available Driver Updates", driverUpdatesId, string.Empty, "mdi:microsoft-windows", string.Empty, Name); - //driverUpdatesSensor.SetState(driverUpdatesStr); - - //if (!Sensors.ContainsKey(driverUpdatesId)) Sensors.Add(driverUpdatesId, driverUpdatesSensor); - //else Sensors[driverUpdatesId] = driverUpdatesSensor; - - // software updates array - // todo - //var softwareUpdatesStr = JsonConvert.SerializeObject(softwareUpdates, Formatting.Indented); - - //var softwareUpdatesId = $"{parentSensorSafeName}_software_updates"; - - //var softwareUpdatesSensor = new DataTypeStringSensor(_updateInterval, $"{Name} Available Software Updates", softwareUpdatesId, string.Empty, "mdi:microsoft-windows", string.Empty, Name); - //softwareUpdatesSensor.SetState(softwareUpdatesStr); - - //if (!Sensors.ContainsKey(softwareUpdatesId)) Sensors.Add(softwareUpdatesId, softwareUpdatesSensor); - //else Sensors[softwareUpdatesId] = softwareUpdatesSensor; - - // all done! - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() => null; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ActiveWindowSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ActiveWindowSensor.cs deleted file mode 100644 index 78b4134..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ActiveWindowSensor.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class ActiveWindowSensor : AbstractSingleValueSensor - { - public ActiveWindowSensor(int? updateInterval = null, string name = "activewindow", string id = default) : base(name ?? "activewindow", updateInterval ?? 15, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:window-maximize", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - return GetActiveWindowTitle(); - } - - [DllImport("user32.dll")] - private static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll")] - private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); - - private static string GetActiveWindowTitle() - { - const int nChars = 256; - var buff = new StringBuilder(nChars); - var handle = GetForegroundWindow(); - - return GetWindowText(handle, buff, nChars) > 0 ? buff.ToString() : null; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/CurrentVolumeSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/CurrentVolumeSensor.cs deleted file mode 100644 index 1601ecf..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/CurrentVolumeSensor.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Globalization; -using CoreAudio; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class CurrentVolumeSensor : AbstractSingleValueSensor - { - public CurrentVolumeSensor(int? updateInterval = null, string name = "currentvolume", string id = default) : base(name ?? "currentvolume", updateInterval ?? 15, id) - { - // - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:volume-medium", - Unit_of_measurement = "%", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - using (var audioDevice = Variables.AudioDeviceEnumerator?.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia)) - { - // check for null & mute - if (audioDevice?.AudioEndpointVolume == null) return "0"; - if (audioDevice.AudioEndpointVolume.Mute) return "0"; - - // return as percentage - return Math.Round(audioDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100, 0).ToString(CultureInfo.InvariantCulture); - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/DummySensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/DummySensor.cs deleted file mode 100644 index b542607..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/DummySensor.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class DummySensor : AbstractSingleValueSensor - { - public DummySensor(int? updateInterval = null, string name = "dummy", string id = default) : base(name ?? "dummy", updateInterval ?? 5, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - return Variables.Rnd.Next(0, 100).ToString(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuLoadSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuLoadSensor.cs deleted file mode 100644 index 3046bf7..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuLoadSensor.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Globalization; -using System.Linq; -using LibreHardwareMonitor.Hardware; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class GpuLoadSensor : AbstractSingleValueSensor - { - private readonly IHardware _gpu; - - public GpuLoadSensor(int? updateInterval = null, string name = "gpuload", string id = default) : base(name ?? "gpuload", updateInterval ?? 30, id) - { - var computer = new Computer - { - IsCpuEnabled = false, - IsGpuEnabled = true, - IsMemoryEnabled = false, - IsMotherboardEnabled = false, - IsControllerEnabled = false, - IsNetworkEnabled = false, - IsStorageEnabled = false, - }; - - computer.Open(); - _gpu = computer.Hardware.FirstOrDefault(h => h.HardwareType == HardwareType.GpuAmd || h.HardwareType == HardwareType.GpuNvidia); - - computer.Close(); - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Unit_of_measurement = "%", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - if (_gpu == null) return "NotSupported"; - - _gpu.Update(); - var sensor = _gpu.Sensors.FirstOrDefault(s => s.SensorType == SensorType.Load); - - if (sensor == null) return "NotSupported"; - - return sensor.Value.HasValue ? sensor.Value.Value.ToString("#.##", CultureInfo.InvariantCulture) : "Unknown"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuTemperatureSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuTemperatureSensor.cs deleted file mode 100644 index 8ada21f..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/GpuTemperatureSensor.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Globalization; -using System.Linq; -using LibreHardwareMonitor.Hardware; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class GpuTemperatureSensor : AbstractSingleValueSensor - { - private readonly IHardware _gpu; - - public GpuTemperatureSensor(int? updateInterval = null, string name = "gputemperature", string id = default) : base(name ?? "gputemperature", updateInterval ?? 30, id) - { - var computer = new Computer - { - IsCpuEnabled = false, - IsGpuEnabled = true, - IsMemoryEnabled = false, - IsMotherboardEnabled = false, - IsControllerEnabled = false, - IsNetworkEnabled = false, - IsStorageEnabled = false, - }; - - computer.Open(); - _gpu = computer.Hardware.FirstOrDefault(h => h.HardwareType == HardwareType.GpuAmd || h.HardwareType == HardwareType.GpuNvidia); - - computer.Close(); - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Device_class = "temperature", - Unit_of_measurement = "°C", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - if (_gpu == null) return "NotSupported"; - - _gpu.Update(); - var sensor = _gpu.Sensors.FirstOrDefault(s => s.SensorType == SensorType.Temperature); - - if (sensor == null) return "NotSupported"; - - return sensor.Value.HasValue ? sensor.Value.Value.ToString("#.##", CultureInfo.InvariantCulture) : "Unknown"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastActiveSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastActiveSensor.cs deleted file mode 100644 index 597bf89..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastActiveSensor.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using HASSAgent.Functions; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class LastActiveSensor : AbstractSingleValueSensor - { - private DateTime _lastActive = DateTime.MinValue; - - public LastActiveSensor(int? updateInterval = 10, string name = "lastactive", string id = default) : base(name ?? "lastactive", updateInterval ?? 10, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:clock-time-three-outline", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability", - Device_class = "timestamp" - }); - } - - public override string GetState() - { - // changed to min. 1 sec difference - // source: https://github.com/sleevezipper/hass-workstation-service/pull/156 - var lastInput = GetLastInputTime(); - if ((_lastActive - lastInput).Duration().TotalSeconds > 1) _lastActive = lastInput; - - return _lastActive.ToTimeZoneString(); - } - - private static DateTime GetLastInputTime() - { - var lastInputInfo = new LASTINPUTINFO(); - lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo); - lastInputInfo.dwTime = 0; - - var envTicks = Environment.TickCount; - - if (!GetLastInputInfo(ref lastInputInfo)) return DateTime.Now; - var lastInputTick = Convert.ToInt32(lastInputInfo.dwTime); - - var idleTime = envTicks - lastInputTick; - return idleTime > 0 ? DateTime.Now - TimeSpan.FromMilliseconds(idleTime) : DateTime.Now; - } - - [DllImport("User32.dll")] - private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); - - [StructLayout(LayoutKind.Sequential)] - // ReSharper disable once InconsistentNaming - private struct LASTINPUTINFO - { - private static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO)); - - [MarshalAs(UnmanagedType.U4)] - public int cbSize; - [MarshalAs(UnmanagedType.U4)] - public uint dwTime; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastBootSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastBootSensor.cs deleted file mode 100644 index 14ff7de..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastBootSensor.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using HASSAgent.Functions; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class LastBootSensor : AbstractSingleValueSensor - { - public LastBootSensor(int? updateInterval = 10, string name = "lastboot", string id = default) : base(name ?? "lastboot", updateInterval ?? 10, id) {} - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:clock-time-three-outline", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability", - Device_class = "timestamp" - }); - } - - public override string GetState() => (DateTime.Now - TimeSpan.FromMilliseconds(GetTickCount64())).ToTimeZoneString(); - - [DllImport("kernel32")] - private static extern ulong GetTickCount64(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastSystemStateChangeSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastSystemStateChangeSensor.cs deleted file mode 100644 index 99e5991..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LastSystemStateChangeSensor.cs +++ /dev/null @@ -1,24 +0,0 @@ -using HASSAgent.Functions; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class LastSystemStateChangeSensor : AbstractSingleValueSensor - { - public LastSystemStateChangeSensor(int? updateInterval = 10, string name = "lastsystemstatechange", string id = default) : base(name ?? "lastsystemstatechange", updateInterval ?? 10, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:cog", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() => SystemStateManager.LastSystemStateEvent.ToString(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUserSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUserSensor.cs deleted file mode 100644 index 027ecf6..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUserSensor.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Text; -using HASSAgent.Functions; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class LoggedUserSensor : AbstractSingleValueSensor - { - public LoggedUserSensor(int? updateInterval = null, string name = "loggeduser", string id = default) : base(name ?? "loggeduser", updateInterval ?? 10, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:account-group", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() => Environment.UserName; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUsersSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUsersSensor.cs deleted file mode 100644 index 857aafe..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/LoggedUsersSensor.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; -using System.Text; -using HASSAgent.Functions; -using Newtonsoft.Json; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class LoggedUsersSensor : AbstractSingleValueSensor - { - public LoggedUsersSensor(int? updateInterval = null, string name = "loggedusers", string id = default) : base(name ?? "loggedusers", updateInterval ?? 30, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:account-group", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() => JsonConvert.SerializeObject(GetLoggedUsers()); - - private static IEnumerable GetLoggedUsers() - { - var loggedInUsers = new List(); - - var serverHandle = WTSOpenServer(Environment.MachineName); - var sessionInfoPtr = IntPtr.Zero; - - try - { - var sessionCount = 0; - var retVal = WTSEnumerateSessions(serverHandle, 0, 1, ref sessionInfoPtr, ref sessionCount); - var dataSize = Marshal.SizeOf(typeof(Cassia.Impl.WTS_SESSION_INFO)); - var currentSession = sessionInfoPtr; - - if (retVal == 0) - { - // nothing found, or error'd out - return GetLoggedUsersBackup(); - } - - for (var i = 0; i < sessionCount; i++) - { - var si = (Cassia.Impl.WTS_SESSION_INFO)Marshal.PtrToStructure(currentSession, typeof(Cassia.Impl.WTS_SESSION_INFO)); - currentSession += dataSize; - - WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSUserName, out var userPtr, out _); - - try - { - var user = Marshal.PtrToStringAnsi(userPtr)?.Trim(); - if (string.IsNullOrEmpty(user)) continue; - - if (!loggedInUsers.Contains(user)) loggedInUsers.Add(user); - } - finally - { - WTSFreeMemory(userPtr); - } - } - - return loggedInUsers; - } - catch (Exception ex) - { - Log.Fatal(ex, "[ACTIVEUSERS] Error while fetching logged users: {err}", ex.Message); - return loggedInUsers; - } - finally - { - WTSFreeMemory(sessionInfoPtr); - WTSCloseServer(serverHandle); - } - } - - private static IEnumerable GetLoggedUsersBackup() - { - var loggedInUsers = new List(); - - try - { - var explorers = Process.GetProcessesByName("explorer"); - foreach (var explorer in explorers) - { - try - { - var owner = HelperFunctions.GetProcessOwner(explorer, false); - if (string.IsNullOrEmpty(owner)) continue; - - if (!loggedInUsers.Contains(owner)) loggedInUsers.Add(owner); - } - finally - { - explorer?.Dispose(); - } - } - - return loggedInUsers; - } - catch (Exception ex) - { - Log.Fatal(ex, "[ACTIVEUSERS] Error while fetching logged users: {err}", ex.Message); - return loggedInUsers; - } - } - - #region IMPORTS - [StructLayout(LayoutKind.Sequential, Pack = 1)] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Local")] - private readonly struct SystemPowerCapabilities - { - [MarshalAs(UnmanagedType.U1)] internal readonly bool PowerButtonPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SleepButtonPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool LidPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SystemS1; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SystemS2; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SystemS3; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SystemS4; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SystemS5; - [MarshalAs(UnmanagedType.U1)] internal readonly bool HiberFilePresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool FullWake; - [MarshalAs(UnmanagedType.U1)] internal readonly bool VideoDimPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool ApmPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool UpsPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool ThermalControl; - [MarshalAs(UnmanagedType.U1)] internal readonly bool ProcessorThrottle; - private readonly byte ProcessorMinThrottle; - private readonly byte ProcessorMaxThrottle; - [MarshalAs(UnmanagedType.U1)] internal readonly bool FastSystemS4; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] internal readonly byte[] spare2; - [MarshalAs(UnmanagedType.U1)] internal readonly bool DiskSpinDown; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] internal readonly byte[] spare3; - [MarshalAs(UnmanagedType.U1)] internal readonly bool SystemBatteriesPresent; - [MarshalAs(UnmanagedType.U1)] internal readonly bool BatteriesAreShortTerm; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] internal readonly BatteryReportingScale[] BatteryScale; - private readonly SystemPowerState AcOnLineWake; - private readonly SystemPowerState SoftLidWake; - private readonly SystemPowerState RtcWake; - private readonly SystemPowerState MinDeviceWakeState; - private readonly SystemPowerState DefaultLowLatencyWake; - } - - internal struct BatteryReportingScale - { - internal ulong Granularity; - internal ulong Capacity; - } - - internal enum SystemPowerState - { - PowerSystemUnspecified = 0, - PowerSystemWorking = 1, - PowerSystemSleeping1 = 2, - PowerSystemSleeping2 = 3, - PowerSystemSleeping3 = 4, - PowerSystemHibernate = 5, - PowerSystemShutdown = 6, - PowerSystemMaximum = 7 - } - - [DllImport("powrprof.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetPwrCapabilities(out SystemPowerCapabilities systemPowerCapabilites); - - private static SystemPowerCapabilities SystemPowerCapabilites; - - [DllImport("advapi32.dll", SetLastError = true)] - private static extern bool GetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationClass, - IntPtr tokenInformation, int tokenInformationLength, out int returnLength); - - private enum TokenInformationClass - { - TokenElevationType - } - - private enum TokenElevationType - { - TokenElevationTypeDefault = 1, - TokenElevationTypeFull, - TokenElevationTypeLimited - } - - [DllImport("user32.dll", EntryPoint = ("GetSystemMetrics"))] - private static extern int GetSystemMetrics(int nIndex); - - - // Ingelogde Users imports - [DllImport("wtsapi32.dll")] - private static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] string pServerName); - - [DllImport("wtsapi32.dll")] - private static extern void WTSCloseServer(IntPtr hServer); - - [DllImport("wtsapi32.dll")] - private static extern int WTSEnumerateSessions( - IntPtr hServer, - [MarshalAs(UnmanagedType.U4)] int Reserved, - [MarshalAs(UnmanagedType.U4)] int Version, - ref IntPtr ppSessionInfo, - [MarshalAs(UnmanagedType.U4)] ref int pCount); - - [DllImport("wtsapi32.dll")] - private static extern void WTSFreeMemory(IntPtr pMemory); - - [DllImport("wtsapi32.dll")] - private static extern bool WTSQuerySessionInformation( - IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out IntPtr ppBuffer, out uint pBytesReturned); - - [StructLayout(LayoutKind.Sequential)] - private readonly struct WTS_SESSION_INFO - { - public readonly int SessionID; - - [MarshalAs(UnmanagedType.LPStr)] - private readonly string pWinStationName; - - private readonly WTS_CONNECTSTATE_CLASS State; - } - - [StructLayout(LayoutKind.Sequential)] - private readonly struct WTS_CLIENT_ADDRESS - { - private readonly int iAddressFamily; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] - public readonly byte[] bAddress; - } - - public enum WTS_INFO_CLASS - { - WTSInitialProgram, - WTSApplicationName, - WTSWorkingDirectory, - WTSOEMId, - WTSSessionId, - WTSUserName, - WTSWinStationName, - WTSDomainName, - WTSConnectState, - WTSClientBuildNumber, - WTSClientName, - WTSClientDirectory, - WTSClientProductId, - WTSClientHardwareId, - WTSClientAddress, - WTSClientDisplay, - WTSClientProtocolType - } - - public enum WTS_CONNECTSTATE_CLASS - { - WTSActive, - WTSConnected, - WTSConnectQuery, - WTSShadow, - WTSDisconnected, - WTSIdle, - WTSListen, - WTSReset, - WTSDown, - WTSInit - } - #endregion - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/MicrophoneActiveSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/MicrophoneActiveSensor.cs deleted file mode 100644 index 8bde74e..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/MicrophoneActiveSensor.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Linq; -using Microsoft.Win32; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class MicrophoneActiveSensor : AbstractSingleValueSensor - { - public override string Domain => "binary_sensor"; - public MicrophoneActiveSensor(int? updateInterval = null, string name = "microphoneactive", string id = default) : base(name ?? "microphoneactive", updateInterval ?? 10, id) {} - - public override string GetState() - { - return IsMicrophoneInUse() ? "ON" : "OFF"; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability" - }); - } - - private static bool IsMicrophoneInUse() - { - const string regKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone"; - bool inUse; - - // first local machine - using (var key = Registry.LocalMachine.OpenSubKey(regKey)) - { - inUse = CheckRegForMicrophoneInUse(key); - if (inUse) return true; - } - - // then current user - using (var key = Registry.CurrentUser.OpenSubKey(regKey)) - { - inUse = CheckRegForMicrophoneInUse(key); - if (inUse) return true; - } - - // nope - return false; - } - - private static bool CheckRegForMicrophoneInUse(RegistryKey key) - { - if (key == null) return false; - - foreach (var subKeyName in key.GetSubKeyNames()) - { - // NonPackaged has multiple subkeys - if (subKeyName == "NonPackaged") - { - using (var nonpackagedkey = key.OpenSubKey(subKeyName)) - { - if (nonpackagedkey == null) continue; - - foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) - { - using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) - { - if (subKey == null || !subKey.GetValueNames().Contains("LastUsedTimeStop")) continue; - - var endTime = subKey.GetValue("LastUsedTimeStop") is long - ? (long)subKey.GetValue("LastUsedTimeStop") - : -1; - - if (endTime <= 0) return true; - } - } - } - } - else - { - using (var subKey = key.OpenSubKey(subKeyName)) - { - if (subKey == null || !subKey.GetValueNames().Contains("LastUsedTimeStop")) continue; - - var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1; - if (endTime <= 0) return true; - } - } - } - - return false; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/NamedWindowSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/NamedWindowSensor.cs deleted file mode 100644 index 642b4d7..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/NamedWindowSensor.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Linq; -using HASSAgent.Functions; -using HWND = System.IntPtr; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class NamedWindowSensor : AbstractSingleValueSensor - { - public override string Domain => "binary_sensor"; - public string WindowName { get; protected set; } - - public NamedWindowSensor(string windowName, string name = "namedwindow", int? updateInterval = 10, string id = default) : base(name ?? "namedwindow", updateInterval ?? 30, id) - { - WindowName = windowName; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - var windowNames = HelperFunctions.GetOpenWindows().Values; - return windowNames.Any(v => v.ToUpper().Contains(WindowName.ToUpper())) ? "ON" : "OFF"; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ProcessActiveSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ProcessActiveSensor.cs deleted file mode 100644 index 9375c88..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ProcessActiveSensor.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using HASSAgent.Functions; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class ProcessActiveSensor : AbstractSingleValueSensor - { - public string ProcessName { get; protected set; } - - public ProcessActiveSensor(string processName, int? updateInterval = null, string name = "processactive", string id = default) : base(name ?? "processactive", updateInterval ?? 10, id) - { - ProcessName = processName; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:file-eye-outline", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - // we don't need the extension - if (ProcessName.Contains(".")) ProcessName = Path.GetFileNameWithoutExtension(ProcessName); - - // search for our process - var procs = Process.GetProcessesByName(ProcessName); - var instanceCount = procs.Any() ? procs.Length : 0; - - // dispose all objects - foreach (var proc in procs) proc?.Dispose(); - - // done - return instanceCount.ToString(); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ServiceStateSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ServiceStateSensor.cs deleted file mode 100644 index 28294eb..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/ServiceStateSensor.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.ServiceProcess; -using HASSAgent.Functions; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class ServiceStateSensor : AbstractSingleValueSensor - { - public string ServiceName { get; protected set; } - - public ServiceStateSensor(string serviceName, int? updateInterval = null, string name = "servicestate", string id = default) : base(name ?? "servicestate", updateInterval ?? 10, id) - { - ServiceName = serviceName; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:file-eye-outline", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - using (var svc = new ServiceController(ServiceName)) - { - try - { - return svc.Status.ToString(); - } - catch (InvalidOperationException) - { - // service wasn't found - return "NotFound"; - } - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/SessionStateSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/SessionStateSensor.cs deleted file mode 100644 index 7f1d5b6..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/SessionStateSensor.cs +++ /dev/null @@ -1,24 +0,0 @@ -using HASSAgent.Functions; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class SessionStateSensor : AbstractSingleValueSensor - { - public SessionStateSensor(int? updateInterval = null, string name = "sessionstate", string id = default) : base(name ?? "sessionstate", updateInterval ?? 10, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:lock", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() => SessionInfo.GetActiveSessionLockState().ToString(); - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/UserNotificationStateSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/UserNotificationStateSensor.cs deleted file mode 100644 index 169d76e..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/UserNotificationStateSensor.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Runtime.InteropServices; -using HASSAgent.Enums; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class UserNotificationStateSensor : AbstractSingleValueSensor - { - public UserNotificationStateSensor(int? updateInterval = null, string name = "notificationstate", string id = default) : base(name ?? "notificationstate", updateInterval ?? 10, id) { } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{Name}/state", - Icon = "mdi:laptop", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - return GetStateEnum().ToString(); - } - - [DllImport("shell32.dll")] - private static extern int SHQueryUserNotificationState(out UserNotificationState state); - - public UserNotificationState GetStateEnum() - { - SHQueryUserNotificationState(out var state); - return state; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/WebcamActiveSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/WebcamActiveSensor.cs deleted file mode 100644 index d28a75f..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/GeneralSensors/SingleValue/WebcamActiveSensor.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System.Linq; -using Microsoft.Win32; - -namespace HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue -{ - public class WebcamActiveSensor : AbstractSingleValueSensor - { - public override string Domain => "binary_sensor"; - public WebcamActiveSensor(int? updateInterval = null, string name = "webcamactive", string id = default) : base(name ?? "webcamactive", updateInterval ?? 10, id) {} - - public override string GetState() - { - return IsWebcamInUse() ? "ON" : "OFF"; - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{Name}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/sensor/{Variables.DeviceConfig.Name}/availability" - }); - } - - private static bool IsWebcamInUse() - { - const string regKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam"; - bool inUse; - - // first local machine - using (var key = Registry.LocalMachine.OpenSubKey(regKey)) - { - inUse = CheckRegForWebcamInUse(key); - if (inUse) return true; - } - - // then current user - using (var key = Registry.CurrentUser.OpenSubKey(regKey)) - { - inUse = CheckRegForWebcamInUse(key); - if (inUse) return true; - } - - // nope - return false; - } - - private static bool CheckRegForWebcamInUse(RegistryKey key) - { - if (key == null) return false; - - foreach (var subKeyName in key.GetSubKeyNames()) - { - // NonPackaged has multiple subkeys - if (subKeyName == "NonPackaged") - { - using (var nonpackagedkey = key.OpenSubKey(subKeyName)) - { - if (nonpackagedkey == null) continue; - - foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames()) - { - using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName)) - { - if (subKey == null || !subKey.GetValueNames().Contains("LastUsedTimeStop")) continue; - - var endTime = subKey.GetValue("LastUsedTimeStop") is long - ? (long)subKey.GetValue("LastUsedTimeStop") - : -1; - - if (endTime <= 0) return true; - } - } - } - } - else - { - using (var subKey = key.OpenSubKey(subKeyName)) - { - if (subKey == null || !subKey.GetValueNames().Contains("LastUsedTimeStop")) continue; - - var endTime = subKey.GetValue("LastUsedTimeStop") is long - ? (long)subKey.GetValue("LastUsedTimeStop") - : -1; - - if (endTime <= 0) return true; - } - } - } - - return false; - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerfCounterSensors/SingleValue/CpuLoadSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerfCounterSensors/SingleValue/CpuLoadSensor.cs deleted file mode 100644 index 3c104bc..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerfCounterSensors/SingleValue/CpuLoadSensor.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace HASSAgent.Models.HomeAssistant.Sensors.PerfCounterSensors.SingleValue -{ - public class CpuLoadSensor : PerformanceCounterSensor - { - public CpuLoadSensor(int? updateInterval = null, string name = "cpuload", string id = default) : base("Processor", "% Processor Time", "_Total", updateInterval ?? 30, name ?? "cpuload", id) {} - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:chart-areaspline", - Unit_of_measurement = "%", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerformanceCounterSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerformanceCounterSensor.cs deleted file mode 100644 index 96072a1..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/PerformanceCounterSensor.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Diagnostics; -using System.Globalization; -using HASSAgent.Functions; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors -{ - public class PerformanceCounterSensor : AbstractSingleValueSensor - { - protected PerformanceCounter Counter = null; - - public string CategoryName; - public string CounterName; - public string InstanceName; - - public PerformanceCounterSensor(string categoryName, string counterName, string instanceName, int? updateInterval = null, string name = "performancecountersensor", string id = default) : base(name ?? "performancecountersensor", updateInterval ?? 10, id) - { - CategoryName = categoryName; - CounterName = counterName; - InstanceName = instanceName; - - Counter = PerformanceCounters.GetSingleInstanceCounter(categoryName, counterName); - if (Counter == null) - { - Log.Error("[PERFMON] Counter not found: {cat}\\{name}\\{inst}", categoryName, counterName, instanceName); - return; - } - - Counter.InstanceName = instanceName; - - try - { - Counter.NextValue(); - } - catch (Exception ex) - { - Log.Fatal(ex, "[PERFMON] Error retrieving counter value for {cat}\\{name}\\{inst}: {msg}", categoryName, counterName, instanceName, ex.Message); - } - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{Name}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - if (Counter == null) return string.Empty; - try - { - return Math.Round(Counter.NextValue()).ToString(CultureInfo.InvariantCulture); - } - catch (Exception ex) - { - Log.Error("[PERFMON] Error retrieving counter value for {cat}\\{name}\\{inst}: {msg}", CategoryName, CounterName, InstanceName, ex.Message); - return string.Empty; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiQuerySensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiQuerySensor.cs deleted file mode 100644 index 52c6074..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiQuerySensor.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Management; - -namespace HASSAgent.Models.HomeAssistant.Sensors -{ - public class WmiQuerySensor : AbstractSingleValueSensor - { - public string Query { get; private set; } - public string Scope { get; private set; } - - protected readonly ObjectQuery ObjectQuery; - protected readonly ManagementObjectSearcher Searcher; - - public WmiQuerySensor(string query, string scope = "", int? updateInterval = null, string name = "wmiquerysensor", string id = default) : base(name ?? "wmiquerysensor", updateInterval ?? 10, id) - { - Query = query; - Scope = scope; - - // prepare query - ObjectQuery = new ObjectQuery(Query); - - // use either default or provided scope - var managementscope = !string.IsNullOrWhiteSpace(scope) ? new ManagementScope(scope) : new ManagementScope(@"\\localhost\"); - - // prepare searcher - Searcher = new ManagementObjectSearcher(managementscope, ObjectQuery); - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{Name}/state", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - using (var collection = Searcher.Get()) - { - var retValue = string.Empty; - foreach (var managementBaseObject in collection) - { - try - { - if (!string.IsNullOrEmpty(retValue)) continue; - - using (var managementObject = (ManagementObject)managementBaseObject) - { - foreach (var property in managementObject.Properties) - { - retValue = property.Value.ToString(); - break; - } - } - } - finally - { - managementBaseObject?.Dispose(); - } - } - return retValue; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/CurrentClockSpeedSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/CurrentClockSpeedSensor.cs deleted file mode 100644 index 54d331b..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/CurrentClockSpeedSensor.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Management; -using Serilog; - -namespace HASSAgent.Models.HomeAssistant.Sensors.WmiSensors.SingleValue -{ - public class CurrentClockSpeedSensor : WmiQuerySensor - { - private readonly ManagementObject _managementObject; - - private protected DateTime LastFetched = DateTime.MinValue; - private protected string LastValue = string.Empty; - - public CurrentClockSpeedSensor(int? updateInterval = null, string name = "currentclockspeed", string id = default) : base(string.Empty, string.Empty, updateInterval ?? 300, name ?? "currentclockspeed", id) - { - _managementObject = new ManagementObject("Win32_Processor.DeviceID='CPU0'"); - } - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:speedometer", - Unit_of_measurement = "MHz", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - try - { - // we're caching this, too heavy - if ((DateTime.Now - LastFetched).TotalHours < 1 && !string.IsNullOrEmpty(LastValue)) return LastValue; - LastFetched = DateTime.Now; - - var speed = (uint)(_managementObject["CurrentClockSpeed"]); - LastValue = speed.ToString(); - - return LastValue; - } - catch (Exception ex) - { - Log.Error("[WMI] Error getting current clockspeed: {msg}", ex.Message); - return "0"; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/MemoryUsageSensor.cs b/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/MemoryUsageSensor.cs deleted file mode 100644 index 2f7af96..0000000 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Sensors/WmiSensors/SingleValue/MemoryUsageSensor.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Globalization; -using System.Management; - -namespace HASSAgent.Models.HomeAssistant.Sensors.WmiSensors.SingleValue -{ - public class MemoryUsageSensor : WmiQuerySensor - { - public MemoryUsageSensor(int? updateInterval = null, string name = "memoryusage", string id = default) : base("SELECT FreePhysicalMemory,TotalVisibleMemorySize FROM Win32_OperatingSystem", string.Empty, updateInterval ?? 30, name ?? "memoryusage", id) {} - - public override DiscoveryConfigModel GetAutoDiscoveryConfig() - { - return AutoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() - { - Name = Name, - Unique_id = Id, - Device = Variables.DeviceConfig, - State_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/{ObjectId}/state", - Icon = "mdi:memory", - Unit_of_measurement = "%", - Availability_topic = $"{Variables.AppSettings.MqttDiscoveryPrefix}/{Domain}/{Variables.DeviceConfig.Name}/availability" - }); - } - - public override string GetState() - { - using (var collection = Searcher.Get()) - { - ulong? totalMemory = null; - ulong? freeMemory = null; - - foreach (var o in collection) - { - var mo = (ManagementObject)o; - try - { - totalMemory = (ulong)mo.Properties["TotalVisibleMemorySize"]?.Value; - freeMemory = (ulong)mo.Properties["FreePhysicalMemory"]?.Value; - } - finally - { - mo?.Dispose(); - } - } - - if (totalMemory == null) return string.Empty; - - decimal totalMemoryDec = totalMemory.Value; - decimal freeMemoryDec = freeMemory.Value; - - var precentageUsed = 100 - (freeMemoryDec / totalMemoryDec) * 100; - return precentageUsed.ToString("#.##", CultureInfo.InvariantCulture); - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/AudioSessionInfo.cs b/src/HASS.Agent/HASSAgent/Models/Internal/AudioSessionInfo.cs deleted file mode 100644 index 7824e03..0000000 --- a/src/HASS.Agent/HASSAgent/Models/Internal/AudioSessionInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace HASSAgent.Models.Internal -{ - public class AudioSessionInfo - { - public AudioSessionInfo() - { - // - } - - public string Application { get; set; } = string.Empty; - public bool Muted { get; set; } - public float MasterVolume { get; set; } = 0f; - public float PeakVolume { get; set; } = 0f; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/ConsoleResult.cs b/src/HASS.Agent/HASSAgent/Models/Internal/ConsoleResult.cs deleted file mode 100644 index 40e86b4..0000000 --- a/src/HASS.Agent/HASSAgent/Models/Internal/ConsoleResult.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace HASSAgent.Models.Internal -{ - public class ConsoleResult - { - public ConsoleResult() - { - // - } - - public ConsoleResult SetError(string errorOutput, int exitCode = -1, string output = "") - { - Error = true; - ExitCode = exitCode; - ErrorOutput = errorOutput; - Output = output; - - return this; - } - - public ConsoleResult SetSucces(string output, int exitCode = -1, string errorOuput = "") - { - Error = false; - ExitCode = exitCode; - Output = output; - ErrorOutput = errorOuput; - - return this; - } - - public bool Error { get; set; } - public int ExitCode { get; set; } = -1; - public string Output { get; set; } = string.Empty; - public string ErrorOutput { get; set; } = string.Empty; - } -} diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/WindowsUpdateInfo.cs b/src/HASS.Agent/HASSAgent/Models/Internal/WindowsUpdateInfo.cs deleted file mode 100644 index 1f067d5..0000000 --- a/src/HASS.Agent/HASSAgent/Models/Internal/WindowsUpdateInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace HASSAgent.Models.Internal -{ - public class WindowsUpdateInfo - { - public WindowsUpdateInfo() - { - // - } - - public string Title { get; set; } - public string Description { get; set; } - public List KbArticleIDs { get; set; } - public bool Hidden { get; set; } - public string SupportUrl { get; set; } - public string Type { get; set; } - public List Categories { get; set; } - } -} diff --git a/src/HASS.Agent/HASSAgent/Program.cs b/src/HASS.Agent/HASSAgent/Program.cs deleted file mode 100644 index eb69bc6..0000000 --- a/src/HASS.Agent/HASSAgent/Program.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Linq; -using System.Runtime.ExceptionServices; -using System.Security; -using System.Windows.Forms; -using HASSAgent.Forms; -using HASSAgent.Forms.ChildApplications; -using HASSAgent.Functions; -using HASSAgent.Settings; -using Serilog; - -namespace HASSAgent -{ - internal static class Program - { - /// - /// Main entry point - /// HandleProcessCorruptedStateExceptions and SecurityCritical make sure we can catch and log PCS exceptions before shutting down: - /// https://docs.microsoft.com/en-us/archive/msdn-magazine/2009/february/clr-inside-out-handling-corrupted-state-exceptions#id0070035 - /// - [HandleProcessCorruptedStateExceptions] - [SecurityCritical] - [STAThread] - private static void Main(string[] args) - { - try - { - // syncfusion license - Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(Variables.SyncfusionLicense); - - // get logging settings - Variables.ExtendedLogging = SettingsManager.GetExtendedLoggingSetting(); - Variables.ExceptionLogging = SettingsManager.GetExceptionReportingSetting(); - - // enable logging and optionally prepare Coderr - LoggingManager.PrepareLogging(); - - if (Variables.ExtendedLogging) - { - // make sure we catch 'm all - AppDomain.CurrentDomain.FirstChanceException += LoggingManager.CurrentDomainOnFirstChanceException; - } - else Log.Information("[PROGRAM] Extended logging disabled"); - - // prepare application - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - - // check to see if we're launched as a child application - if (args.Any(x => x == "update")) - { - Log.Information("[SYSTEM] Post-update mode activated"); - Variables.ChildApplicationMode = true; - - // prepare form - var postUpdate = new PostUpdate(); - - // prepare msgbox - HelperFunctions.SetMsgBoxStyle(postUpdate.Font); - - // run - Application.Run(postUpdate); - } - else if (args.Any(x => x == "portreservation")) - { - Log.Information("[SYSTEM] Port reservation mode activated"); - Variables.ChildApplicationMode = true; - - // prepare form - var portReservation = new PortReservation(); - - // prepare msgbox - HelperFunctions.SetMsgBoxStyle(portReservation.Font); - - // run - Application.Run(portReservation); - } - if (args.Any(x => x == "restart")) - { - Log.Information("[SYSTEM] Restart mode activated"); - Variables.ChildApplicationMode = true; - - // prepare form - var restart = new Restart(); - - // prepare msgbox - HelperFunctions.SetMsgBoxStyle(restart.Font); - - // run - Application.Run(restart); - } - else - { - // prepare default application - Variables.MainForm = new Main(); - - // prepare msgbox - HelperFunctions.SetMsgBoxStyle(Variables.MainForm.Font); - - // run (hidden) - Application.Run(new CustomApplicationContext(Variables.MainForm)); - } - } - catch (AccessViolationException ex) - { - Log.Fatal(ex, "[PROGRAM] AccessViolationException: {err}", ex.Message); - Log.CloseAndFlush(); - } - catch (Exception ex) - { - Log.Fatal(ex, "[PROGRAM] {err}", ex.Message); - Log.CloseAndFlush(); - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Properties/AssemblyInfo.cs b/src/HASS.Agent/HASSAgent/Properties/AssemblyInfo.cs deleted file mode 100644 index 40980a5..0000000 --- a/src/HASS.Agent/HASSAgent/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -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("HASS.Agent")] -[assembly: AssemblyDescription("Windows-based client for Home Assistant")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("LAB02 Research")] -[assembly: AssemblyProduct("HASS.Agent")] -[assembly: AssemblyCopyright("Copyright © LAB02 Research 2022")] -[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("407fff5a-97ea-429e-bd5e-81d93240a1bd")] - -// 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("2022.3.8.0")] -[assembly: AssemblyFileVersion("2022.3.8.0")] diff --git a/src/HASS.Agent/HASSAgent/Properties/Settings.Designer.cs b/src/HASS.Agent/HASSAgent/Properties/Settings.Designer.cs deleted file mode 100644 index 3babb7d..0000000 --- a/src/HASS.Agent/HASSAgent/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace HASSAgent.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/src/HASS.Agent/HASSAgent/Properties/Settings.settings b/src/HASS.Agent/HASSAgent/Properties/Settings.settings deleted file mode 100644 index 2bd17f0..0000000 --- a/src/HASS.Agent/HASSAgent/Properties/Settings.settings +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Sensors/SensorsManager.cs b/src/HASS.Agent/HASSAgent/Sensors/SensorsManager.cs deleted file mode 100644 index dda814e..0000000 --- a/src/HASS.Agent/HASSAgent/Sensors/SensorsManager.cs +++ /dev/null @@ -1,373 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using HASSAgent.Enums; -using HASSAgent.Models.Config; -using HASSAgent.Mqtt; -using HASSAgent.Settings; -using Serilog; - -namespace HASSAgent.Sensors -{ - /// - /// Continuously performs sensor autodiscovery and state publishing - /// - internal static class SensorsManager - { - private static readonly Dictionary SensorInfo = new Dictionary(); - - private static bool _active = true; - private static bool _pause; - - private static DateTime _lastAutoDiscoPublish = DateTime.MinValue; - - /// - /// Initializes the sensor manager - /// - internal static async void Initialize() - { - // load sensor descriptions - LoadSensorInfo(); - - // wait while mqtt's connecting - while (MqttManager.GetStatus() == MqttStatus.Connecting) await Task.Delay(250); - - // start background processing - _ = Task.Run(Process); - } - - /// - /// Stop processing sensor states - /// - internal static void Stop() => _active = false; - - /// - /// Pause processing sensor states - /// - internal static void Pause() => _pause = true; - - /// - /// Resume processing sensor states - /// - internal static void Unpause() => _pause = false; - - /// - /// Unpublishes all single- and multivalue sensors - /// - /// - internal static async Task UnpublishAllSensors() - { - // unpublish the autodisco's - if (SingleValueSensorsPresent()) foreach (var sensor in Variables.SingleValueSensors) await sensor.UnPublishAutoDiscoveryConfigAsync(); - if (MultiValueSensorsPresent()) foreach (var sensor in Variables.MultiValueSensors) await sensor.UnPublishAutoDiscoveryConfigAsync(); - } - - /// - /// Continously processes sensors (autodiscovery, states) - /// - private static async void Process() - { - // we use the firstrun flag to publish our state without respecting the time elapsed/value change check - // otherwise, the state might stay in 'unknown' in HA until the value changes - var firstRun = true; - var firstRunDone = false; - - while (_active) - { - try - { - await Task.Delay(TimeSpan.FromMilliseconds(750)); - - // are we paused? - if (_pause) continue; - - // is mqtt available? - if (MqttManager.GetStatus() != MqttStatus.Connected) - { - // nothing to do - continue; - } - - // optionally flag as the first real run - if (!firstRunDone) firstRunDone = true; - - // publish availability & sensor autodisco's every 30 sec - if ((DateTime.Now - _lastAutoDiscoPublish).TotalSeconds > 30) - { - // let hass know we're still here - await MqttManager.AnnounceAvailabilityAsync(); - - // publish the autodisco's - if (SingleValueSensorsPresent()) - { - foreach (var sensor in Variables.SingleValueSensors.TakeWhile(sensor => !_pause).TakeWhile(command => _active)) - { - if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue; - await sensor.PublishAutoDiscoveryConfigAsync(); - } - } - - if (MultiValueSensorsPresent()) - { - foreach (var sensor in Variables.MultiValueSensors.TakeWhile(sensor => !_pause).TakeWhile(command => _active)) - { - if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue; - await sensor.PublishAutoDiscoveryConfigAsync(); - } - } - - // log moment - _lastAutoDiscoPublish = DateTime.Now; - } - - if (_pause) continue; - - // publish sensor states (they have their own time-based scheduling) - if (SingleValueSensorsPresent()) - { - foreach (var sensor in Variables.SingleValueSensors.TakeWhile(sensor => !_pause).TakeWhile(command => _active)) - { - if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue; - await sensor.PublishStateAsync(!firstRun); - } - } - - // check if there are multivalue sensors - if (!MultiValueSensorsPresent()) continue; - - foreach (var sensor in Variables.MultiValueSensors.TakeWhile(sensor => !_pause).TakeWhile(command => _active)) - { - if (_pause || MqttManager.GetStatus() != MqttStatus.Connected) continue; - await sensor.PublishStatesAsync(!firstRun); - } - } - catch (Exception ex) - { - Log.Fatal(ex, "[SENSORSMANAGER] Error while publishing: {err}", ex.Message); - } - finally - { - // check if we need to take down the 'first run' flag - if (firstRunDone && firstRun) firstRun = false; - } - } - } - - /// - /// Resets all sensor checks (last sent and previous value), so they'll all be published again - /// - internal static void ResetAllSensorChecks() - { - try - { - // pause processing - Pause(); - - // reset single-value sensors - if (SingleValueSensorsPresent()) - { - foreach (var sensor in Variables.SingleValueSensors) sensor.ResetChecks(); - } - - // reset multi-value sensors - if (MultiValueSensorsPresent()) - { - foreach (var sensor in Variables.MultiValueSensors) sensor.ResetChecks(); - } - - // done - } - catch (Exception ex) - { - Log.Fatal(ex, "[SENSORSMANAGER] Error while resetting all sensor checks: {err}", ex.Message); - } - finally - { - // resume processing - Unpause(); - } - } - - /// - /// Stores the provided sensors, and (re)publishes them - /// - /// - /// - /// - internal static async Task StoreAsync(List sensors, List toBeDeletedSensors = null) - { - if (toBeDeletedSensors == null) toBeDeletedSensors = new List(); - - try - { - // pause processing - Pause(); - - // process the to-be-removed - if (toBeDeletedSensors.Any()) - { - foreach (var sensor in toBeDeletedSensors.Where(sensor => sensor != null)) - { - if (sensor.IsSingleValue()) - { - var abstractSensor = StoredSensors.ConvertConfiguredToAbstractSingleValue(sensor); - - // remove and unregister - await abstractSensor.UnPublishAutoDiscoveryConfigAsync(); - Variables.SingleValueSensors.RemoveAt(Variables.SingleValueSensors.FindIndex(x => x.Id == abstractSensor.Id)); - - Log.Information("[SENSORS] Removed single-value sensor: {sensor}", abstractSensor.Name); - } - else - { - var abstractSensor = StoredSensors.ConvertConfiguredToAbstractMultiValue(sensor); - - // remove and unregister - await abstractSensor.UnPublishAutoDiscoveryConfigAsync(); - Variables.MultiValueSensors.RemoveAt(Variables.MultiValueSensors.FindIndex(x => x.Id == abstractSensor.Id)); - - Log.Information("[SENSORS] Removed multi-value sensor: {sensor}", abstractSensor.Name); - } - } - } - - // copy our list to the main one - foreach (var sensor in sensors.Where(sensor => sensor != null)) - { - if (sensor.IsSingleValue()) - { - var abstractSensor = StoredSensors.ConvertConfiguredToAbstractSingleValue(sensor); - if (Variables.SingleValueSensors.All(x => x.Id != abstractSensor.Id)) - { - // new, add and register - Variables.SingleValueSensors.Add(abstractSensor); - await abstractSensor.PublishAutoDiscoveryConfigAsync(); - await abstractSensor.PublishStateAsync(false); - - Log.Information("[SENSORS] Added single-value sensor: {sensor}", abstractSensor.Name); - continue; - } - - // existing, update and re-register - var currentSensorIndex = Variables.SingleValueSensors.FindIndex(x => x.Id == abstractSensor.Id); - if (Variables.SingleValueSensors[currentSensorIndex].Name != abstractSensor.Name) - { - // name changed, unregister - Log.Information("[SENSORS] Single-value sensor changed name, re-registering as new entity: {old} to {new}", Variables.SingleValueSensors[currentSensorIndex].Name, abstractSensor.Name); - - await Variables.SingleValueSensors[currentSensorIndex].UnPublishAutoDiscoveryConfigAsync(); - } - - Variables.SingleValueSensors[currentSensorIndex] = abstractSensor; - await abstractSensor.PublishAutoDiscoveryConfigAsync(); - await abstractSensor.PublishStateAsync(false); - - Log.Information("[SENSORS] Modified single-value sensor: {sensor}", abstractSensor.Name); - } - else - { - var abstractSensor = StoredSensors.ConvertConfiguredToAbstractMultiValue(sensor); - if (Variables.MultiValueSensors.All(x => x.Id != abstractSensor.Id)) - { - // new, add and register - Variables.MultiValueSensors.Add(abstractSensor); - await abstractSensor.PublishAutoDiscoveryConfigAsync(); - await abstractSensor.PublishStatesAsync(false); - - Log.Information("[SENSORS] Added multi-value sensor: {sensor}", abstractSensor.Name); - continue; - } - - // existing, update and re-register - var currentSensorIndex = Variables.MultiValueSensors.FindIndex(x => x.Id == abstractSensor.Id); - if (Variables.MultiValueSensors[currentSensorIndex].Name != abstractSensor.Name) - { - // name changed, unregister - Log.Information("[SENSORS] Multi-value sensor changed name, re-registering as new entity: {old} to {new}", Variables.MultiValueSensors[currentSensorIndex].Name, abstractSensor.Name); - - await Variables.MultiValueSensors[currentSensorIndex].UnPublishAutoDiscoveryConfigAsync(); - } - - Variables.MultiValueSensors[currentSensorIndex] = abstractSensor; - await abstractSensor.PublishAutoDiscoveryConfigAsync(); - await abstractSensor.PublishStatesAsync(false); - - Log.Information("[SENSORS] Modified multi-value sensor: {sensor}", abstractSensor.Name); - } - } - - // annouce ourselves - await MqttManager.AnnounceAvailabilityAsync(); - - // store to file - StoredSensors.Store(); - - // done - return true; - } - catch (Exception ex) - { - Log.Fatal(ex, "[SENSORSMANAGER] Error while storing: {err}", ex.Message); - return false; - } - finally - { - // resume processing - Unpause(); - } - } - - private static bool SingleValueSensorsPresent() => Variables.SingleValueSensors != null && Variables.SingleValueSensors.Any(); - private static bool MultiValueSensorsPresent() => Variables.MultiValueSensors != null && Variables.MultiValueSensors.Any(); - - /// - /// Returns default information for the specified sensor type - /// - /// - /// - internal static (string name, int interval) GetSensorDefaultInfo(SensorType type) - { - return !SensorInfo.ContainsKey(type) ? ("Unknown sensor, make sure HASS.Agent has finished booting up", 0) : SensorInfo[type]; - } - - /// - /// Loads info regarding the various sensor types - /// - private static void LoadSensorInfo() - { - SensorInfo.Add(SensorType.UserNotificationStateSensor, ("Provides the current user state:\r\n\r\nNotPresent, Busy, RunningDirect3dFullScreen, PresentationMode, AcceptsNotifications, QuietTime or RunningWindowsStoreApp.\r\n\r\nCan for instance be used to determine whether to send notifications or TTS messages.", 10)); - SensorInfo.Add(SensorType.DummySensor, ("Dummy sensor for testing purposes, sends a random integer value between 0 and 100.", 5)); - SensorInfo.Add(SensorType.CurrentClockSpeedSensor, ("Provides the current clockspeed of the first CPU.", 300)); - SensorInfo.Add(SensorType.CpuLoadSensor, ("Provides the current load of the first CPU as a percentage.", 30)); - SensorInfo.Add(SensorType.MemoryUsageSensor, ("Provides the amount of used memory as a percentage.", 30)); - SensorInfo.Add(SensorType.ActiveWindowSensor, ("Provides the title of the current active window.", 15)); - SensorInfo.Add(SensorType.NamedWindowSensor, ("Provides an ON/OFF value based on whether the window is currently open (doesn't have to be active).", 30)); - SensorInfo.Add(SensorType.LastActiveSensor, ("Provides a datetime value containing the last moment the user provided any input.", 10)); - SensorInfo.Add(SensorType.LastSystemStateChangeSensor, ("Provides the last system state change:\r\n\r\nHassAgentStarted, Logoff, SystemShutdown, Resume, Suspend, ConsoleConnect, ConsoleDisconnect, RemoteConnect, RemoteDisconnect, SessionLock, SessionLogoff, SessionLogon, SessionRemoteControl and SessionUnlock.", 10)); - SensorInfo.Add(SensorType.LastBootSensor, ("Provides a datetime value containing the last moment the system (re)booted.\r\n\r\nImportant: Windows' FastBoot option can throw this value off, because that's a form of hibernation. You can disable it through Power Options -> 'Choose what the power buttons do' -> uncheck 'Turn on fast start-up'. It doesn't make much difference for modern machines with SSDs, but disabling makes sure you get a clean state after rebooting.", 10)); - SensorInfo.Add(SensorType.WebcamActiveSensor, ("Provides a bool value based on whether the webcam is currently being used.", 10)); - SensorInfo.Add(SensorType.MicrophoneActiveSensor, ("Provides a bool value based on whether the microphone is currently being used.", 10)); - SensorInfo.Add(SensorType.SessionStateSensor, ("Provides the current session state:\r\n\r\nLocked, Unlocked or Unknown.\r\n\r\nUse a LastSystemStateChangeSensor to monitor session state changes.", 10)); - SensorInfo.Add(SensorType.CurrentVolumeSensor, ("Provides the current volume level as a percentage.\r\n\r\nCurrently takes the volume of your default device.", 15)); - SensorInfo.Add(SensorType.GpuLoadSensor, ("Provides the current load of the first GPU as a percentage.", 30)); - SensorInfo.Add(SensorType.GpuTemperatureSensor, ("Provides the current temperature of the first GPU.", 30)); - SensorInfo.Add(SensorType.WmiQuerySensor, ("Provides the result of the provided WMI query.", 10)); - SensorInfo.Add(SensorType.StorageSensors, ("Provides the labels, total size (MB), available space (MB), used space (MB) and file system of all present non-removable disks.\r\n\r\nThis is a multi-value sensor.", 30)); - SensorInfo.Add(SensorType.NetworkSensors, ("Provides card info, configuration, transfer- & package statistics and addresses (ip, mac, dhcp, dns) of all present network cards.\r\n\r\nThis is a multi-value sensor.", 30)); - SensorInfo.Add(SensorType.PerformanceCounterSensor, ("Provides the values of a performance counter.\r\n\r\nFor example, the built-in CPU load sensor uses these values:\r\n\r\nCategory: Processor\r\nCounter: % Processor Time\r\nInstance: _Total\r\n\r\nYou can explore the counters through Windows' 'perfmon.exe' tool.", 30)); - - //SensorInfo.Add(SensorType.WindowsUpdatesSensors, ("Provides a sensor with the amount of pending driver updates, a sensor with the amount of pending software updates, a sensor containing all pending driver updates information (title, kb article id's, hidden, type and categories) and a sensor containing the same for pending software updates.\r\n\r\nThis is a costly request, so the recommended interval is 15 minutes (900 seconds). But it's capped at 10 minutes, if you provide a lower value, you'll get the last known list.\r\n\r\nThis is a multi-value sensor.", 900)); - SensorInfo.Add(SensorType.WindowsUpdatesSensors, ("Provides a sensor with the amount of pending driver updates and a sensor with the amount of pending software updates.\r\n\r\nThis is a costly request, so the recommended interval is 15 minutes (900 seconds). But it's capped at 10 minutes, if you provide a lower value, you'll get the last known list.\r\n\r\nThis is a multi-value sensor.", 900)); - - SensorInfo.Add(SensorType.BatterySensors, ("Provides a sensor with the current charging status, estimated amount of minutes on a full charge, remaining charge in percentage, remaining charge in minutes and the powerline status.\r\n\r\nThis is a multi-value sensor.", 30)); - SensorInfo.Add(SensorType.DisplaySensors, ("Provides a sensor with the amount of displays, name of the primary display, and per display its name, resolution and bits per pixel.\r\n\r\nThis is a multi-value sensor.", 15)); - SensorInfo.Add(SensorType.AudioSensors, ("Provides information various aspects of your device's audio:\r\n\r\nCurrent peak volume level (can be used as a simple 'is something playing' value).\r\n\r\nDefault audiodevice: name, state and volume.\r\n\r\nSummary of your audio sessions: application name, muted state, volume and current peak volume.\r\n\r\nThis is a multi-value sensor.", 20)); - SensorInfo.Add(SensorType.ProcessActiveSensor, ("Provides the number of active instances of the process.", 10)); - SensorInfo.Add(SensorType.ServiceStateSensor, ("Returns the state of the provided service: NotFound, Stopped, StartPending, StopPending, Running, ContinuePending, PausePending or Paused.\r\n\r\nMake sure to provide the 'Service name', not the 'Display name'.", 10)); - SensorInfo.Add(SensorType.LoggedUsersSensor, ("Returns a json-formatted list of currently logged users.", 30)); - SensorInfo.Add(SensorType.LoggedUserSensor, ("Returns the name of the currently logged user.", 30)); - } - } -} diff --git a/src/HASSAgent.sln b/src/HASSAgent.sln new file mode 100644 index 0000000..5922a24 --- /dev/null +++ b/src/HASSAgent.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HASSAgent", "HASSAgent\HASSAgent.csproj", "{F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Debug|x64.ActiveCfg = Debug|x64 + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Debug|x64.Build.0 = Debug|x64 + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Release|Any CPU.Build.0 = Release|Any CPU + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Release|x64.ActiveCfg = Release|x64 + {F172A9B4-AA7B-4F78-B44A-A2BC0CD52DAA}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + VisualSVNWorkingCopyRoot = . + SolutionGuid = {4350BB92-A2B6-4199-B628-AC4EBD1DE959} + EndGlobalSection +EndGlobal diff --git a/src/HASSAgent/Commands/CommandsManager.cs b/src/HASSAgent/Commands/CommandsManager.cs new file mode 100644 index 0000000..828ca79 --- /dev/null +++ b/src/HASSAgent/Commands/CommandsManager.cs @@ -0,0 +1,406 @@ +using HASSAgent.Models.Internal; +using HASSAgent.Settings; +using HASSAgent.Shared.Enums; +using HASSAgent.Shared.Models.Config; +using Serilog; + +namespace HASSAgent.Commands +{ + /// + /// Continuously performs command autodiscovery and state publishing + /// + internal static class CommandsManager + { + internal static readonly Dictionary CommandInfoCards = new(); + + private static bool _active = true; + private static bool _pause; + + private static DateTime _lastAutoDiscoPublish = DateTime.MinValue; + + /// + /// Initializes the command manager + /// + internal static async void Initialize() + { + // wait while mqtt's connecting + while (Variables.MqttManager.GetStatus() == MqttStatus.Connecting) await Task.Delay(250); + + // start background processing + _ = Task.Run(Process); + } + + /// + /// Stop processing commands + /// + internal static void Stop() => _active = false; + + /// + /// Pause processing commands + /// + internal static void Pause() => _pause = true; + + /// + /// Resume processing commands + /// + internal static void Unpause() => _pause = false; + + /// + /// Unpublishes all commands + /// + /// + internal static async Task UnpublishAllCommands() + { + // unpublish the autodisco's + if (!CommandsPresent()) return; + foreach (var command in Variables.Commands) + { + await command.UnPublishAutoDiscoveryConfigAsync(); + await Variables.MqttManager.UnubscribeAsync(command); + } + } + + /// + /// Generates new ID's for all commands + /// + internal static void ResetCommandIds() + { + if (!CommandsPresent()) return; + foreach (var command in Variables.Commands) command.Id = Guid.NewGuid().ToString(); + + StoredCommands.Store(); + } + + /// + /// Continuously processes commands (autodiscovery, state) + /// + private static async void Process() + { + var firstRun = true; + var subscribed = false; + + while (_active) + { + try + { + if (firstRun) + { + // 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)); + } + else await Task.Delay(TimeSpan.FromSeconds(30)); + + // are we paused? + if (_pause) continue; + + // is mqtt available? + if (Variables.MqttManager.GetStatus() != MqttStatus.Connected) + { + // nothing to do + continue; + } + + // we're starting the first real run + firstRun = false; + + // do we have commands? + if (!CommandsPresent()) continue; + + // publish availability & sensor autodisco's every 30 sec + if ((DateTime.Now - _lastAutoDiscoPublish).TotalSeconds > 30) + { + // let hass know we're still here + await Variables.MqttManager.AnnounceAvailabilityAsync(); + + // publish command autodisco's + foreach (var command in Variables.Commands.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await command.PublishAutoDiscoveryConfigAsync(); + } + + // are we subscribed? + if (!subscribed) + { + foreach (var command in Variables.Commands.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await Variables.MqttManager.SubscribeAsync(command); + } + subscribed = true; + } + + // log moment + _lastAutoDiscoPublish = DateTime.Now; + } + + // publish command states (they have their own time-based scheduling) + foreach (var command in Variables.Commands.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await command.PublishStateAsync(); + } + } + catch (Exception ex) + { + Log.Fatal(ex, "[COMMANDSMANAGER] Error while publishing: {err}", ex.Message); + } + } + } + + /// + /// Stores the provided commands, and (re)publishes them + /// + /// + /// + /// + internal static async Task StoreAsync(List commands, List toBeDeletedCommands = null) + { + toBeDeletedCommands ??= new List(); + + 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 Variables.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 Variables.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 Variables.MqttManager.UnubscribeAsync(Variables.Commands[currentCommandIndex]); + await Variables.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 Variables.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(); + } + } + + private static bool CommandsPresent() => Variables.Commands != null && Variables.Commands.Any(); + + /// + /// Returns default information for the specified command type, or null if not found + /// + /// + /// + internal static CommandInfoCard GetCommandDefaultInfo(CommandType type) + { + return CommandInfoCards.ContainsKey(type) ? CommandInfoCards[type] : null; + } + + /// + /// Loads info regarding the various command types + /// + internal static void LoadCommandInfo() + { + // ================================= + + var commandInfoCard = new CommandInfoCard(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.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(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.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.HibernateCommand, + "Sets the machine in hibernation.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(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\nIf you need more keys and/or modifiers like CTRL, use the MultipleKeys command.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(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.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.LockCommand, + "Locks the current session.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.LogOffCommand, + "Logs off the current session.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MediaMuteCommand, + "Simulates 'mute' key.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MediaNextCommand, + "Simulates 'media next' key.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MediaPlayPauseCommand, + "Simulates 'media playpause' key.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MediaPreviousCommand, + "Simulates 'media previous' key.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MediaVolumeDownCommand, + "Simulates 'volume down' key.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MediaVolumeUpCommand, + "Simulates 'volume up' key.", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.MultipleKeysCommand, + "Simulates pressing mulitple keys.\r\n\r\nYou need to put [ ] between every key, otherwise HASS.Agent can't tell them apart. So say you want to press X TAB Y SHIFT-Z, it'd be [X] [{TAB}] [Y] [+Z].\r\n\r\nThere are a few tricks you can use:\r\n\r\n- Special keys go between { }, like {TAB} or {UP}\r\n\r\n- Put a + in front of a key to add SHIFT, ^ for CTRL and % for ALT. So, +C is SHIFT-C. Or, +(CD) is SHIFT-C and SHIFT-D, while +CD is SHIFT-C and D\r\n\r\n- For multiple presses, use {z 15}, which means Z will get pressed 15 times.\r\n\r\nMore info: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys", + true, false); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.PowershellCommand, + "Execute a Powershell command or script.\r\n\r\nYou can either provide the location of a script (*.ps1), or a single-line command.\r\n\r\nThis will run without special elevation.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(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.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.RestartCommand, + "Restarts the machine after one minute.\r\n\r\nTip: accidentally triggered? Run 'shutdown /a' to abort.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(CommandType.ShutdownCommand, + "Shuts down the machine after one minute.\r\n\r\nTip: accidentally triggered? Run 'shutdown /a' to abort.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + + // ================================= + + commandInfoCard = new CommandInfoCard(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.", + true, true); + + CommandInfoCards.Add(commandInfoCard.CommandType, commandInfoCard); + } + } +} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs b/src/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs similarity index 80% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs rename to src/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs index e81e8e1..59be6b7 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/ExternalTools.Designer.cs @@ -49,10 +49,11 @@ private void InitializeComponent() // // label31 // - this.label31.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label31.Location = new System.Drawing.Point(27, 19); + this.label31.AutoSize = true; + this.label31.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label31.Location = new System.Drawing.Point(70, 36); this.label31.Name = "label31"; - this.label31.Size = new System.Drawing.Size(669, 44); + this.label31.Size = new System.Drawing.Size(388, 19); this.label31.TabIndex = 57; this.label31.Text = "This page allows you to configure bindings with external tools."; // @@ -60,9 +61,9 @@ private void InitializeComponent() // this.TbExternalBrowserName.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbExternalBrowserName.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbExternalBrowserName.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbExternalBrowserName.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbExternalBrowserName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbExternalBrowserName.Location = new System.Drawing.Point(102, 227); + this.TbExternalBrowserName.Location = new System.Drawing.Point(73, 238); this.TbExternalBrowserName.Name = "TbExternalBrowserName"; this.TbExternalBrowserName.Size = new System.Drawing.Size(358, 25); this.TbExternalBrowserName.TabIndex = 55; @@ -70,20 +71,20 @@ private void InitializeComponent() // label30 // this.label30.AutoSize = true; - this.label30.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label30.Location = new System.Drawing.Point(99, 207); + this.label30.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label30.Location = new System.Drawing.Point(70, 216); this.label30.Name = "label30"; - this.label30.Size = new System.Drawing.Size(92, 17); + this.label30.Size = new System.Drawing.Size(96, 19); this.label30.TabIndex = 56; this.label30.Text = "browser name"; // // label32 // this.label32.AutoSize = true; - this.label32.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label32.Location = new System.Drawing.Point(99, 80); + this.label32.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label32.Location = new System.Drawing.Point(70, 89); this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(547, 51); + this.label32.Size = new System.Drawing.Size(579, 57); this.label32.TabIndex = 58; this.label32.Text = resources.GetString("label32.Text"); // @@ -91,9 +92,9 @@ private void InitializeComponent() // this.TbExternalBrowserBinary.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbExternalBrowserBinary.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbExternalBrowserBinary.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbExternalBrowserBinary.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbExternalBrowserBinary.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbExternalBrowserBinary.Location = new System.Drawing.Point(102, 169); + this.TbExternalBrowserBinary.Location = new System.Drawing.Point(73, 180); this.TbExternalBrowserBinary.Name = "TbExternalBrowserBinary"; this.TbExternalBrowserBinary.Size = new System.Drawing.Size(358, 25); this.TbExternalBrowserBinary.TabIndex = 59; @@ -102,10 +103,10 @@ private void InitializeComponent() // label1 // this.label1.AutoSize = true; - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(99, 149); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(70, 158); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(96, 17); + this.label1.Size = new System.Drawing.Size(100, 19); this.label1.TabIndex = 60; this.label1.Text = "browser binary"; // @@ -113,9 +114,9 @@ private void InitializeComponent() // this.TbExternalBrowserIncognito.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbExternalBrowserIncognito.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbExternalBrowserIncognito.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbExternalBrowserIncognito.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbExternalBrowserIncognito.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbExternalBrowserIncognito.Location = new System.Drawing.Point(102, 290); + this.TbExternalBrowserIncognito.Location = new System.Drawing.Point(73, 301); this.TbExternalBrowserIncognito.Name = "TbExternalBrowserIncognito"; this.TbExternalBrowserIncognito.Size = new System.Drawing.Size(358, 25); this.TbExternalBrowserIncognito.TabIndex = 61; @@ -123,10 +124,10 @@ private void InitializeComponent() // label2 // this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(99, 270); + this.label2.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(70, 279); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(127, 17); + this.label2.Size = new System.Drawing.Size(134, 19); this.label2.TabIndex = 62; this.label2.Text = "launch incognito arg"; // @@ -134,9 +135,9 @@ private void InitializeComponent() // this.TbExternalExecutorBinary.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbExternalExecutorBinary.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbExternalExecutorBinary.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbExternalExecutorBinary.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbExternalExecutorBinary.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbExternalExecutorBinary.Location = new System.Drawing.Point(102, 460); + this.TbExternalExecutorBinary.Location = new System.Drawing.Point(73, 471); this.TbExternalExecutorBinary.Name = "TbExternalExecutorBinary"; this.TbExternalExecutorBinary.Size = new System.Drawing.Size(358, 25); this.TbExternalExecutorBinary.TabIndex = 66; @@ -145,20 +146,20 @@ private void InitializeComponent() // label3 // this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(99, 440); + this.label3.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(70, 449); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(144, 17); + this.label3.Size = new System.Drawing.Size(152, 19); this.label3.TabIndex = 67; this.label3.Text = "custom executor binary"; // // label4 // this.label4.AutoSize = true; - this.label4.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label4.Location = new System.Drawing.Point(99, 387); + this.label4.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label4.Location = new System.Drawing.Point(70, 399); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(457, 34); + this.label4.Size = new System.Drawing.Size(477, 38); this.label4.TabIndex = 65; this.label4.Text = "You can configure HASS.Agent to use a specific executor, like perl or python. \r\nU" + "se the \'custom executor\' command to launch this executor."; @@ -167,9 +168,9 @@ private void InitializeComponent() // this.TbExternalExecutorName.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbExternalExecutorName.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbExternalExecutorName.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbExternalExecutorName.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbExternalExecutorName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbExternalExecutorName.Location = new System.Drawing.Point(102, 520); + this.TbExternalExecutorName.Location = new System.Drawing.Point(73, 531); this.TbExternalExecutorName.Name = "TbExternalExecutorName"; this.TbExternalExecutorName.Size = new System.Drawing.Size(358, 25); this.TbExternalExecutorName.TabIndex = 63; @@ -177,30 +178,30 @@ private void InitializeComponent() // label5 // this.label5.AutoSize = true; - this.label5.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label5.Location = new System.Drawing.Point(99, 500); + this.label5.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label5.Location = new System.Drawing.Point(70, 509); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(140, 17); + this.label5.Size = new System.Drawing.Size(148, 19); this.label5.TabIndex = 64; this.label5.Text = "custom executor name"; // // label27 // this.label27.AutoSize = true; - this.label27.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label27.Location = new System.Drawing.Point(466, 174); + this.label27.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label27.Location = new System.Drawing.Point(437, 184); this.label27.Name = "label27"; - this.label27.Size = new System.Drawing.Size(141, 13); + this.label27.Size = new System.Drawing.Size(143, 15); this.label27.TabIndex = 68; this.label27.Text = "tip: doubleclick to browse"; // // label6 // this.label6.AutoSize = true; - this.label6.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label6.Location = new System.Drawing.Point(466, 465); + this.label6.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label6.Location = new System.Drawing.Point(437, 475); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(141, 13); + this.label6.Size = new System.Drawing.Size(143, 15); this.label6.TabIndex = 69; this.label6.Text = "tip: doubleclick to browse"; // @@ -208,9 +209,9 @@ private void InitializeComponent() // this.BtnExternalBrowserIncognitoTest.AccessibleName = "Button"; this.BtnExternalBrowserIncognitoTest.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnExternalBrowserIncognitoTest.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnExternalBrowserIncognitoTest.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnExternalBrowserIncognitoTest.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnExternalBrowserIncognitoTest.Location = new System.Drawing.Point(469, 290); + this.BtnExternalBrowserIncognitoTest.Location = new System.Drawing.Point(437, 301); this.BtnExternalBrowserIncognitoTest.Name = "BtnExternalBrowserIncognitoTest"; this.BtnExternalBrowserIncognitoTest.Size = new System.Drawing.Size(138, 25); this.BtnExternalBrowserIncognitoTest.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -247,7 +248,6 @@ private void InitializeComponent() this.Controls.Add(this.label31); this.Controls.Add(this.TbExternalBrowserName); this.Controls.Add(this.label30); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "ExternalTools"; diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.cs b/src/HASSAgent/Controls/Configuration/ExternalTools.cs similarity index 67% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.cs rename to src/HASSAgent/Controls/Configuration/ExternalTools.cs index 21de427..eacd2a3 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/ExternalTools.cs +++ b/src/HASSAgent/Controls/Configuration/ExternalTools.cs @@ -1,14 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; +using System.Diagnostics; using Serilog; using Syncfusion.Windows.Forms; @@ -23,18 +13,16 @@ public ExternalTools() private void TbExternalBrowserBinary_DoubleClick(object sender, EventArgs e) { - using (var dialog = new OpenFileDialog()) - { - dialog.CheckFileExists = true; - dialog.Multiselect = false; - dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + using var dialog = new OpenFileDialog(); + dialog.CheckFileExists = true; + dialog.Multiselect = false; + dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) return; + var result = dialog.ShowDialog(); + if (result != DialogResult.OK) return; - // process selected browser - ProcessSelectedBrowser(dialog.FileName); - } + // process selected browser + ProcessSelectedBrowser(dialog.FileName); } /// @@ -81,18 +69,16 @@ private void ProcessSelectedBrowser(string binary) private void TbExternalExecutorBinary_DoubleClick(object sender, EventArgs e) { - using (var dialog = new OpenFileDialog()) - { - dialog.CheckFileExists = true; - dialog.Multiselect = false; - dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + using var dialog = new OpenFileDialog(); + dialog.CheckFileExists = true; + dialog.Multiselect = false; + dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) return; + var result = dialog.ShowDialog(); + if (result != DialogResult.OK) return; - TbExternalExecutorBinary.Text = dialog.FileName; - TbExternalExecutorName.Text = Path.GetFileNameWithoutExtension(dialog.FileName); - } + TbExternalExecutorBinary.Text = dialog.FileName; + TbExternalExecutorName.Text = Path.GetFileNameWithoutExtension(dialog.FileName); } private void BtnExternalBrowserIncognitoTest_Click(object sender, EventArgs e) @@ -130,17 +116,15 @@ private void BtnExternalBrowserIncognitoTest_Click(object sender, EventArgs e) try { - using (var testProc = new Process()) + using var testProc = new Process(); + var startupArgs = new ProcessStartInfo { - var startupArgs = new ProcessStartInfo - { - FileName = browserBin, - Arguments = !string.IsNullOrEmpty(incognitoArg) ? $"{incognitoArg} https://github.com/LAB02-Research/HASS.Agent" : "https://github.com/LAB02-Research/HASS.Agent" - }; - - testProc.StartInfo = startupArgs; - testProc.Start(); - } + FileName = browserBin, + Arguments = !string.IsNullOrEmpty(incognitoArg) ? $"{incognitoArg} https://github.com/LAB02-Research/HASS.Agent" : "https://github.com/LAB02-Research/HASS.Agent" + }; + + testProc.StartInfo = startupArgs; + testProc.Start(); } catch (Exception ex) { diff --git a/src/HASSAgent/Controls/Configuration/ExternalTools.resx b/src/HASSAgent/Controls/Configuration/ExternalTools.resx new file mode 100644 index 0000000..f624907 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/ExternalTools.resx @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + By default, HASS.Agent will launch URLs using your default browser. If you want, you can also +configure a specific browser. Additionally, you can configure the arguments used to launch +in private mode. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/General.Designer.cs b/src/HASSAgent/Controls/Configuration/General.Designer.cs similarity index 51% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/General.Designer.cs rename to src/HASSAgent/Controls/Configuration/General.Designer.cs index d04b399..053dab1 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/General.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/General.Designer.cs @@ -1,6 +1,4 @@ -using System.Globalization; - -namespace HASSAgent.Controls.Configuration +namespace HASSAgent.Controls.Configuration { partial class General { @@ -33,23 +31,23 @@ private void InitializeComponent() System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(General)); this.label36 = new System.Windows.Forms.Label(); this.label35 = new System.Windows.Forms.Label(); - this.TbDisconnectGrace = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); this.label34 = new System.Windows.Forms.Label(); this.label33 = new System.Windows.Forms.Label(); this.label32 = new System.Windows.Forms.Label(); this.label31 = new System.Windows.Forms.Label(); this.TbDeviceName = new System.Windows.Forms.TextBox(); this.label30 = new System.Windows.Forms.Label(); - ((System.ComponentModel.ISupportInitialize)(this.TbDisconnectGrace)).BeginInit(); + this.NumDisconnectGrace = new Syncfusion.Windows.Forms.Tools.NumericUpDownExt(); + ((System.ComponentModel.ISupportInitialize)(this.NumDisconnectGrace)).BeginInit(); this.SuspendLayout(); // // label36 // this.label36.AutoSize = true; - this.label36.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label36.Location = new System.Drawing.Point(99, 289); + this.label36.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label36.Location = new System.Drawing.Point(73, 350); this.label36.Name = "label36"; - this.label36.Size = new System.Drawing.Size(522, 34); + this.label36.Size = new System.Drawing.Size(550, 38); this.label36.TabIndex = 63; this.label36.Text = "HASS.Agent will wait a while before notifying you of disconnects from MQTT or HA\'" + "s API.\r\nYou can set the amount of seconds here."; @@ -57,79 +55,49 @@ private void InitializeComponent() // label35 // this.label35.AutoSize = true; - this.label35.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label35.Location = new System.Drawing.Point(200, 359); + this.label35.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label35.Location = new System.Drawing.Point(171, 428); this.label35.Name = "label35"; - this.label35.Size = new System.Drawing.Size(56, 17); + this.label35.Size = new System.Drawing.Size(58, 19); this.label35.TabIndex = 62; this.label35.Text = "seconds"; // - // TbDisconnectGrace - // - this.TbDisconnectGrace.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbDisconnectGrace.BeforeTouchSize = new System.Drawing.Size(92, 25); - this.TbDisconnectGrace.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbDisconnectGrace.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbDisconnectGrace.CurrentCultureRefresh = true; - this.TbDisconnectGrace.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbDisconnectGrace.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbDisconnectGrace.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbDisconnectGrace.IntegerValue = ((long)(60)); - this.TbDisconnectGrace.Location = new System.Drawing.Point(102, 357); - this.TbDisconnectGrace.MaxValue = ((long)(66000)); - this.TbDisconnectGrace.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbDisconnectGrace.MinValue = ((long)(1)); - this.TbDisconnectGrace.Name = "TbDisconnectGrace"; - this.TbDisconnectGrace.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbDisconnectGrace.Size = new System.Drawing.Size(92, 25); - this.TbDisconnectGrace.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbDisconnectGrace.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbDisconnectGrace.TabIndex = 60; - this.TbDisconnectGrace.Text = "60"; - this.TbDisconnectGrace.ThemeName = "Metro"; - this.TbDisconnectGrace.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbDisconnectGrace.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbDisconnectGrace.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbDisconnectGrace.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbDisconnectGrace.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbDisconnectGrace.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbDisconnectGrace.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // // label34 // this.label34.AutoSize = true; - this.label34.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label34.Location = new System.Drawing.Point(99, 335); + this.label34.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label34.Location = new System.Drawing.Point(70, 404); this.label34.Name = "label34"; - this.label34.Size = new System.Drawing.Size(165, 17); + this.label34.Size = new System.Drawing.Size(169, 19); this.label34.TabIndex = 61; this.label34.Text = "disconnected grace period"; // // label33 // this.label33.AutoSize = true; - this.label33.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label33.Location = new System.Drawing.Point(99, 186); + this.label33.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label33.Location = new System.Drawing.Point(73, 221); this.label33.Name = "label33"; - this.label33.Size = new System.Drawing.Size(555, 51); + this.label33.Size = new System.Drawing.Size(586, 57); this.label33.TabIndex = 59; this.label33.Text = resources.GetString("label33.Text"); // // label32 // this.label32.AutoSize = true; - this.label32.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label32.Location = new System.Drawing.Point(99, 80); + this.label32.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label32.Location = new System.Drawing.Point(70, 99); this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(515, 34); + this.label32.Size = new System.Drawing.Size(534, 38); this.label32.TabIndex = 58; this.label32.Text = "Device name is used to identify your machine on HA. \r\nIt\'s also used as a prefix " + "for your command/sensor names (can be changed per entity)."; // // label31 // - this.label31.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label31.Location = new System.Drawing.Point(27, 19); + this.label31.AutoEllipsis = true; + this.label31.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label31.Location = new System.Drawing.Point(70, 36); this.label31.Name = "label31"; this.label31.Size = new System.Drawing.Size(669, 44); this.label31.TabIndex = 57; @@ -140,9 +108,9 @@ private void InitializeComponent() // this.TbDeviceName.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbDeviceName.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbDeviceName.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbDeviceName.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbDeviceName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbDeviceName.Location = new System.Drawing.Point(102, 147); + this.TbDeviceName.Location = new System.Drawing.Point(73, 174); this.TbDeviceName.Name = "TbDeviceName"; this.TbDeviceName.Size = new System.Drawing.Size(358, 25); this.TbDeviceName.TabIndex = 55; @@ -150,33 +118,61 @@ private void InitializeComponent() // label30 // this.label30.AutoSize = true; - this.label30.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label30.Location = new System.Drawing.Point(99, 127); + this.label30.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label30.Location = new System.Drawing.Point(70, 152); this.label30.Name = "label30"; - this.label30.Size = new System.Drawing.Size(81, 17); + this.label30.Size = new System.Drawing.Size(85, 19); this.label30.TabIndex = 56; this.label30.Text = "device name"; // + // NumDisconnectGrace + // + this.NumDisconnectGrace.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.NumDisconnectGrace.BeforeTouchSize = new System.Drawing.Size(92, 25); + this.NumDisconnectGrace.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat; + this.NumDisconnectGrace.BorderColor = System.Drawing.SystemColors.WindowFrame; + this.NumDisconnectGrace.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumDisconnectGrace.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.NumDisconnectGrace.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.NumDisconnectGrace.Location = new System.Drawing.Point(73, 426); + this.NumDisconnectGrace.Maximum = new decimal(new int[] { + 86400, + 0, + 0, + 0}); + this.NumDisconnectGrace.MaxLength = 10; + this.NumDisconnectGrace.MetroColor = System.Drawing.SystemColors.WindowFrame; + this.NumDisconnectGrace.Name = "NumDisconnectGrace"; + this.NumDisconnectGrace.Size = new System.Drawing.Size(92, 25); + this.NumDisconnectGrace.TabIndex = 64; + this.NumDisconnectGrace.ThemeName = "Metro"; + this.NumDisconnectGrace.Value = new decimal(new int[] { + 60, + 0, + 0, + 0}); + this.NumDisconnectGrace.VisualStyle = Syncfusion.Windows.Forms.VisualStyle.Metro; + // // General // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.NumDisconnectGrace); this.Controls.Add(this.label36); this.Controls.Add(this.label35); - this.Controls.Add(this.TbDisconnectGrace); this.Controls.Add(this.label34); this.Controls.Add(this.label33); this.Controls.Add(this.label32); this.Controls.Add(this.label31); this.Controls.Add(this.TbDeviceName); this.Controls.Add(this.label30); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "General"; - this.Size = new System.Drawing.Size(700, 457); - ((System.ComponentModel.ISupportInitialize)(this.TbDisconnectGrace)).EndInit(); + this.Size = new System.Drawing.Size(740, 544); + this.Load += new System.EventHandler(this.General_Load); + ((System.ComponentModel.ISupportInitialize)(this.NumDisconnectGrace)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -191,7 +187,7 @@ private void InitializeComponent() private System.Windows.Forms.Label label32; private System.Windows.Forms.Label label31; private System.Windows.Forms.Label label30; - internal Syncfusion.Windows.Forms.Tools.IntegerTextBox TbDisconnectGrace; internal System.Windows.Forms.TextBox TbDeviceName; + internal Syncfusion.Windows.Forms.Tools.NumericUpDownExt NumDisconnectGrace; } } diff --git a/src/HASSAgent/Controls/Configuration/General.cs b/src/HASSAgent/Controls/Configuration/General.cs new file mode 100644 index 0000000..5fc11e3 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/General.cs @@ -0,0 +1,15 @@ +namespace HASSAgent.Controls.Configuration +{ + public partial class General : UserControl + { + public General() + { + InitializeComponent(); + } + + private void General_Load(object sender, EventArgs e) + { + // + } + } +} diff --git a/src/HASSAgent/Controls/Configuration/General.resx b/src/HASSAgent/Controls/Configuration/General.resx new file mode 100644 index 0000000..1893b64 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/General.resx @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Important: if you change this value, HASS.Agent will unpublish all your sensors and commands +and force a restart of itself, so they can be republished under the new device name. +Your automations and scripts will keep working. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs b/src/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs similarity index 81% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs rename to src/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs index 45c332b..1744419 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/HomeAssistantApi.Designer.cs @@ -44,10 +44,10 @@ private void InitializeComponent() // label28 // this.label28.AutoSize = true; - this.label28.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label28.Location = new System.Drawing.Point(453, 292); + this.label28.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label28.Location = new System.Drawing.Point(471, 340); this.label28.Name = "label28"; - this.label28.Size = new System.Drawing.Size(189, 13); + this.label28.Size = new System.Drawing.Size(191, 15); this.label28.TabIndex = 57; this.label28.Text = "tip: doubleclick this field to browse"; // @@ -55,9 +55,9 @@ private void InitializeComponent() // this.TbHassClientCertificate.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbHassClientCertificate.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbHassClientCertificate.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbHassClientCertificate.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbHassClientCertificate.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbHassClientCertificate.Location = new System.Drawing.Point(158, 264); + this.TbHassClientCertificate.Location = new System.Drawing.Point(177, 312); this.TbHassClientCertificate.Name = "TbHassClientCertificate"; this.TbHassClientCertificate.Size = new System.Drawing.Size(484, 25); this.TbHassClientCertificate.TabIndex = 55; @@ -66,20 +66,20 @@ private void InitializeComponent() // label29 // this.label29.AutoSize = true; - this.label29.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label29.Location = new System.Drawing.Point(46, 266); + this.label29.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label29.Location = new System.Drawing.Point(69, 314); this.label29.Name = "label29"; - this.label29.Size = new System.Drawing.Size(98, 17); + this.label29.Size = new System.Drawing.Size(103, 19); this.label29.TabIndex = 56; this.label29.Text = "client certificate"; // // CbHassAutoClientCertificate // this.CbHassAutoClientCertificate.AutoSize = true; - this.CbHassAutoClientCertificate.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbHassAutoClientCertificate.Location = new System.Drawing.Point(158, 332); + this.CbHassAutoClientCertificate.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbHassAutoClientCertificate.Location = new System.Drawing.Point(177, 378); this.CbHassAutoClientCertificate.Name = "CbHassAutoClientCertificate"; - this.CbHassAutoClientCertificate.Size = new System.Drawing.Size(257, 21); + this.CbHassAutoClientCertificate.Size = new System.Drawing.Size(269, 23); this.CbHassAutoClientCertificate.TabIndex = 54; this.CbHassAutoClientCertificate.Text = "use automatic client certificate selection"; this.CbHassAutoClientCertificate.UseVisualStyleBackColor = true; @@ -88,9 +88,9 @@ private void InitializeComponent() // this.BtnTestApi.AccessibleName = "Button"; this.BtnTestApi.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnTestApi.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnTestApi.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnTestApi.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnTestApi.Location = new System.Drawing.Point(462, 370); + this.BtnTestApi.Location = new System.Drawing.Point(481, 420); this.BtnTestApi.Name = "BtnTestApi"; this.BtnTestApi.Size = new System.Drawing.Size(180, 29); this.BtnTestApi.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -107,10 +107,10 @@ private void InitializeComponent() // // label11 // - this.label11.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label11.Location = new System.Drawing.Point(27, 19); + this.label11.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label11.Location = new System.Drawing.Point(70, 36); this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(669, 96); + this.label11.Size = new System.Drawing.Size(595, 86); this.label11.TabIndex = 53; this.label11.Text = resources.GetString("label11.Text"); // @@ -118,9 +118,9 @@ private void InitializeComponent() // this.TbHassApiToken.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbHassApiToken.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbHassApiToken.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbHassApiToken.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbHassApiToken.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbHassApiToken.Location = new System.Drawing.Point(158, 214); + this.TbHassApiToken.Location = new System.Drawing.Point(177, 262); this.TbHassApiToken.Name = "TbHassApiToken"; this.TbHassApiToken.Size = new System.Drawing.Size(484, 25); this.TbHassApiToken.TabIndex = 49; @@ -129,9 +129,9 @@ private void InitializeComponent() // this.TbHassIp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbHassIp.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbHassIp.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbHassIp.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbHassIp.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbHassIp.Location = new System.Drawing.Point(159, 165); + this.TbHassIp.Location = new System.Drawing.Point(178, 213); this.TbHassIp.Name = "TbHassIp"; this.TbHassIp.Size = new System.Drawing.Size(484, 25); this.TbHassIp.TabIndex = 48; @@ -139,20 +139,20 @@ private void InitializeComponent() // label3 // this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(76, 216); + this.label3.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(106, 264); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(62, 17); + this.label3.Size = new System.Drawing.Size(66, 19); this.label3.TabIndex = 51; this.label3.Text = "api token"; // // label2 // this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(79, 167); + this.label2.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(106, 215); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(63, 17); + this.label2.Size = new System.Drawing.Size(66, 19); this.label2.TabIndex = 50; this.label2.Text = "server uri"; // @@ -171,11 +171,10 @@ private void InitializeComponent() this.Controls.Add(this.TbHassIp); this.Controls.Add(this.label3); this.Controls.Add(this.label2); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "HomeAssistantApi"; - this.Size = new System.Drawing.Size(700, 457); + this.Size = new System.Drawing.Size(740, 544); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.cs b/src/HASSAgent/Controls/Configuration/HomeAssistantApi.cs similarity index 75% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.cs rename to src/HASSAgent/Controls/Configuration/HomeAssistantApi.cs index 8abfec9..18086a3 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.cs +++ b/src/HASSAgent/Controls/Configuration/HomeAssistantApi.cs @@ -1,13 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.HomeAssistant; +using HASSAgent.HomeAssistant; using Syncfusion.Windows.Forms; namespace HASSAgent.Controls.Configuration @@ -21,17 +12,15 @@ public HomeAssistantApi() private void TbHassClientCertificate_DoubleClick(object sender, EventArgs e) { - using (var dialog = new OpenFileDialog()) - { - dialog.CheckFileExists = true; - dialog.Multiselect = false; - dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + using var dialog = new OpenFileDialog(); + dialog.CheckFileExists = true; + dialog.Multiselect = false; + dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); - var result = dialog.ShowDialog(); - if (result != DialogResult.OK) return; + var result = dialog.ShowDialog(); + if (result != DialogResult.OK) return; - TbHassClientCertificate.Text = dialog.FileName; - } + TbHassClientCertificate.Text = dialog.FileName; } private async void BtnTestApi_Click(object sender, EventArgs e) diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.resx b/src/HASSAgent/Controls/Configuration/HomeAssistantApi.resx similarity index 50% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.resx rename to src/HASSAgent/Controls/Configuration/HomeAssistantApi.resx index a72a27a..55ae5d4 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/HomeAssistantApi.resx +++ b/src/HASSAgent/Controls/Configuration/HomeAssistantApi.resx @@ -1,64 +1,4 @@ - - - + diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.Designer.cs b/src/HASSAgent/Controls/Configuration/HotKey.Designer.cs similarity index 84% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.Designer.cs rename to src/HASSAgent/Controls/Configuration/HotKey.Designer.cs index 33764ea..78a057b 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/HotKey.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/HotKey.Designer.cs @@ -39,9 +39,9 @@ private void InitializeComponent() // this.BtnClearHotKey.AccessibleName = "Button"; this.BtnClearHotKey.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnClearHotKey.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnClearHotKey.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnClearHotKey.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnClearHotKey.Location = new System.Drawing.Point(362, 237); + this.BtnClearHotKey.Location = new System.Drawing.Point(438, 279); this.BtnClearHotKey.Name = "BtnClearHotKey"; this.BtnClearHotKey.Size = new System.Drawing.Size(102, 25); this.BtnClearHotKey.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -57,10 +57,10 @@ private void InitializeComponent() // // label16 // - this.label16.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label16.Location = new System.Drawing.Point(27, 19); + this.label16.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label16.Location = new System.Drawing.Point(70, 36); this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(664, 62); + this.label16.Size = new System.Drawing.Size(605, 62); this.label16.TabIndex = 17; this.label16.Text = "An easy way to pull up your quick actions is to use a global hotkey.\r\n\r\nThis way," + " whatever you\'re doing on your machine, you can always interact with Home Assist" + @@ -70,9 +70,9 @@ private void InitializeComponent() // this.TbQuickActionsHotkey.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbQuickActionsHotkey.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbQuickActionsHotkey.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbQuickActionsHotkey.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbQuickActionsHotkey.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbQuickActionsHotkey.Location = new System.Drawing.Point(125, 237); + this.TbQuickActionsHotkey.Location = new System.Drawing.Point(201, 279); this.TbQuickActionsHotkey.Name = "TbQuickActionsHotkey"; this.TbQuickActionsHotkey.Size = new System.Drawing.Size(231, 25); this.TbQuickActionsHotkey.TabIndex = 16; @@ -80,10 +80,10 @@ private void InitializeComponent() // CbEnableQuickActionsHotkey // this.CbEnableQuickActionsHotkey.AutoSize = true; - this.CbEnableQuickActionsHotkey.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbEnableQuickActionsHotkey.Location = new System.Drawing.Point(125, 169); + this.CbEnableQuickActionsHotkey.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbEnableQuickActionsHotkey.Location = new System.Drawing.Point(201, 181); this.CbEnableQuickActionsHotkey.Name = "CbEnableQuickActionsHotkey"; - this.CbEnableQuickActionsHotkey.Size = new System.Drawing.Size(187, 21); + this.CbEnableQuickActionsHotkey.Size = new System.Drawing.Size(197, 23); this.CbEnableQuickActionsHotkey.TabIndex = 15; this.CbEnableQuickActionsHotkey.Text = "enable quick actions hotkey"; this.CbEnableQuickActionsHotkey.UseVisualStyleBackColor = true; @@ -91,10 +91,10 @@ private void InitializeComponent() // label5 // this.label5.AutoSize = true; - this.label5.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label5.Location = new System.Drawing.Point(122, 217); + this.label5.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label5.Location = new System.Drawing.Point(201, 257); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(122, 17); + this.label5.Size = new System.Drawing.Size(131, 19); this.label5.TabIndex = 14; this.label5.Text = "hotkey combination"; // @@ -108,11 +108,10 @@ private void InitializeComponent() this.Controls.Add(this.TbQuickActionsHotkey); this.Controls.Add(this.CbEnableQuickActionsHotkey); this.Controls.Add(this.label5); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "HotKey"; - this.Size = new System.Drawing.Size(700, 457); + this.Size = new System.Drawing.Size(740, 544); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/HASSAgent/Controls/Configuration/HotKey.cs b/src/HASSAgent/Controls/Configuration/HotKey.cs new file mode 100644 index 0000000..89e4233 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/HotKey.cs @@ -0,0 +1,10 @@ +namespace HASSAgent.Controls.Configuration +{ + public partial class HotKey : UserControl + { + public HotKey() + { + InitializeComponent(); + } + } +} diff --git a/src/HASSAgent/Controls/Configuration/HotKey.resx b/src/HASSAgent/Controls/Configuration/HotKey.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/HotKey.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs b/src/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs similarity index 62% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs rename to src/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs index 5d2cbc2..6dc2dc5 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/LocalStorage.Designer.cs @@ -1,6 +1,4 @@ -using System.Globalization; - -namespace HASSAgent.Controls.Configuration +namespace HASSAgent.Controls.Configuration { partial class LocalStorage { @@ -35,18 +33,18 @@ private void InitializeComponent() this.TbImageCacheLocation = new System.Windows.Forms.TextBox(); this.label21 = new System.Windows.Forms.Label(); this.label20 = new System.Windows.Forms.Label(); - this.TbIntImageRetention = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); this.label19 = new System.Windows.Forms.Label(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntImageRetention)).BeginInit(); + this.NumImageRetention = new Syncfusion.Windows.Forms.Tools.NumericUpDownExt(); + ((System.ComponentModel.ISupportInitialize)(this.NumImageRetention)).BeginInit(); this.SuspendLayout(); // // BtnClearImageCache // this.BtnClearImageCache.AccessibleName = "Button"; this.BtnClearImageCache.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnClearImageCache.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnClearImageCache.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnClearImageCache.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnClearImageCache.Location = new System.Drawing.Point(436, 92); + this.BtnClearImageCache.Location = new System.Drawing.Point(443, 154); this.BtnClearImageCache.Name = "BtnClearImageCache"; this.BtnClearImageCache.Size = new System.Drawing.Size(197, 25); this.BtnClearImageCache.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -65,9 +63,9 @@ private void InitializeComponent() // this.BtnOpenImageCache.AccessibleName = "Button"; this.BtnOpenImageCache.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnOpenImageCache.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnOpenImageCache.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnOpenImageCache.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnOpenImageCache.Location = new System.Drawing.Point(508, 203); + this.BtnOpenImageCache.Location = new System.Drawing.Point(515, 265); this.BtnOpenImageCache.Name = "BtnOpenImageCache"; this.BtnOpenImageCache.Size = new System.Drawing.Size(125, 25); this.BtnOpenImageCache.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -86,9 +84,9 @@ private void InitializeComponent() // this.TbImageCacheLocation.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbImageCacheLocation.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbImageCacheLocation.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbImageCacheLocation.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbImageCacheLocation.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbImageCacheLocation.Location = new System.Drawing.Point(94, 172); + this.TbImageCacheLocation.Location = new System.Drawing.Point(101, 234); this.TbImageCacheLocation.Name = "TbImageCacheLocation"; this.TbImageCacheLocation.ReadOnly = true; this.TbImageCacheLocation.Size = new System.Drawing.Size(539, 25); @@ -97,83 +95,79 @@ private void InitializeComponent() // label21 // this.label21.AutoSize = true; - this.label21.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label21.Location = new System.Drawing.Point(91, 152); + this.label21.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label21.Location = new System.Drawing.Point(101, 212); this.label21.Name = "label21"; - this.label21.Size = new System.Drawing.Size(131, 17); + this.label21.Size = new System.Drawing.Size(136, 19); this.label21.TabIndex = 33; this.label21.Text = "image cache location"; // // label20 // this.label20.AutoSize = true; - this.label20.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label20.Location = new System.Drawing.Point(170, 96); + this.label20.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label20.Location = new System.Drawing.Point(190, 158); this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(35, 17); + this.label20.Size = new System.Drawing.Size(37, 19); this.label20.TabIndex = 32; this.label20.Text = "days"; // - // TbIntImageRetention - // - this.TbIntImageRetention.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntImageRetention.BeforeTouchSize = new System.Drawing.Size(67, 25); - this.TbIntImageRetention.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntImageRetention.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbIntImageRetention.CurrentCultureRefresh = true; - this.TbIntImageRetention.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntImageRetention.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbIntImageRetention.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntImageRetention.IntegerValue = ((long)(7)); - this.TbIntImageRetention.Location = new System.Drawing.Point(94, 92); - this.TbIntImageRetention.MaxValue = ((long)(365)); - this.TbIntImageRetention.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntImageRetention.MinValue = ((long)(0)); - this.TbIntImageRetention.Name = "TbIntImageRetention"; - this.TbIntImageRetention.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntImageRetention.Size = new System.Drawing.Size(67, 25); - this.TbIntImageRetention.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbIntImageRetention.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbIntImageRetention.TabIndex = 31; - this.TbIntImageRetention.Text = "7"; - this.TbIntImageRetention.ThemeName = "Metro"; - this.TbIntImageRetention.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntImageRetention.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntImageRetention.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntImageRetention.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntImageRetention.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntImageRetention.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntImageRetention.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // // label19 // - this.label19.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label19.Location = new System.Drawing.Point(27, 19); + this.label19.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label19.Location = new System.Drawing.Point(70, 36); this.label19.Name = "label19"; this.label19.Size = new System.Drawing.Size(634, 46); this.label19.TabIndex = 30; this.label19.Text = "Images shown in notifications have to be temporarily stored locally. You can conf" + "igure the amount of days they should be kept before HASS.Agent deletes them. Ent" + "er \'0\' to keep them permanently."; + // + // NumImageRetention + // + this.NumImageRetention.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.NumImageRetention.BeforeTouchSize = new System.Drawing.Size(83, 25); + this.NumImageRetention.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat; + this.NumImageRetention.BorderColor = System.Drawing.SystemColors.WindowFrame; + this.NumImageRetention.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumImageRetention.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.NumImageRetention.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.NumImageRetention.Location = new System.Drawing.Point(101, 156); + this.NumImageRetention.Maximum = new decimal(new int[] { + 3650, + 0, + 0, + 0}); + this.NumImageRetention.MaxLength = 10; + this.NumImageRetention.MetroColor = System.Drawing.SystemColors.WindowFrame; + this.NumImageRetention.Name = "NumImageRetention"; + this.NumImageRetention.Size = new System.Drawing.Size(83, 25); + this.NumImageRetention.TabIndex = 37; + this.NumImageRetention.ThemeName = "Metro"; + this.NumImageRetention.Value = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.NumImageRetention.VisualStyle = Syncfusion.Windows.Forms.VisualStyle.Metro; // // LocalStorage // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.NumImageRetention); this.Controls.Add(this.BtnClearImageCache); this.Controls.Add(this.BtnOpenImageCache); this.Controls.Add(this.TbImageCacheLocation); this.Controls.Add(this.label21); this.Controls.Add(this.label20); - this.Controls.Add(this.TbIntImageRetention); this.Controls.Add(this.label19); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "LocalStorage"; - this.Size = new System.Drawing.Size(700, 457); - ((System.ComponentModel.ISupportInitialize)(this.TbIntImageRetention)).EndInit(); + this.Size = new System.Drawing.Size(740, 544); + ((System.ComponentModel.ISupportInitialize)(this.NumImageRetention)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -186,6 +180,6 @@ private void InitializeComponent() internal Syncfusion.WinForms.Controls.SfButton BtnClearImageCache; internal Syncfusion.WinForms.Controls.SfButton BtnOpenImageCache; internal System.Windows.Forms.TextBox TbImageCacheLocation; - internal Syncfusion.Windows.Forms.Tools.IntegerTextBox TbIntImageRetention; + internal Syncfusion.Windows.Forms.Tools.NumericUpDownExt NumImageRetention; } } diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.cs b/src/HASSAgent/Controls/Configuration/LocalStorage.cs similarity index 67% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.cs rename to src/HASSAgent/Controls/Configuration/LocalStorage.cs index 29ee52e..39c7cb5 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/LocalStorage.cs +++ b/src/HASSAgent/Controls/Configuration/LocalStorage.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Diagnostics; -using System.Drawing; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; +using System.Diagnostics; using HASSAgent.Functions; using Syncfusion.Windows.Forms; @@ -20,8 +9,6 @@ public partial class LocalStorage : UserControl public LocalStorage() { InitializeComponent(); - - TbIntImageRetention.Culture = CultureInfo.InstalledUICulture; } private async void BtnClearImageCache_Click(object sender, EventArgs e) @@ -42,7 +29,7 @@ private void BtnOpenImageCache_Click(object sender, EventArgs e) if (string.IsNullOrEmpty(Variables.ImageCachePath)) return; if (!Directory.Exists(Variables.ImageCachePath)) Directory.CreateDirectory(Variables.ImageCachePath); - Process.Start("C:\\Windows\\explorer.exe", Variables.ImageCachePath); + HelperFunctions.OpenLocalFolder(Variables.ImageCachePath); } } } diff --git a/src/HASSAgent/Controls/Configuration/LocalStorage.resx b/src/HASSAgent/Controls/Configuration/LocalStorage.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/LocalStorage.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASSAgent/Controls/Configuration/Logging.Designer.cs b/src/HASSAgent/Controls/Configuration/Logging.Designer.cs new file mode 100644 index 0000000..1fd7eab --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Logging.Designer.cs @@ -0,0 +1,100 @@ +namespace HASSAgent.Controls.Configuration +{ + partial class Logging + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Logging)); + this.label23 = new System.Windows.Forms.Label(); + this.CbExtendedLogging = new System.Windows.Forms.CheckBox(); + this.BtnShowLogs = new Syncfusion.WinForms.Controls.SfButton(); + this.SuspendLayout(); + // + // label23 + // + this.label23.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label23.Location = new System.Drawing.Point(70, 36); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(601, 82); + this.label23.TabIndex = 31; + this.label23.Text = resources.GetString("label23.Text"); + // + // CbExtendedLogging + // + this.CbExtendedLogging.AutoSize = true; + this.CbExtendedLogging.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbExtendedLogging.Location = new System.Drawing.Point(70, 175); + this.CbExtendedLogging.Name = "CbExtendedLogging"; + this.CbExtendedLogging.Size = new System.Drawing.Size(178, 23); + this.CbExtendedLogging.TabIndex = 30; + this.CbExtendedLogging.Text = "enable extended logging"; + this.CbExtendedLogging.UseVisualStyleBackColor = true; + // + // BtnShowLogs + // + this.BtnShowLogs.AccessibleName = "Button"; + this.BtnShowLogs.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnShowLogs.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Location = new System.Drawing.Point(70, 461); + this.BtnShowLogs.Name = "BtnShowLogs"; + this.BtnShowLogs.Size = new System.Drawing.Size(601, 31); + this.BtnShowLogs.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnShowLogs.TabIndex = 47; + this.BtnShowLogs.Text = "open logs folder"; + this.BtnShowLogs.UseVisualStyleBackColor = false; + this.BtnShowLogs.Click += new System.EventHandler(this.BtnShowLogs_Click); + // + // Logging + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.BtnShowLogs); + this.Controls.Add(this.label23); + this.Controls.Add(this.CbExtendedLogging); + this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "Logging"; + this.Size = new System.Drawing.Size(740, 544); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.Label label23; + internal System.Windows.Forms.CheckBox CbExtendedLogging; + internal Syncfusion.WinForms.Controls.SfButton BtnShowLogs; + } +} diff --git a/src/HASSAgent/Controls/Configuration/Logging.cs b/src/HASSAgent/Controls/Configuration/Logging.cs new file mode 100644 index 0000000..5358632 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Logging.cs @@ -0,0 +1,15 @@ +using System.Diagnostics; +using HASSAgent.Functions; + +namespace HASSAgent.Controls.Configuration +{ + public partial class Logging : UserControl + { + public Logging() + { + InitializeComponent(); + } + + private void BtnShowLogs_Click(object sender, EventArgs e) => HelperFunctions.OpenLocalFolder(Variables.LogPath); + } +} diff --git a/src/HASSAgent/Controls/Configuration/Logging.resx b/src/HASSAgent/Controls/Configuration/Logging.resx new file mode 100644 index 0000000..e0f5b33 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Logging.resx @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Extended logging provides more verbose and in-depth logging, in case the default logging isn't sufficient. Please note that enabling this can cause the logfiles to grow large, and should only be used when you suspect something's wrong with HASS.Agent itself or when asked by the developers. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.Designer.cs b/src/HASSAgent/Controls/Configuration/MQTT.Designer.cs similarity index 68% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.Designer.cs rename to src/HASSAgent/Controls/Configuration/MQTT.Designer.cs index 303350e..2cbe667 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/MQTT.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/MQTT.Designer.cs @@ -1,6 +1,4 @@ -using System.Globalization; - -namespace HASSAgent.Controls.Configuration +namespace HASSAgent.Controls.Configuration { partial class MQTT { @@ -42,7 +40,6 @@ private void InitializeComponent() this.label13 = new System.Windows.Forms.Label(); this.TbMqttDiscoveryPrefix = new System.Windows.Forms.TextBox(); this.label10 = new System.Windows.Forms.Label(); - this.TbIntMqttPort = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); this.TbMqttPassword = new System.Windows.Forms.TextBox(); this.TbMqttUsername = new System.Windows.Forms.TextBox(); this.TbMqttAddress = new System.Windows.Forms.TextBox(); @@ -54,16 +51,19 @@ private void InitializeComponent() this.label1 = new System.Windows.Forms.Label(); this.TbMqttClientId = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntMqttPort)).BeginInit(); + this.NumMqttPort = new Syncfusion.Windows.Forms.Tools.NumericUpDownExt(); + this.PbShow = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.NumMqttPort)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PbShow)).BeginInit(); this.SuspendLayout(); // // label27 // this.label27.AutoSize = true; - this.label27.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label27.Location = new System.Drawing.Point(400, 203); + this.label27.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label27.Location = new System.Drawing.Point(413, 243); this.label27.Name = "label27"; - this.label27.Size = new System.Drawing.Size(203, 13); + this.label27.Size = new System.Drawing.Size(205, 15); this.label27.TabIndex = 64; this.label27.Text = "tip: doubleclick these fields to browse"; // @@ -71,9 +71,9 @@ private void InitializeComponent() // this.TbMqttClientCertificate.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttClientCertificate.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttClientCertificate.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttClientCertificate.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttClientCertificate.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttClientCertificate.Location = new System.Drawing.Point(403, 175); + this.TbMqttClientCertificate.Location = new System.Drawing.Point(413, 215); this.TbMqttClientCertificate.Name = "TbMqttClientCertificate"; this.TbMqttClientCertificate.Size = new System.Drawing.Size(268, 25); this.TbMqttClientCertificate.TabIndex = 62; @@ -82,10 +82,10 @@ private void InitializeComponent() // label26 // this.label26.AutoSize = true; - this.label26.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label26.Location = new System.Drawing.Point(400, 156); + this.label26.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label26.Location = new System.Drawing.Point(410, 193); this.label26.Name = "label26"; - this.label26.Size = new System.Drawing.Size(98, 17); + this.label26.Size = new System.Drawing.Size(103, 19); this.label26.TabIndex = 63; this.label26.Text = "client certificate"; // @@ -93,9 +93,9 @@ private void InitializeComponent() // this.TbMqttRootCertificate.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttRootCertificate.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttRootCertificate.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttRootCertificate.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttRootCertificate.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttRootCertificate.Location = new System.Drawing.Point(403, 123); + this.TbMqttRootCertificate.Location = new System.Drawing.Point(413, 155); this.TbMqttRootCertificate.Name = "TbMqttRootCertificate"; this.TbMqttRootCertificate.Size = new System.Drawing.Size(268, 25); this.TbMqttRootCertificate.TabIndex = 60; @@ -104,20 +104,20 @@ private void InitializeComponent() // label25 // this.label25.AutoSize = true; - this.label25.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label25.Location = new System.Drawing.Point(400, 104); + this.label25.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label25.Location = new System.Drawing.Point(410, 133); this.label25.Name = "label25"; - this.label25.Size = new System.Drawing.Size(93, 17); + this.label25.Size = new System.Drawing.Size(97, 19); this.label25.TabIndex = 61; this.label25.Text = "root certificate"; // // CbUseRetainFlag // this.CbUseRetainFlag.AutoSize = true; - this.CbUseRetainFlag.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbUseRetainFlag.Location = new System.Drawing.Point(403, 313); + this.CbUseRetainFlag.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbUseRetainFlag.Location = new System.Drawing.Point(410, 345); this.CbUseRetainFlag.Name = "CbUseRetainFlag"; - this.CbUseRetainFlag.Size = new System.Drawing.Size(110, 21); + this.CbUseRetainFlag.Size = new System.Drawing.Size(114, 23); this.CbUseRetainFlag.TabIndex = 59; this.CbUseRetainFlag.Text = "use retain flag"; this.CbUseRetainFlag.UseVisualStyleBackColor = true; @@ -125,10 +125,10 @@ private void InitializeComponent() // CbAllowUntrustedCertificates // this.CbAllowUntrustedCertificates.AutoSize = true; - this.CbAllowUntrustedCertificates.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbAllowUntrustedCertificates.Location = new System.Drawing.Point(403, 261); + this.CbAllowUntrustedCertificates.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbAllowUntrustedCertificates.Location = new System.Drawing.Point(410, 287); this.CbAllowUntrustedCertificates.Name = "CbAllowUntrustedCertificates"; - this.CbAllowUntrustedCertificates.Size = new System.Drawing.Size(182, 21); + this.CbAllowUntrustedCertificates.Size = new System.Drawing.Size(191, 23); this.CbAllowUntrustedCertificates.TabIndex = 58; this.CbAllowUntrustedCertificates.Text = "allow untrusted certificates"; this.CbAllowUntrustedCertificates.UseVisualStyleBackColor = true; @@ -137,9 +137,9 @@ private void InitializeComponent() // this.BtnMqttClearConfig.AccessibleName = "Button"; this.BtnMqttClearConfig.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnMqttClearConfig.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnMqttClearConfig.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnMqttClearConfig.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnMqttClearConfig.Location = new System.Drawing.Point(443, 438); + this.BtnMqttClearConfig.Location = new System.Drawing.Point(496, 499); this.BtnMqttClearConfig.Name = "BtnMqttClearConfig"; this.BtnMqttClearConfig.Size = new System.Drawing.Size(228, 31); this.BtnMqttClearConfig.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -157,19 +157,19 @@ private void InitializeComponent() // label14 // this.label14.AutoSize = true; - this.label14.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label14.Location = new System.Drawing.Point(42, 370); + this.label14.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label14.Location = new System.Drawing.Point(252, 421); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(135, 13); + this.label14.Size = new System.Drawing.Size(138, 15); this.label14.TabIndex = 56; this.label14.Text = "(leave default if not sure)"; // // label13 // - this.label13.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label13.Location = new System.Drawing.Point(27, 19); + this.label13.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label13.Location = new System.Drawing.Point(70, 36); this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(670, 44); + this.label13.Size = new System.Drawing.Size(589, 44); this.label13.TabIndex = 55; this.label13.Text = "Commands and sensors are sent through MQTT. Please provide credentials for your s" + "erver. If you\'re using the HA addon, you can probably use the preset address.\r\n"; @@ -178,10 +178,9 @@ private void InitializeComponent() // this.TbMqttDiscoveryPrefix.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttDiscoveryPrefix.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttDiscoveryPrefix.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttDiscoveryPrefix.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttDiscoveryPrefix.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttDiscoveryPrefix.Location = new System.Drawing.Point(45, 342); - this.TbMqttDiscoveryPrefix.MaxLength = 100; + this.TbMqttDiscoveryPrefix.Location = new System.Drawing.Point(55, 417); this.TbMqttDiscoveryPrefix.Name = "TbMqttDiscoveryPrefix"; this.TbMqttDiscoveryPrefix.Size = new System.Drawing.Size(191, 25); this.TbMqttDiscoveryPrefix.TabIndex = 53; @@ -189,51 +188,20 @@ private void InitializeComponent() // label10 // this.label10.AutoSize = true; - this.label10.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label10.Location = new System.Drawing.Point(44, 322); + this.label10.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label10.Location = new System.Drawing.Point(52, 395); this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(100, 17); + this.label10.Size = new System.Drawing.Size(103, 19); this.label10.TabIndex = 54; this.label10.Text = "discovery prefix"; // - // TbIntMqttPort - // - this.TbIntMqttPort.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntMqttPort.BeforeTouchSize = new System.Drawing.Size(92, 25); - this.TbIntMqttPort.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbIntMqttPort.CurrentCultureRefresh = true; - this.TbIntMqttPort.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbIntMqttPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.IntegerValue = ((long)(1883)); - this.TbIntMqttPort.Location = new System.Drawing.Point(80, 166); - this.TbIntMqttPort.MaxValue = ((long)(66000)); - this.TbIntMqttPort.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.MinValue = ((long)(1)); - this.TbIntMqttPort.Name = "TbIntMqttPort"; - this.TbIntMqttPort.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.Size = new System.Drawing.Size(92, 25); - this.TbIntMqttPort.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbIntMqttPort.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbIntMqttPort.TabIndex = 45; - this.TbIntMqttPort.Text = "1,883"; - this.TbIntMqttPort.ThemeName = "Metro"; - this.TbIntMqttPort.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntMqttPort.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // // TbMqttPassword // this.TbMqttPassword.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttPassword.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttPassword.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttPassword.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttPassword.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttPassword.Location = new System.Drawing.Point(45, 283); + this.TbMqttPassword.Location = new System.Drawing.Point(55, 345); this.TbMqttPassword.Name = "TbMqttPassword"; this.TbMqttPassword.Size = new System.Drawing.Size(191, 25); this.TbMqttPassword.TabIndex = 49; @@ -243,9 +211,9 @@ private void InitializeComponent() // this.TbMqttUsername.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttUsername.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttUsername.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttUsername.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttUsername.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttUsername.Location = new System.Drawing.Point(47, 231); + this.TbMqttUsername.Location = new System.Drawing.Point(57, 287); this.TbMqttUsername.Name = "TbMqttUsername"; this.TbMqttUsername.Size = new System.Drawing.Size(191, 25); this.TbMqttUsername.TabIndex = 48; @@ -254,9 +222,9 @@ private void InitializeComponent() // this.TbMqttAddress.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttAddress.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttAddress.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttAddress.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttAddress.Location = new System.Drawing.Point(47, 123); + this.TbMqttAddress.Location = new System.Drawing.Point(57, 155); this.TbMqttAddress.Name = "TbMqttAddress"; this.TbMqttAddress.Size = new System.Drawing.Size(259, 25); this.TbMqttAddress.TabIndex = 44; @@ -264,10 +232,10 @@ private void InitializeComponent() // CbMqttTls // this.CbMqttTls.AutoSize = true; - this.CbMqttTls.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbMqttTls.Location = new System.Drawing.Point(195, 171); + this.CbMqttTls.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbMqttTls.Location = new System.Drawing.Point(197, 215); this.CbMqttTls.Name = "CbMqttTls"; - this.CbMqttTls.Size = new System.Drawing.Size(47, 21); + this.CbMqttTls.Size = new System.Drawing.Size(49, 23); this.CbMqttTls.TabIndex = 46; this.CbMqttTls.Text = "TLS"; this.CbMqttTls.UseVisualStyleBackColor = true; @@ -275,80 +243,122 @@ private void InitializeComponent() // label9 // this.label9.AutoSize = true; - this.label9.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label9.Location = new System.Drawing.Point(44, 263); + this.label9.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label9.Location = new System.Drawing.Point(54, 323); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(65, 17); + this.label9.Size = new System.Drawing.Size(67, 19); this.label9.TabIndex = 52; this.label9.Text = "password"; // // label8 // this.label8.AutoSize = true; - this.label8.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label8.Location = new System.Drawing.Point(44, 212); + this.label8.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label8.Location = new System.Drawing.Point(54, 265); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(65, 17); + this.label8.Size = new System.Drawing.Size(69, 19); this.label8.TabIndex = 51; this.label8.Text = "username"; // // label7 // this.label7.AutoSize = true; - this.label7.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label7.Location = new System.Drawing.Point(42, 169); + this.label7.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label7.Location = new System.Drawing.Point(52, 215); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(33, 17); + this.label7.Size = new System.Drawing.Size(35, 19); this.label7.TabIndex = 50; this.label7.Text = "port"; // // label6 // this.label6.AutoSize = true; - this.label6.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label6.Location = new System.Drawing.Point(44, 103); + this.label6.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label6.Location = new System.Drawing.Point(54, 133); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(191, 17); + this.label6.Size = new System.Drawing.Size(197, 19); this.label6.TabIndex = 47; this.label6.Text = "broker ip address or hostname"; // // label1 // this.label1.AutoSize = true; - this.label1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(44, 443); + this.label1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(252, 479); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(134, 13); - this.label1.TabIndex = 67; + this.label1.Size = new System.Drawing.Size(142, 15); + this.label1.TabIndex = 70; this.label1.Text = "(leave empty for random)"; // // TbMqttClientId // this.TbMqttClientId.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttClientId.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttClientId.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttClientId.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttClientId.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttClientId.Location = new System.Drawing.Point(45, 415); + this.TbMqttClientId.Location = new System.Drawing.Point(55, 475); this.TbMqttClientId.MaxLength = 100; this.TbMqttClientId.Name = "TbMqttClientId"; this.TbMqttClientId.Size = new System.Drawing.Size(191, 25); - this.TbMqttClientId.TabIndex = 65; + this.TbMqttClientId.TabIndex = 68; // // label2 // this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(44, 395); + this.label2.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(52, 453); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(53, 17); - this.label2.TabIndex = 66; + this.label2.Size = new System.Drawing.Size(56, 19); + this.label2.TabIndex = 69; this.label2.Text = "client id"; // + // NumMqttPort + // + this.NumMqttPort.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.NumMqttPort.BeforeTouchSize = new System.Drawing.Size(83, 25); + this.NumMqttPort.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat; + this.NumMqttPort.BorderColor = System.Drawing.SystemColors.WindowFrame; + this.NumMqttPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumMqttPort.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.NumMqttPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.NumMqttPort.Location = new System.Drawing.Point(91, 213); + this.NumMqttPort.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.NumMqttPort.MaxLength = 10; + this.NumMqttPort.MetroColor = System.Drawing.SystemColors.WindowFrame; + this.NumMqttPort.Name = "NumMqttPort"; + this.NumMqttPort.Size = new System.Drawing.Size(83, 25); + this.NumMqttPort.TabIndex = 71; + this.NumMqttPort.ThemeName = "Metro"; + this.NumMqttPort.Value = new decimal(new int[] { + 1883, + 0, + 0, + 0}); + this.NumMqttPort.VisualStyle = Syncfusion.Windows.Forms.VisualStyle.Metro; + // + // PbShow + // + this.PbShow.Cursor = System.Windows.Forms.Cursors.Hand; + this.PbShow.Image = global::HASSAgent.Properties.Resources.show_24; + this.PbShow.Location = new System.Drawing.Point(252, 346); + this.PbShow.Name = "PbShow"; + this.PbShow.Size = new System.Drawing.Size(24, 24); + this.PbShow.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.PbShow.TabIndex = 100; + this.PbShow.TabStop = false; + this.PbShow.Click += new System.EventHandler(this.PbShow_Click); + // // MQTT // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.PbShow); + this.Controls.Add(this.NumMqttPort); this.Controls.Add(this.label1); this.Controls.Add(this.TbMqttClientId); this.Controls.Add(this.label2); @@ -364,7 +374,6 @@ private void InitializeComponent() this.Controls.Add(this.label13); this.Controls.Add(this.TbMqttDiscoveryPrefix); this.Controls.Add(this.label10); - this.Controls.Add(this.TbIntMqttPort); this.Controls.Add(this.TbMqttPassword); this.Controls.Add(this.TbMqttUsername); this.Controls.Add(this.TbMqttAddress); @@ -373,13 +382,13 @@ private void InitializeComponent() this.Controls.Add(this.label8); this.Controls.Add(this.label7); this.Controls.Add(this.label6); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "MQTT"; - this.Size = new System.Drawing.Size(700, 486); + this.Size = new System.Drawing.Size(740, 544); this.Load += new System.EventHandler(this.MQTT_Load); - ((System.ComponentModel.ISupportInitialize)(this.TbIntMqttPort)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NumMqttPort)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PbShow)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -403,7 +412,6 @@ private void InitializeComponent() internal System.Windows.Forms.CheckBox CbAllowUntrustedCertificates; internal Syncfusion.WinForms.Controls.SfButton BtnMqttClearConfig; internal System.Windows.Forms.TextBox TbMqttDiscoveryPrefix; - internal Syncfusion.Windows.Forms.Tools.IntegerTextBox TbIntMqttPort; internal System.Windows.Forms.TextBox TbMqttPassword; internal System.Windows.Forms.TextBox TbMqttUsername; internal System.Windows.Forms.TextBox TbMqttAddress; @@ -411,5 +419,7 @@ private void InitializeComponent() private System.Windows.Forms.Label label1; internal System.Windows.Forms.TextBox TbMqttClientId; private System.Windows.Forms.Label label2; + internal Syncfusion.Windows.Forms.Tools.NumericUpDownExt NumMqttPort; + private PictureBox PbShow; } } diff --git a/src/HASSAgent/Controls/Configuration/MQTT.cs b/src/HASSAgent/Controls/Configuration/MQTT.cs new file mode 100644 index 0000000..2dc057c --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/MQTT.cs @@ -0,0 +1,59 @@ +namespace HASSAgent.Controls.Configuration +{ + // ReSharper disable once InconsistentNaming + public partial class MQTT : UserControl + { + public MQTT() + { + InitializeComponent(); + } + + private void TbMqttRootCertificate_DoubleClick(object sender, EventArgs e) + { + using var dialog = new OpenFileDialog(); + dialog.CheckFileExists = true; + dialog.Multiselect = false; + dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + + var result = dialog.ShowDialog(); + if (result != DialogResult.OK) return; + + TbMqttRootCertificate.Text = dialog.FileName; + } + + private void TbMqttClientCertificate_DoubleClick(object sender, EventArgs e) + { + using var dialog = new OpenFileDialog(); + dialog.CheckFileExists = true; + dialog.Multiselect = false; + dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + + var result = dialog.ShowDialog(); + if (result != DialogResult.OK) return; + + TbMqttClientCertificate.Text = dialog.FileName; + } + + private void BtnMqttClearConfig_Click(object sender, EventArgs e) + { + TbMqttAddress.Text = string.Empty; + NumMqttPort.Value = 1883; + CbMqttTls.CheckState = CheckState.Unchecked; + TbMqttUsername.Text = string.Empty; + TbMqttPassword.Text = string.Empty; + TbMqttDiscoveryPrefix.Text = "homeassistant"; + TbMqttClientId.Text = string.Empty; + TbMqttRootCertificate.Text = string.Empty; + TbMqttClientCertificate.Text = string.Empty; + CbAllowUntrustedCertificates.CheckState = CheckState.Checked; + CbUseRetainFlag.CheckState = CheckState.Checked; + } + + private void MQTT_Load(object sender, EventArgs e) + { + // + } + + private void PbShow_Click(object sender, EventArgs e) => TbMqttPassword.UseSystemPasswordChar = !TbMqttPassword.UseSystemPasswordChar; + } +} diff --git a/src/HASSAgent/Controls/Configuration/MQTT.resx b/src/HASSAgent/Controls/Configuration/MQTT.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/MQTT.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASSAgent/Controls/Configuration/Notifications.Designer.cs b/src/HASSAgent/Controls/Configuration/Notifications.Designer.cs new file mode 100644 index 0000000..8257c9f --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Notifications.Designer.cs @@ -0,0 +1,209 @@ +namespace HASSAgent.Controls.Configuration +{ + partial class Notifications + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Notifications)); + this.label18 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.BtnNotificationsReadme = new Syncfusion.WinForms.Controls.SfButton(); + this.label1 = new System.Windows.Forms.Label(); + this.CbAcceptNotifications = new System.Windows.Forms.CheckBox(); + this.NumNotificationApiPort = new Syncfusion.Windows.Forms.Tools.NumericUpDownExt(); + this.BtnSendTestNotification = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnExecutePortReservation = new Syncfusion.WinForms.Controls.SfButton(); + ((System.ComponentModel.ISupportInitialize)(this.NumNotificationApiPort)).BeginInit(); + this.SuspendLayout(); + // + // label18 + // + this.label18.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label18.Location = new System.Drawing.Point(70, 364); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(416, 128); + this.label18.TabIndex = 37; + this.label18.Text = resources.GetString("label18.Text"); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label12.Location = new System.Drawing.Point(70, 36); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(526, 19); + this.label12.TabIndex = 36; + this.label12.Text = "HASS.Agent can receive notifications from Home Assistant, using text and/or image" + + "s."; + // + // BtnNotificationsReadme + // + this.BtnNotificationsReadme.AccessibleName = "Button"; + this.BtnNotificationsReadme.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnNotificationsReadme.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnNotificationsReadme.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnNotificationsReadme.Location = new System.Drawing.Point(493, 497); + this.BtnNotificationsReadme.Name = "BtnNotificationsReadme"; + this.BtnNotificationsReadme.Size = new System.Drawing.Size(228, 31); + this.BtnNotificationsReadme.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnNotificationsReadme.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnNotificationsReadme.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnNotificationsReadme.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnNotificationsReadme.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnNotificationsReadme.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnNotificationsReadme.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnNotificationsReadme.TabIndex = 35; + this.BtnNotificationsReadme.Text = "notifications documentation"; + this.BtnNotificationsReadme.UseVisualStyleBackColor = false; + this.BtnNotificationsReadme.Click += new System.EventHandler(this.BtnNotificationsReadme_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(220, 126); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(35, 19); + this.label1.TabIndex = 34; + this.label1.Text = "port"; + // + // CbAcceptNotifications + // + this.CbAcceptNotifications.AutoSize = true; + this.CbAcceptNotifications.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbAcceptNotifications.Location = new System.Drawing.Point(376, 126); + this.CbAcceptNotifications.Name = "CbAcceptNotifications"; + this.CbAcceptNotifications.Size = new System.Drawing.Size(145, 23); + this.CbAcceptNotifications.TabIndex = 33; + this.CbAcceptNotifications.Text = "accept notifications"; + this.CbAcceptNotifications.UseVisualStyleBackColor = true; + // + // NumNotificationApiPort + // + this.NumNotificationApiPort.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.NumNotificationApiPort.BeforeTouchSize = new System.Drawing.Size(83, 25); + this.NumNotificationApiPort.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat; + this.NumNotificationApiPort.BorderColor = System.Drawing.SystemColors.WindowFrame; + this.NumNotificationApiPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumNotificationApiPort.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.NumNotificationApiPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.NumNotificationApiPort.Location = new System.Drawing.Point(261, 124); + this.NumNotificationApiPort.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.NumNotificationApiPort.MaxLength = 10; + this.NumNotificationApiPort.MetroColor = System.Drawing.SystemColors.WindowFrame; + this.NumNotificationApiPort.Name = "NumNotificationApiPort"; + this.NumNotificationApiPort.Size = new System.Drawing.Size(83, 25); + this.NumNotificationApiPort.TabIndex = 72; + this.NumNotificationApiPort.ThemeName = "Metro"; + this.NumNotificationApiPort.Value = new decimal(new int[] { + 5115, + 0, + 0, + 0}); + this.NumNotificationApiPort.VisualStyle = Syncfusion.Windows.Forms.VisualStyle.Metro; + // + // BtnSendTestNotification + // + this.BtnSendTestNotification.AccessibleName = "Button"; + this.BtnSendTestNotification.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnSendTestNotification.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnSendTestNotification.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnSendTestNotification.Location = new System.Drawing.Point(220, 260); + this.BtnSendTestNotification.Name = "BtnSendTestNotification"; + this.BtnSendTestNotification.Size = new System.Drawing.Size(301, 31); + this.BtnSendTestNotification.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnSendTestNotification.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnSendTestNotification.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnSendTestNotification.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnSendTestNotification.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnSendTestNotification.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnSendTestNotification.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnSendTestNotification.TabIndex = 73; + this.BtnSendTestNotification.Text = "show test notification"; + this.BtnSendTestNotification.UseVisualStyleBackColor = false; + this.BtnSendTestNotification.Click += new System.EventHandler(this.BtnSendTestNotification_Click); + // + // BtnExecutePortReservation + // + this.BtnExecutePortReservation.AccessibleName = "Button"; + this.BtnExecutePortReservation.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnExecutePortReservation.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnExecutePortReservation.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnExecutePortReservation.Location = new System.Drawing.Point(220, 207); + this.BtnExecutePortReservation.Name = "BtnExecutePortReservation"; + this.BtnExecutePortReservation.Size = new System.Drawing.Size(301, 31); + this.BtnExecutePortReservation.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnExecutePortReservation.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnExecutePortReservation.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnExecutePortReservation.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnExecutePortReservation.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnExecutePortReservation.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnExecutePortReservation.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnExecutePortReservation.TabIndex = 74; + this.BtnExecutePortReservation.Text = "execute port reservation"; + this.BtnExecutePortReservation.UseVisualStyleBackColor = false; + this.BtnExecutePortReservation.Click += new System.EventHandler(this.BtnExecutePortReservation_Click); + // + // Notifications + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.BtnExecutePortReservation); + this.Controls.Add(this.BtnSendTestNotification); + this.Controls.Add(this.NumNotificationApiPort); + this.Controls.Add(this.label18); + this.Controls.Add(this.label12); + this.Controls.Add(this.BtnNotificationsReadme); + this.Controls.Add(this.label1); + this.Controls.Add(this.CbAcceptNotifications); + this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "Notifications"; + this.Size = new System.Drawing.Size(740, 544); + ((System.ComponentModel.ISupportInitialize)(this.NumNotificationApiPort)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label18; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label1; + internal Syncfusion.WinForms.Controls.SfButton BtnNotificationsReadme; + internal System.Windows.Forms.CheckBox CbAcceptNotifications; + internal Syncfusion.Windows.Forms.Tools.NumericUpDownExt NumNotificationApiPort; + internal Syncfusion.WinForms.Controls.SfButton BtnSendTestNotification; + internal Syncfusion.WinForms.Controls.SfButton BtnExecutePortReservation; + } +} diff --git a/src/HASSAgent/Controls/Configuration/Notifications.cs b/src/HASSAgent/Controls/Configuration/Notifications.cs new file mode 100644 index 0000000..717d95b --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Notifications.cs @@ -0,0 +1,66 @@ +using HASSAgent.Functions; +using HASSAgent.Models.HomeAssistant; +using HASSAgent.Notifications; +using Serilog; +using Syncfusion.Windows.Forms; + +namespace HASSAgent.Controls.Configuration +{ + public partial class Notifications : UserControl + { + public Notifications() + { + InitializeComponent(); + } + + private void BtnNotificationsReadme_Click(object sender, EventArgs e) => HelperFunctions.LaunchUrl("https://github.com/LAB02-Research/HASS.Agent/wiki/Notification-Usage-&-Examples"); + + private void BtnSendTestNotification_Click(object sender, EventArgs e) + { + if (!Variables.AppSettings.NotificationsEnabled) + { + MessageBoxAdv.Show("Notifications are still disabled. Please enable, restart HASS.Agent and try again.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + var testNotification = new Notification + { + Message = "This is a test notification.", + Title = "HASS.Agent" + }; + + Log.Information("[NOTIFIER] Attempting to show test notification .."); + + NotifierManager.ShowNotification(testNotification); + + Log.Information("[NOTIFIER] Test notification attempt completed"); + + MessageBoxAdv.Show("The notification should've popped up. If not, check the logs, or check the documentation for troubleshooting tips.\r\n\r\nNote: this only tests locally whether notifications can be shown!", + "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + private async void BtnExecutePortReservation_Click(object sender, EventArgs e) + { + BtnExecutePortReservation.Text = "executing, please wait .."; + + BtnSendTestNotification.Enabled = false; + BtnExecutePortReservation.Enabled = false; + + // try to reserve elevated + if (!await Task.Run(NotifierManager.ExecuteElevatedPortReservation)) + { + // failed, copy the command onto the clipboard + Clipboard.SetText($"http add urlacl url=http://+:{Variables.AppSettings.NotifierApiPort}/ user={Environment.UserDomainName}\\{Environment.UserName}"); + + // notify the user + MessageBoxAdv.Show("Something went wrong!\r\n\r\nPlease manually execute the required command. It has been copied onto your clipboard, " + + "you just need to paste it into an elevated command prompt.\r\n\r\nRemember to change your firewall rule's port as well.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + BtnExecutePortReservation.Text = "execute port reservation"; + + BtnExecutePortReservation.Enabled = true; + BtnSendTestNotification.Enabled = true; + } + } +} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.resx b/src/HASSAgent/Controls/Configuration/Notifications.resx similarity index 50% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.resx rename to src/HASSAgent/Controls/Configuration/Notifications.resx index 358e13a..83ee31f 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Notifications.resx +++ b/src/HASSAgent/Controls/Configuration/Notifications.resx @@ -1,64 +1,4 @@ - - - + diff --git a/src/HASSAgent/Controls/Configuration/Service.Designer.cs b/src/HASSAgent/Controls/Configuration/Service.Designer.cs new file mode 100644 index 0000000..ef196d3 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Service.Designer.cs @@ -0,0 +1,304 @@ +namespace HASSAgent.Controls.Configuration +{ + partial class Service + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Service)); + this.label12 = new System.Windows.Forms.Label(); + this.LblServiceStatus = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.BtnStartService = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnDisableService = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnStopService = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnEnableService = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnReinstallService = new Syncfusion.WinForms.Controls.SfButton(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.BtnShowLogs = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnRescanStatus = new Syncfusion.WinForms.Controls.SfButton(); + this.label3 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label12.Location = new System.Drawing.Point(70, 36); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(581, 38); + this.label12.TabIndex = 36; + this.label12.Text = "The satellite service allows you to run sensors and commands even when no user\'s " + + "logged in. \r\nUse the \'satellite service\' button on the main window to manage it." + + ""; + // + // LblServiceStatus + // + this.LblServiceStatus.AutoSize = true; + this.LblServiceStatus.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.LblServiceStatus.Location = new System.Drawing.Point(290, 107); + this.LblServiceStatus.Name = "LblServiceStatus"; + this.LblServiceStatus.Size = new System.Drawing.Size(15, 19); + this.LblServiceStatus.TabIndex = 38; + this.LblServiceStatus.Text = "-"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label4.Location = new System.Drawing.Point(154, 107); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(94, 19); + this.label4.TabIndex = 37; + this.label4.Text = "service status:"; + // + // BtnStartService + // + this.BtnStartService.AccessibleName = "Button"; + this.BtnStartService.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStartService.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnStartService.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStartService.Location = new System.Drawing.Point(396, 161); + this.BtnStartService.Name = "BtnStartService"; + this.BtnStartService.Size = new System.Drawing.Size(188, 31); + this.BtnStartService.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStartService.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStartService.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStartService.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStartService.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStartService.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStartService.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnStartService.TabIndex = 39; + this.BtnStartService.Text = "start service"; + this.BtnStartService.UseVisualStyleBackColor = false; + this.BtnStartService.Click += new System.EventHandler(this.BtnStartService_Click); + // + // BtnDisableService + // + this.BtnDisableService.AccessibleName = "Button"; + this.BtnDisableService.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnDisableService.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnDisableService.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnDisableService.Location = new System.Drawing.Point(156, 290); + this.BtnDisableService.Name = "BtnDisableService"; + this.BtnDisableService.Size = new System.Drawing.Size(188, 31); + this.BtnDisableService.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnDisableService.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnDisableService.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnDisableService.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnDisableService.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnDisableService.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnDisableService.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnDisableService.TabIndex = 40; + this.BtnDisableService.Text = "disable service"; + this.BtnDisableService.UseVisualStyleBackColor = false; + this.BtnDisableService.Click += new System.EventHandler(this.BtnDisableService_Click); + // + // BtnStopService + // + this.BtnStopService.AccessibleName = "Button"; + this.BtnStopService.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStopService.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnStopService.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStopService.Location = new System.Drawing.Point(156, 161); + this.BtnStopService.Name = "BtnStopService"; + this.BtnStopService.Size = new System.Drawing.Size(188, 31); + this.BtnStopService.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStopService.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStopService.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStopService.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStopService.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStopService.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStopService.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnStopService.TabIndex = 41; + this.BtnStopService.Text = "stop service"; + this.BtnStopService.UseVisualStyleBackColor = false; + this.BtnStopService.Click += new System.EventHandler(this.BtnStopService_Click); + // + // BtnEnableService + // + this.BtnEnableService.AccessibleName = "Button"; + this.BtnEnableService.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnEnableService.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnEnableService.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnEnableService.Location = new System.Drawing.Point(396, 290); + this.BtnEnableService.Name = "BtnEnableService"; + this.BtnEnableService.Size = new System.Drawing.Size(188, 31); + this.BtnEnableService.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnEnableService.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnEnableService.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnEnableService.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnEnableService.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnEnableService.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnEnableService.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnEnableService.TabIndex = 42; + this.BtnEnableService.Text = "enable service"; + this.BtnEnableService.UseVisualStyleBackColor = false; + this.BtnEnableService.Click += new System.EventHandler(this.BtnEnableService_Click); + // + // BtnReinstallService + // + this.BtnReinstallService.AccessibleName = "Button"; + this.BtnReinstallService.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnReinstallService.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnReinstallService.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnReinstallService.Location = new System.Drawing.Point(154, 403); + this.BtnReinstallService.Name = "BtnReinstallService"; + this.BtnReinstallService.Size = new System.Drawing.Size(432, 31); + this.BtnReinstallService.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnReinstallService.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnReinstallService.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnReinstallService.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnReinstallService.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnReinstallService.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnReinstallService.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnReinstallService.TabIndex = 43; + this.BtnReinstallService.Text = "reinstall service"; + this.BtnReinstallService.UseVisualStyleBackColor = false; + this.BtnReinstallService.Click += new System.EventHandler(this.BtnReinstallService_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.ImageAlign = System.Drawing.ContentAlignment.TopCenter; + this.label1.Location = new System.Drawing.Point(47, 222); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(646, 38); + this.label1.TabIndex = 44; + this.label1.Text = resources.GetString("label1.Text"); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(177, 350); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(386, 38); + this.label2.TabIndex = 45; + this.label2.Text = "You can try reinstalling the service if it\'s not working correctly.\r\nYour configu" + + "ration and entities won\'t be removed."; + // + // BtnShowLogs + // + this.BtnShowLogs.AccessibleName = "Button"; + this.BtnShowLogs.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnShowLogs.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Location = new System.Drawing.Point(154, 491); + this.BtnShowLogs.Name = "BtnShowLogs"; + this.BtnShowLogs.Size = new System.Drawing.Size(432, 31); + this.BtnShowLogs.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnShowLogs.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnShowLogs.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnShowLogs.TabIndex = 46; + this.BtnShowLogs.Text = "open service logs folder"; + this.BtnShowLogs.UseVisualStyleBackColor = false; + this.BtnShowLogs.Click += new System.EventHandler(this.BtnShowLogs_Click); + // + // BtnRescanStatus + // + this.BtnRescanStatus.AccessibleName = "Button"; + this.BtnRescanStatus.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRescanStatus.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnRescanStatus.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRescanStatus.ImageSize = new System.Drawing.Size(24, 24); + this.BtnRescanStatus.Location = new System.Drawing.Point(535, 100); + this.BtnRescanStatus.Name = "BtnRescanStatus"; + this.BtnRescanStatus.Size = new System.Drawing.Size(51, 31); + this.BtnRescanStatus.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRescanStatus.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRescanStatus.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRescanStatus.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRescanStatus.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRescanStatus.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRescanStatus.Style.Image = global::HASSAgent.Properties.Resources.reset_24; + this.BtnRescanStatus.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnRescanStatus.TabIndex = 47; + this.BtnRescanStatus.TextImageRelation = System.Windows.Forms.TextImageRelation.Overlay; + this.BtnRescanStatus.UseVisualStyleBackColor = false; + this.BtnRescanStatus.Click += new System.EventHandler(this.BtnRescanStatus_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(68, 454); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(605, 19); + this.label3.TabIndex = 48; + this.label3.Text = "If the service still fails after reinstalling, please open a ticket and send the " + + "content of the latest log."; + // + // Service + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.label3); + this.Controls.Add(this.BtnRescanStatus); + this.Controls.Add(this.BtnShowLogs); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.BtnReinstallService); + this.Controls.Add(this.BtnEnableService); + this.Controls.Add(this.BtnStopService); + this.Controls.Add(this.BtnDisableService); + this.Controls.Add(this.BtnStartService); + this.Controls.Add(this.LblServiceStatus); + this.Controls.Add(this.label4); + this.Controls.Add(this.label12); + this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "Service"; + this.Size = new System.Drawing.Size(740, 544); + this.Load += new System.EventHandler(this.Service_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.Label label12; + internal Label LblServiceStatus; + private Label label4; + internal Syncfusion.WinForms.Controls.SfButton BtnStartService; + internal Syncfusion.WinForms.Controls.SfButton BtnDisableService; + internal Syncfusion.WinForms.Controls.SfButton BtnStopService; + internal Syncfusion.WinForms.Controls.SfButton BtnEnableService; + internal Syncfusion.WinForms.Controls.SfButton BtnReinstallService; + private Label label1; + private Label label2; + internal Syncfusion.WinForms.Controls.SfButton BtnShowLogs; + internal Syncfusion.WinForms.Controls.SfButton BtnRescanStatus; + private Label label3; + } +} diff --git a/src/HASSAgent/Controls/Configuration/Service.cs b/src/HASSAgent/Controls/Configuration/Service.cs new file mode 100644 index 0000000..58b73b8 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Service.cs @@ -0,0 +1,214 @@ +using System.ServiceProcess; +using HASSAgent.Enums; +using HASSAgent.Functions; +using HASSAgent.Service; +using HASSAgent.Shared.Functions; +using Serilog; +using Syncfusion.Windows.Forms; + +namespace HASSAgent.Controls.Configuration +{ + public partial class Service : UserControl + { + public Service() + { + InitializeComponent(); + } + + private void Service_Load(object sender, EventArgs e) + { + Task.Run(DetermineServiceStatus); + } + + /// + /// Determine the current status of the start-on-login setting, and sets the GUI accordingly + /// + internal void DetermineServiceStatus() + { + try + { + if (!ServiceControllerManager.ServiceExists()) + { + Variables.MainForm?.SetServiceStatus(ComponentStatus.Disabled); + + // set not-installed + Invoke(new MethodInvoker(delegate + { + LblServiceStatus.ForeColor = Color.OrangeRed; + LblServiceStatus.Text = "not installed"; + + })); + + return; + } + + // disabled? + var startupState = ServiceControllerManager.GetServiceStartMode(); + if (startupState == ServiceStartMode.Disabled) + { + Variables.MainForm?.SetServiceStatus(ComponentStatus.Disabled); + + Invoke(new MethodInvoker(delegate + { + LblServiceStatus.ForeColor = Color.OrangeRed; + LblServiceStatus.Text = "disabled"; + })); + + return; + } + + // set state + var state = ServiceControllerManager.GetServiceState(); + switch (state) + { + case ServiceControllerStatus.Running: + + Variables.MainForm?.SetServiceStatus(ComponentStatus.Ok); + + Invoke(new MethodInvoker(delegate + { + LblServiceStatus.ForeColor = Color.LimeGreen; + LblServiceStatus.Text = "running"; + })); + break; + + case ServiceControllerStatus.Stopped: + Variables.MainForm?.SetServiceStatus(ComponentStatus.Stopped); + + Invoke(new MethodInvoker(delegate + { + LblServiceStatus.ForeColor = Color.OrangeRed; + LblServiceStatus.Text = state.ToString().ToLower(); + })); + break; + + default: + Variables.MainForm?.SetServiceStatus(ComponentStatus.Failed); + + Invoke(new MethodInvoker(delegate + { + LblServiceStatus.ForeColor = Color.OrangeRed; + LblServiceStatus.Text = state.ToString().ToLower(); + })); + break; + } + } + catch (InvalidOperationException) + { + // ignore, form closed + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error setting service state: {err}", ex.Message); + } + } + + private void BtnRescanStatus_Click(object sender, EventArgs e) => Task.Run(DetermineServiceStatus); + + private async void BtnStopService_Click(object sender, EventArgs e) + { + if (ServiceControllerManager.GetServiceState() == ServiceControllerStatus.Stopped) + { + // already stopped, refresh the state incase it's not showing correctly + _ = Task.Run(DetermineServiceStatus); + return; + } + + // needs to be done elevated + var done = await Task.Run(() => CommandLineManager.ExecuteElevated(Variables.ApplicationExecutable, "service_stop", TimeSpan.FromMinutes(2))); + + // show the new state + _ = Task.Run(DetermineServiceStatus); + + // check if went ok + if (!done) MessageBoxAdv.Show("Something went wrong trying to stop the service. Did you allow the UAC prompt?\r\n\r\nCheck the HASS.Agent (not the service) logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + + // done + } + + private async void BtnStartService_Click(object sender, EventArgs e) + { + if (ServiceControllerManager.GetServiceState() == ServiceControllerStatus.Running) + { + // already running, refresh the state incase it's not showing correctly + _ = Task.Run(DetermineServiceStatus); + return; + } + + if (ServiceControllerManager.GetServiceStartMode() == ServiceStartMode.Disabled) + { + MessageBoxAdv.Show("The service is set to 'disabled', so it can't be started.\r\n\r\nPlease enable the service first, then try again.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + // needs to be done elevated + var done = await Task.Run(() => CommandLineManager.ExecuteElevated(Variables.ApplicationExecutable, "service_start", TimeSpan.FromMinutes(2))); + + // show the new state + _ = Task.Run(DetermineServiceStatus); + + // check if went ok + if (!done) MessageBoxAdv.Show("Something went wrong trying to start the service. Did you allow the UAC prompt?\r\n\r\nCheck the HASS.Agent (not the service) logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + + // done + } + + private async void BtnDisableService_Click(object sender, EventArgs e) + { + if (ServiceControllerManager.GetServiceStartMode() == ServiceStartMode.Disabled) + { + // already disabled, refresh the state incase it's not showing correctly + _ = Task.Run(DetermineServiceStatus); + return; + } + + // needs to be done elevated + var done = await Task.Run(() => CommandLineManager.ExecuteElevated(Variables.ApplicationExecutable, "service_disable", TimeSpan.FromMinutes(2))); + + // show the new state + _ = Task.Run(DetermineServiceStatus); + + // check if went ok + if (!done) MessageBoxAdv.Show("Something went wrong trying to disable the service. Did you allow the UAC prompt?\r\n\r\nCheck the HASS.Agent (not the service) logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + + // done + } + + private async void BtnEnableService_Click(object sender, EventArgs e) + { + if (ServiceControllerManager.GetServiceStartMode() == ServiceStartMode.Automatic) + { + // already enabled, refresh the state incase it's not showing correctly + _ = Task.Run(DetermineServiceStatus); + return; + } + + // needs to be done elevated + var done = await Task.Run(() => CommandLineManager.ExecuteElevated(Variables.ApplicationExecutable, "service_enabled", TimeSpan.FromMinutes(2))); + + // show the new state + _ = Task.Run(DetermineServiceStatus); + + // check if went ok + if (!done) MessageBoxAdv.Show("Something went wrong trying to enable the service. Did you allow the UAC prompt?\r\n\r\nCheck the HASS.Agent (not the service) logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + + // done + } + + private void BtnShowLogs_Click(object sender, EventArgs e) => HelperFunctions.OpenLocalFolder(Variables.SatelliteServiceLogPath); + + private async void BtnReinstallService_Click(object sender, EventArgs e) + { + // needs to be done elevated + var done = await Task.Run(() => CommandLineManager.ExecuteElevated(Variables.ApplicationExecutable, "service_reinstall", TimeSpan.FromMinutes(5))); + + // show the new state + _ = Task.Run(DetermineServiceStatus); + + // check if went ok + if (!done) MessageBoxAdv.Show("Something went wrong trying to reinstall the service. Did you allow the UAC prompt?\r\n\r\nCheck the HASS.Agent (not the service) logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + + // done + } + } +} diff --git a/src/HASSAgent/Controls/Configuration/Service.resx b/src/HASSAgent/Controls/Configuration/Service.resx new file mode 100644 index 0000000..39cd8fe --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Service.resx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + If you don't configure the service, it won't do anything. However, you can still decide to disable it as well. +The installer will leave the disabled service alone (if you remove the service, the installer will reinstall it). + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.Designer.cs b/src/HASSAgent/Controls/Configuration/Startup.Designer.cs similarity index 84% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.Designer.cs rename to src/HASSAgent/Controls/Configuration/Startup.Designer.cs index 3b3af39..3501585 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/Startup.Designer.cs @@ -37,10 +37,10 @@ private void InitializeComponent() // // label15 // - this.label15.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label15.Location = new System.Drawing.Point(27, 19); + this.label15.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label15.Location = new System.Drawing.Point(70, 36); this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(668, 96); + this.label15.Size = new System.Drawing.Size(580, 87); this.label15.TabIndex = 15; this.label15.Text = resources.GetString("label15.Text"); // @@ -48,9 +48,9 @@ private void InitializeComponent() // this.BtnSetStartOnLogin.AccessibleName = "Button"; this.BtnSetStartOnLogin.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnSetStartOnLogin.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnSetStartOnLogin.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnSetStartOnLogin.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnSetStartOnLogin.Location = new System.Drawing.Point(128, 219); + this.BtnSetStartOnLogin.Location = new System.Drawing.Point(222, 294); this.BtnSetStartOnLogin.Name = "BtnSetStartOnLogin"; this.BtnSetStartOnLogin.Size = new System.Drawing.Size(295, 31); this.BtnSetStartOnLogin.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -68,20 +68,20 @@ private void InitializeComponent() // LblStartOnLoginStatus // this.LblStartOnLoginStatus.AutoSize = true; - this.LblStartOnLoginStatus.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblStartOnLoginStatus.Location = new System.Drawing.Point(293, 169); + this.LblStartOnLoginStatus.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.LblStartOnLoginStatus.Location = new System.Drawing.Point(398, 205); this.LblStartOnLoginStatus.Name = "LblStartOnLoginStatus"; - this.LblStartOnLoginStatus.Size = new System.Drawing.Size(13, 17); + this.LblStartOnLoginStatus.Size = new System.Drawing.Size(15, 19); this.LblStartOnLoginStatus.TabIndex = 13; this.LblStartOnLoginStatus.Text = "-"; // // label4 // this.label4.AutoSize = true; - this.label4.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label4.Location = new System.Drawing.Point(125, 169); + this.label4.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label4.Location = new System.Drawing.Point(222, 205); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(129, 17); + this.label4.Size = new System.Drawing.Size(139, 19); this.label4.TabIndex = 12; this.label4.Text = "start-on-login status:"; // @@ -94,11 +94,10 @@ private void InitializeComponent() this.Controls.Add(this.BtnSetStartOnLogin); this.Controls.Add(this.LblStartOnLoginStatus); this.Controls.Add(this.label4); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Startup"; - this.Size = new System.Drawing.Size(700, 457); + this.Size = new System.Drawing.Size(740, 544); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.cs b/src/HASSAgent/Controls/Configuration/Startup.cs similarity index 76% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.cs rename to src/HASSAgent/Controls/Configuration/Startup.cs index 7024aca..a6bc08e 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Startup.cs +++ b/src/HASSAgent/Controls/Configuration/Startup.cs @@ -1,13 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Functions; +using HASSAgent.Functions; using Syncfusion.Windows.Forms; namespace HASSAgent.Controls.Configuration @@ -58,22 +49,24 @@ internal void DetermineStartOnLoginStatus() { if (LaunchManager.CheckLaunchOnUserLogin()) { + // set enabled Invoke(new MethodInvoker(delegate { LblStartOnLoginStatus.ForeColor = Color.LimeGreen; LblStartOnLoginStatus.Text = "enabled"; BtnSetStartOnLogin.Text = "disable start-on-login"; })); + + return; } - else + + // set disabled + Invoke(new MethodInvoker(delegate { - Invoke(new MethodInvoker(delegate - { - LblStartOnLoginStatus.ForeColor = Color.OrangeRed; - LblStartOnLoginStatus.Text = "disabled"; - BtnSetStartOnLogin.Text = "enable start-on-login"; - })); - } + LblStartOnLoginStatus.ForeColor = Color.OrangeRed; + LblStartOnLoginStatus.Text = "disabled"; + BtnSetStartOnLogin.Text = "enable start-on-login"; + })); } } } diff --git a/src/HASSAgent/Controls/Configuration/Startup.resx b/src/HASSAgent/Controls/Configuration/Startup.resx new file mode 100644 index 0000000..12e12d7 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Startup.resx @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + HASS.Agent can start when you login by creating an entry in your user profile's registry. + +Since HASS.Agent is user based, if you want to launch for another user, just install and config HASS.Agent there. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.Designer.cs b/src/HASSAgent/Controls/Configuration/Updates.Designer.cs similarity index 80% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.Designer.cs rename to src/HASSAgent/Controls/Configuration/Updates.Designer.cs index f896c41..18bcf88 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.Designer.cs +++ b/src/HASSAgent/Controls/Configuration/Updates.Designer.cs @@ -39,18 +39,18 @@ private void InitializeComponent() // CbBetaUpdates // this.CbBetaUpdates.AutoSize = true; - this.CbBetaUpdates.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbBetaUpdates.Location = new System.Drawing.Point(124, 164); + this.CbBetaUpdates.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbBetaUpdates.Location = new System.Drawing.Point(207, 209); this.CbBetaUpdates.Name = "CbBetaUpdates"; - this.CbBetaUpdates.Size = new System.Drawing.Size(222, 21); + this.CbBetaUpdates.Size = new System.Drawing.Size(229, 23); this.CbBetaUpdates.TabIndex = 39; this.CbBetaUpdates.Text = "notify me of beta releases as well"; this.CbBetaUpdates.UseVisualStyleBackColor = true; // // label24 // - this.label24.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label24.Location = new System.Drawing.Point(27, 228); + this.label24.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label24.Location = new System.Drawing.Point(70, 293); this.label24.Name = "label24"; this.label24.Size = new System.Drawing.Size(598, 79); this.label24.TabIndex = 38; @@ -59,20 +59,20 @@ private void InitializeComponent() // CbExecuteUpdater // this.CbExecuteUpdater.AutoSize = true; - this.CbExecuteUpdater.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbExecuteUpdater.Location = new System.Drawing.Point(124, 335); + this.CbExecuteUpdater.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbExecuteUpdater.Location = new System.Drawing.Point(207, 422); this.CbExecuteUpdater.Name = "CbExecuteUpdater"; - this.CbExecuteUpdater.Size = new System.Drawing.Size(314, 21); + this.CbExecuteUpdater.Size = new System.Drawing.Size(327, 23); this.CbExecuteUpdater.TabIndex = 37; this.CbExecuteUpdater.Text = "offer to download and launch the installer for me"; this.CbExecuteUpdater.UseVisualStyleBackColor = true; // // label17 // - this.label17.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label17.Location = new System.Drawing.Point(27, 19); + this.label17.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label17.Location = new System.Drawing.Point(70, 36); this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(668, 69); + this.label17.Size = new System.Drawing.Size(616, 69); this.label17.TabIndex = 36; this.label17.Text = "If you want, HASS.Agent can check for updates in the background. \r\n\r\nYou\'ll get a" + " notification (once per update) , letting you know a new version is ready to be " + @@ -81,10 +81,10 @@ private void InitializeComponent() // CbUpdates // this.CbUpdates.AutoSize = true; - this.CbUpdates.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbUpdates.Location = new System.Drawing.Point(124, 113); + this.CbUpdates.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbUpdates.Location = new System.Drawing.Point(207, 158); this.CbUpdates.Name = "CbUpdates"; - this.CbUpdates.Size = new System.Drawing.Size(267, 21); + this.CbUpdates.Size = new System.Drawing.Size(278, 23); this.CbUpdates.TabIndex = 35; this.CbUpdates.Text = "notify me when a new release is available"; this.CbUpdates.UseVisualStyleBackColor = true; @@ -99,11 +99,10 @@ private void InitializeComponent() this.Controls.Add(this.CbExecuteUpdater); this.Controls.Add(this.label17); this.Controls.Add(this.CbUpdates); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Updates"; - this.Size = new System.Drawing.Size(700, 457); + this.Size = new System.Drawing.Size(740, 544); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/HASSAgent/Controls/Configuration/Updates.cs b/src/HASSAgent/Controls/Configuration/Updates.cs new file mode 100644 index 0000000..ce4af38 --- /dev/null +++ b/src/HASSAgent/Controls/Configuration/Updates.cs @@ -0,0 +1,10 @@ +namespace HASSAgent.Controls.Configuration +{ + public partial class Updates : UserControl + { + public Updates() + { + InitializeComponent(); + } + } +} diff --git a/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.resx b/src/HASSAgent/Controls/Configuration/Updates.resx similarity index 50% rename from src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.resx rename to src/HASSAgent/Controls/Configuration/Updates.resx index f3990f3..24411f3 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Configuration/Updates.resx +++ b/src/HASSAgent/Controls/Configuration/Updates.resx @@ -1,64 +1,4 @@ - - - + diff --git a/src/CustomGroupBox/CustomGroupBox/CustomGroupBox.cs b/src/HASSAgent/Controls/CustomGroupBox.cs similarity index 83% rename from src/CustomGroupBox/CustomGroupBox/CustomGroupBox.cs rename to src/HASSAgent/Controls/CustomGroupBox.cs index c7bb0b0..676f9c1 100644 --- a/src/CustomGroupBox/CustomGroupBox/CustomGroupBox.cs +++ b/src/HASSAgent/Controls/CustomGroupBox.cs @@ -1,7 +1,10 @@ -using System.Drawing; -using System.Windows.Forms; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; -namespace CustomGroupBox +namespace HASSAgent.Controls { public class CustomGroupBox : GroupBox { diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs b/src/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs similarity index 84% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs rename to src/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs index ad3df0a..744dd97 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/1-Welcome.Designer.cs @@ -38,10 +38,10 @@ private void InitializeComponent() // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(384, 128); + this.label1.Size = new System.Drawing.Size(466, 66); this.label1.TabIndex = 0; this.label1.Text = "It looks like this is the first time you\'ve launched HASS.Agent.\r\n\r\nIf you want, " + "we can go through the configuration. If not, just click \'close\'.\r\n"; @@ -60,10 +60,10 @@ private void InitializeComponent() // label32 // this.label32.AutoSize = true; - this.label32.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label32.Location = new System.Drawing.Point(180, 243); + this.label32.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label32.Location = new System.Drawing.Point(180, 241); this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(411, 34); + this.label32.Size = new System.Drawing.Size(424, 38); this.label32.TabIndex = 51; this.label32.Text = "Device name is used to identify your machine on HA. \r\nIt\'s also used as a suggest" + "ed prefix for your commands and sensors.\r\n"; @@ -72,20 +72,20 @@ private void InitializeComponent() // this.TbDeviceName.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbDeviceName.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbDeviceName.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbDeviceName.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbDeviceName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.TbDeviceName.Location = new System.Drawing.Point(183, 196); this.TbDeviceName.Name = "TbDeviceName"; - this.TbDeviceName.Size = new System.Drawing.Size(358, 25); + this.TbDeviceName.Size = new System.Drawing.Size(372, 25); this.TbDeviceName.TabIndex = 50; // // label3 // this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(180, 176); + this.label3.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(180, 174); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(81, 17); + this.label3.Size = new System.Drawing.Size(85, 19); this.label3.TabIndex = 52; this.label3.Text = "device name"; // @@ -99,11 +99,10 @@ private void InitializeComponent() this.Controls.Add(this.TbDeviceName); this.Controls.Add(this.PbHassAgentLogo); this.Controls.Add(this.label1); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Welcome"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.Welcome_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); this.ResumeLayout(false); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.cs b/src/HASSAgent/Controls/Onboarding/1-Welcome.cs similarity index 81% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.cs rename to src/HASSAgent/Controls/Onboarding/1-Welcome.cs index c8c3298..cb09cee 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/1-Welcome.cs +++ b/src/HASSAgent/Controls/Onboarding/1-Welcome.cs @@ -1,7 +1,4 @@ -using System; -using System.Windows.Forms; - -namespace HASSAgent.Controls.Onboarding +namespace HASSAgent.Controls.Onboarding { public partial class Welcome : UserControl { diff --git a/src/HASSAgent/Controls/Onboarding/1-Welcome.resx b/src/HASSAgent/Controls/Onboarding/1-Welcome.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/1-Welcome.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs b/src/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs similarity index 89% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs rename to src/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs index b52e8a6..8c74606 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/2-Startup.Designer.cs @@ -51,9 +51,9 @@ private void InitializeComponent() this.BtnSetLaunchOnLogin.AccessibleName = "Button"; this.BtnSetLaunchOnLogin.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.BtnSetLaunchOnLogin.Enabled = false; - this.BtnSetLaunchOnLogin.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnSetLaunchOnLogin.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnSetLaunchOnLogin.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnSetLaunchOnLogin.Location = new System.Drawing.Point(183, 266); + this.BtnSetLaunchOnLogin.Location = new System.Drawing.Point(180, 277); this.BtnSetLaunchOnLogin.Name = "BtnSetLaunchOnLogin"; this.BtnSetLaunchOnLogin.Size = new System.Drawing.Size(402, 31); this.BtnSetLaunchOnLogin.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -70,10 +70,10 @@ private void InitializeComponent() // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(405, 128); + this.label1.Size = new System.Drawing.Size(567, 88); this.label1.TabIndex = 5; this.label1.Text = "HASS.Agent can launch when you login to Windows, by creating a key in your user p" + "rofile\'s registry.\r\n\r\nYou can always remove (or recreate) this key through the C" + @@ -81,8 +81,8 @@ private void InitializeComponent() // // LblCreateInfo // - this.LblCreateInfo.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblCreateInfo.Location = new System.Drawing.Point(180, 189); + this.LblCreateInfo.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.LblCreateInfo.Location = new System.Drawing.Point(180, 190); this.LblCreateInfo.Name = "LblCreateInfo"; this.LblCreateInfo.Size = new System.Drawing.Size(405, 56); this.LblCreateInfo.TabIndex = 6; @@ -97,11 +97,10 @@ private void InitializeComponent() this.Controls.Add(this.LblCreateInfo); this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Startup"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.Startup_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); this.ResumeLayout(false); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.cs b/src/HASSAgent/Controls/Onboarding/2-Startup.cs similarity index 93% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.cs rename to src/HASSAgent/Controls/Onboarding/2-Startup.cs index 2273136..3b49d1d 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/2-Startup.cs +++ b/src/HASSAgent/Controls/Onboarding/2-Startup.cs @@ -1,7 +1,4 @@ -using System; -using System.Drawing; -using System.Windows.Forms; -using HASSAgent.Functions; +using HASSAgent.Functions; using Task = System.Threading.Tasks.Task; namespace HASSAgent.Controls.Onboarding diff --git a/src/HASSAgent/Controls/Onboarding/2-Startup.resx b/src/HASSAgent/Controls/Onboarding/2-Startup.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/2-Startup.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs b/src/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs new file mode 100644 index 0000000..de7f0d6 --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/3-Notifications.Designer.cs @@ -0,0 +1,142 @@ +namespace HASSAgent.Controls.Onboarding +{ + partial class Notifications + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.PbHassAgentLogo = new System.Windows.Forms.PictureBox(); + this.label2 = new System.Windows.Forms.Label(); + this.CbAcceptNotifications = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.NumNotificationApiPort = new Syncfusion.Windows.Forms.Tools.NumericUpDownExt(); + ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NumNotificationApiPort)).BeginInit(); + this.SuspendLayout(); + // + // PbHassAgentLogo + // + this.PbHassAgentLogo.Cursor = System.Windows.Forms.Cursors.Hand; + this.PbHassAgentLogo.Image = global::HASSAgent.Properties.Resources.logo_128; + this.PbHassAgentLogo.Location = new System.Drawing.Point(24, 20); + this.PbHassAgentLogo.Name = "PbHassAgentLogo"; + this.PbHassAgentLogo.Size = new System.Drawing.Size(128, 128); + this.PbHassAgentLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.PbHassAgentLogo.TabIndex = 2; + this.PbHassAgentLogo.TabStop = false; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(180, 415); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(425, 13); + this.label2.TabIndex = 26; + this.label2.Text = "Note: 5115 is the default port, only change it if you changed it in Home Assistan" + + "t."; + // + // CbAcceptNotifications + // + this.CbAcceptNotifications.AutoSize = true; + this.CbAcceptNotifications.Checked = true; + this.CbAcceptNotifications.CheckState = System.Windows.Forms.CheckState.Checked; + this.CbAcceptNotifications.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbAcceptNotifications.Location = new System.Drawing.Point(180, 179); + this.CbAcceptNotifications.Name = "CbAcceptNotifications"; + this.CbAcceptNotifications.Size = new System.Drawing.Size(222, 23); + this.CbAcceptNotifications.TabIndex = 0; + this.CbAcceptNotifications.Text = "yes, accept notifications on port"; + this.CbAcceptNotifications.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(180, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(555, 68); + this.label1.TabIndex = 24; + this.label1.Text = "HASS.Agent can receive notifications from Home Assistant, using text and/or image" + + "s.\r\n\r\nDo you want to enable this function?"; + // + // NumNotificationApiPort + // + this.NumNotificationApiPort.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.NumNotificationApiPort.BeforeTouchSize = new System.Drawing.Size(83, 25); + this.NumNotificationApiPort.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat; + this.NumNotificationApiPort.BorderColor = System.Drawing.SystemColors.WindowFrame; + this.NumNotificationApiPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumNotificationApiPort.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.NumNotificationApiPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.NumNotificationApiPort.Location = new System.Drawing.Point(408, 179); + this.NumNotificationApiPort.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.NumNotificationApiPort.MaxLength = 10; + this.NumNotificationApiPort.MetroColor = System.Drawing.SystemColors.WindowFrame; + this.NumNotificationApiPort.Name = "NumNotificationApiPort"; + this.NumNotificationApiPort.Size = new System.Drawing.Size(83, 25); + this.NumNotificationApiPort.TabIndex = 73; + this.NumNotificationApiPort.ThemeName = "Metro"; + this.NumNotificationApiPort.Value = new decimal(new int[] { + 5115, + 0, + 0, + 0}); + this.NumNotificationApiPort.VisualStyle = Syncfusion.Windows.Forms.VisualStyle.Metro; + // + // Notifications + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.NumNotificationApiPort); + this.Controls.Add(this.label2); + this.Controls.Add(this.CbAcceptNotifications); + this.Controls.Add(this.label1); + this.Controls.Add(this.PbHassAgentLogo); + this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "Notifications"; + this.Size = new System.Drawing.Size(803, 457); + this.Load += new System.EventHandler(this.Notifications_Load); + ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NumNotificationApiPort)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.PictureBox PbHassAgentLogo; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.CheckBox CbAcceptNotifications; + private System.Windows.Forms.Label label1; + internal Syncfusion.Windows.Forms.Tools.NumericUpDownExt NumNotificationApiPort; + } +} diff --git a/src/HASSAgent/Controls/Onboarding/3-Notifications.cs b/src/HASSAgent/Controls/Onboarding/3-Notifications.cs new file mode 100644 index 0000000..c46415c --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/3-Notifications.cs @@ -0,0 +1,24 @@ +namespace HASSAgent.Controls.Onboarding +{ + public partial class Notifications : UserControl + { + public Notifications() + { + InitializeComponent(); + } + + private void Notifications_Load(object sender, EventArgs e) + { + CbAcceptNotifications.Checked = Variables.AppSettings.NotificationsEnabled; + NumNotificationApiPort.Value = Variables.AppSettings.NotifierApiPort; + } + + internal bool Store() + { + Variables.AppSettings.NotificationsEnabled = CbAcceptNotifications.Checked; + Variables.AppSettings.NotifierApiPort = (int)NumNotificationApiPort.Value; + + return true; + } + } +} diff --git a/src/HASSAgent/Controls/Onboarding/3-Notifications.resx b/src/HASSAgent/Controls/Onboarding/3-Notifications.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/3-Notifications.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs b/src/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs similarity index 83% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs rename to src/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs index b5230d5..e9acb3a 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/4-Integration.Designer.cs @@ -51,29 +51,31 @@ private void InitializeComponent() // this.LblIntegration.AutoSize = true; this.LblIntegration.Cursor = System.Windows.Forms.Cursors.Hand; - this.LblIntegration.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblIntegration.Location = new System.Drawing.Point(180, 131); + this.LblIntegration.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point); + this.LblIntegration.Location = new System.Drawing.Point(180, 187); this.LblIntegration.Name = "LblIntegration"; - this.LblIntegration.Size = new System.Drawing.Size(211, 17); + this.LblIntegration.Size = new System.Drawing.Size(215, 19); this.LblIntegration.TabIndex = 27; this.LblIntegration.Text = "HASS.Agent-Notifier GitHub page"; this.LblIntegration.Click += new System.EventHandler(this.LblIntegration_Click); // // label3 // - this.label3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(180, 180); + this.label3.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(180, 277); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(384, 163); + this.label3.Size = new System.Drawing.Size(384, 127); this.label3.TabIndex = 26; - this.label3.Text = resources.GetString("label3.Text"); + this.label3.Text = "Make sure you follow these steps:\r\n\r\n- Install HASS.Agent-Notifier integration\r\n-" + + " Restart Home Assistant\r\n- Configure a notifier entity\r\n- Restart Home Assistant" + + "\r\n"; // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(384, 103); + this.label1.Size = new System.Drawing.Size(583, 103); this.label1.TabIndex = 25; this.label1.Text = resources.GetString("label1.Text"); // @@ -86,11 +88,10 @@ private void InitializeComponent() this.Controls.Add(this.label3); this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Integration"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.Integration_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); this.ResumeLayout(false); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.cs b/src/HASSAgent/Controls/Onboarding/4-Integration.cs similarity index 82% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.cs rename to src/HASSAgent/Controls/Onboarding/4-Integration.cs index bc1c9c7..9b5cb9e 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/4-Integration.cs +++ b/src/HASSAgent/Controls/Onboarding/4-Integration.cs @@ -1,6 +1,4 @@ -using System; -using System.Windows.Forms; -using HASSAgent.Functions; +using HASSAgent.Functions; namespace HASSAgent.Controls.Onboarding { diff --git a/src/HASSAgent/Controls/Onboarding/4-Integration.resx b/src/HASSAgent/Controls/Onboarding/4-Integration.resx new file mode 100644 index 0000000..931ed22 --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/4-Integration.resx @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + To use notifications, you need to install and configure the HASS.Agent-notifier integration in Home Assistant. + +This is very easy using HACS, but you can also install manually. Visit the link below for more information. + + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.Designer.cs b/src/HASSAgent/Controls/Onboarding/5-API.Designer.cs similarity index 86% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.Designer.cs rename to src/HASSAgent/Controls/Onboarding/5-API.Designer.cs index d287cfa..e856e1c 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/5-API.Designer.cs @@ -55,9 +55,9 @@ private void InitializeComponent() // this.TbHassApiToken.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbHassApiToken.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbHassApiToken.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbHassApiToken.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbHassApiToken.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbHassApiToken.Location = new System.Drawing.Point(183, 265); + this.TbHassApiToken.Location = new System.Drawing.Point(180, 297); this.TbHassApiToken.Name = "TbHassApiToken"; this.TbHassApiToken.Size = new System.Drawing.Size(392, 25); this.TbHassApiToken.TabIndex = 1; @@ -66,9 +66,9 @@ private void InitializeComponent() // this.TbHassIp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbHassIp.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbHassIp.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbHassIp.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbHassIp.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbHassIp.Location = new System.Drawing.Point(183, 202); + this.TbHassIp.Location = new System.Drawing.Point(180, 209); this.TbHassIp.Name = "TbHassIp"; this.TbHassIp.Size = new System.Drawing.Size(392, 25); this.TbHassIp.TabIndex = 0; @@ -77,29 +77,29 @@ private void InitializeComponent() // label3 // this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(180, 245); + this.label3.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(180, 275); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(62, 17); + this.label3.Size = new System.Drawing.Size(66, 19); this.label3.TabIndex = 15; this.label3.Text = "api token"; // // label2 // this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(180, 182); + this.label2.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(180, 187); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(198, 17); + this.label2.Size = new System.Drawing.Size(207, 19); this.label2.TabIndex = 14; this.label2.Text = "server uri (should be ok like this)"; // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(401, 158); + this.label1.Size = new System.Drawing.Size(574, 128); this.label1.TabIndex = 13; this.label1.Text = resources.GetString("label1.Text"); // @@ -107,9 +107,9 @@ private void InitializeComponent() // this.BtnTest.AccessibleName = "Button"; this.BtnTest.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnTest.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnTest.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnTest.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnTest.Location = new System.Drawing.Point(395, 296); + this.BtnTest.Location = new System.Drawing.Point(392, 328); this.BtnTest.Name = "BtnTest"; this.BtnTest.Size = new System.Drawing.Size(180, 23); this.BtnTest.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -127,8 +127,8 @@ private void InitializeComponent() // label4 // this.label4.AutoSize = true; - this.label4.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label4.Location = new System.Drawing.Point(178, 341); + this.label4.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label4.Location = new System.Drawing.Point(180, 416); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(358, 13); this.label4.TabIndex = 36; @@ -147,11 +147,10 @@ private void InitializeComponent() this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "API"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.API_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); this.ResumeLayout(false); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.cs b/src/HASSAgent/Controls/Onboarding/5-API.cs similarity index 94% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.cs rename to src/HASSAgent/Controls/Onboarding/5-API.cs index 8f2883e..22a522f 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/5-API.cs +++ b/src/HASSAgent/Controls/Onboarding/5-API.cs @@ -1,6 +1,4 @@ -using System; -using System.Windows.Forms; -using HASSAgent.HomeAssistant; +using HASSAgent.HomeAssistant; using Syncfusion.Windows.Forms; namespace HASSAgent.Controls.Onboarding diff --git a/src/HASSAgent/Controls/Onboarding/5-API.resx b/src/HASSAgent/Controls/Onboarding/5-API.resx new file mode 100644 index 0000000..bd97638 --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/5-API.resx @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + To learn which entities you have configured, and to send quick actions, HASS.Agent uses Home Assistant's API. + +Please provide a long-lived access token, and the address of your Home Assistant instance. You can get a token through your profile page. Scroll to the bottom and click 'CREATE TOKEN'. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs b/src/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs similarity index 65% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs rename to src/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs index f6b51e2..76941e7 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/6-MQTT.Designer.cs @@ -1,6 +1,4 @@ -using System.Globalization; - -namespace HASSAgent.Controls.Onboarding +namespace HASSAgent.Controls.Onboarding { partial class MQTT { @@ -32,7 +30,6 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MQTT)); this.PbHassAgentLogo = new System.Windows.Forms.PictureBox(); - this.TbIntMqttPort = new Syncfusion.Windows.Forms.Tools.IntegerTextBox(); this.TbMqttPassword = new System.Windows.Forms.TextBox(); this.TbMqttUsername = new System.Windows.Forms.TextBox(); this.TbMqttAddress = new System.Windows.Forms.TextBox(); @@ -46,8 +43,11 @@ private void InitializeComponent() this.label10 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); + this.NumMqttPort = new Syncfusion.Windows.Forms.Tools.NumericUpDownExt(); + this.PbShow = new System.Windows.Forms.PictureBox(); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntMqttPort)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NumMqttPort)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PbShow)).BeginInit(); this.SuspendLayout(); // // PbHassAgentLogo @@ -61,44 +61,13 @@ private void InitializeComponent() this.PbHassAgentLogo.TabIndex = 2; this.PbHassAgentLogo.TabStop = false; // - // TbIntMqttPort - // - this.TbIntMqttPort.BackGroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntMqttPort.BeforeTouchSize = new System.Drawing.Size(92, 25); - this.TbIntMqttPort.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbIntMqttPort.CurrentCultureRefresh = true; - this.TbIntMqttPort.FocusBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TbIntMqttPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.IntegerValue = ((long)(1883)); - this.TbIntMqttPort.Location = new System.Drawing.Point(220, 186); - this.TbIntMqttPort.MaxValue = ((long)(66000)); - this.TbIntMqttPort.Metrocolor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.MinValue = ((long)(1)); - this.TbIntMqttPort.Name = "TbIntMqttPort"; - this.TbIntMqttPort.PositiveColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.Size = new System.Drawing.Size(92, 25); - this.TbIntMqttPort.SpecialCultureValue = Syncfusion.Windows.Forms.Tools.SpecialCultureValues.InstalledCulture; - this.TbIntMqttPort.Style = Syncfusion.Windows.Forms.Tools.TextBoxExt.theme.Metro; - this.TbIntMqttPort.TabIndex = 1; - this.TbIntMqttPort.Text = "1,883"; - this.TbIntMqttPort.ThemeName = "Metro"; - this.TbIntMqttPort.ThemeStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.TbIntMqttPort.ThemeStyle.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.ThemeStyle.FocusedBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.ThemeStyle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.ThemeStyle.HoverBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.TbIntMqttPort.ThemeStyle.ZeroForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbIntMqttPort.ZeroColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - // // TbMqttPassword // this.TbMqttPassword.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttPassword.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttPassword.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttPassword.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttPassword.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttPassword.Location = new System.Drawing.Point(373, 245); + this.TbMqttPassword.Location = new System.Drawing.Point(373, 275); this.TbMqttPassword.Name = "TbMqttPassword"; this.TbMqttPassword.Size = new System.Drawing.Size(162, 25); this.TbMqttPassword.TabIndex = 4; @@ -108,9 +77,9 @@ private void InitializeComponent() // this.TbMqttUsername.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttUsername.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttUsername.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttUsername.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttUsername.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttUsername.Location = new System.Drawing.Point(183, 245); + this.TbMqttUsername.Location = new System.Drawing.Point(181, 275); this.TbMqttUsername.Name = "TbMqttUsername"; this.TbMqttUsername.Size = new System.Drawing.Size(160, 25); this.TbMqttUsername.TabIndex = 3; @@ -119,9 +88,9 @@ private void InitializeComponent() // this.TbMqttAddress.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttAddress.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttAddress.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttAddress.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttAddress.Location = new System.Drawing.Point(183, 143); + this.TbMqttAddress.Location = new System.Drawing.Point(181, 151); this.TbMqttAddress.Name = "TbMqttAddress"; this.TbMqttAddress.Size = new System.Drawing.Size(352, 25); this.TbMqttAddress.TabIndex = 0; @@ -129,10 +98,10 @@ private void InitializeComponent() // CbMqttTls // this.CbMqttTls.AutoSize = true; - this.CbMqttTls.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbMqttTls.Location = new System.Drawing.Point(373, 188); + this.CbMqttTls.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbMqttTls.Location = new System.Drawing.Point(374, 208); this.CbMqttTls.Name = "CbMqttTls"; - this.CbMqttTls.Size = new System.Drawing.Size(47, 21); + this.CbMqttTls.Size = new System.Drawing.Size(49, 23); this.CbMqttTls.TabIndex = 2; this.CbMqttTls.Text = "TLS"; this.CbMqttTls.UseVisualStyleBackColor = true; @@ -141,49 +110,49 @@ private void InitializeComponent() // label9 // this.label9.AutoSize = true; - this.label9.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label9.Location = new System.Drawing.Point(370, 225); + this.label9.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label9.Location = new System.Drawing.Point(373, 253); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(65, 17); + this.label9.Size = new System.Drawing.Size(67, 19); this.label9.TabIndex = 31; this.label9.Text = "password"; // // label8 // this.label8.AutoSize = true; - this.label8.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label8.Location = new System.Drawing.Point(180, 225); + this.label8.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label8.Location = new System.Drawing.Point(181, 253); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(65, 17); + this.label8.Size = new System.Drawing.Size(69, 19); this.label8.TabIndex = 30; this.label8.Text = "username"; // // label7 // this.label7.AutoSize = true; - this.label7.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label7.Location = new System.Drawing.Point(178, 188); + this.label7.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label7.Location = new System.Drawing.Point(182, 208); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(33, 17); + this.label7.Size = new System.Drawing.Size(35, 19); this.label7.TabIndex = 29; this.label7.Text = "port"; // // label6 // this.label6.AutoSize = true; - this.label6.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label6.Location = new System.Drawing.Point(180, 123); + this.label6.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label6.Location = new System.Drawing.Point(181, 129); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(148, 17); + this.label6.Size = new System.Drawing.Size(153, 19); this.label6.TabIndex = 28; this.label6.Text = "ip address or hostname"; // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(399, 100); + this.label1.Size = new System.Drawing.Size(569, 84); this.label1.TabIndex = 27; this.label1.Text = resources.GetString("label1.Text"); // @@ -191,9 +160,9 @@ private void InitializeComponent() // this.TbMqttDiscoveryPrefix.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbMqttDiscoveryPrefix.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbMqttDiscoveryPrefix.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbMqttDiscoveryPrefix.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbMqttDiscoveryPrefix.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbMqttDiscoveryPrefix.Location = new System.Drawing.Point(181, 304); + this.TbMqttDiscoveryPrefix.Location = new System.Drawing.Point(181, 350); this.TbMqttDiscoveryPrefix.Name = "TbMqttDiscoveryPrefix"; this.TbMqttDiscoveryPrefix.Size = new System.Drawing.Size(162, 25); this.TbMqttDiscoveryPrefix.TabIndex = 5; @@ -201,18 +170,18 @@ private void InitializeComponent() // label10 // this.label10.AutoSize = true; - this.label10.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label10.Location = new System.Drawing.Point(180, 284); + this.label10.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label10.Location = new System.Drawing.Point(180, 328); this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(100, 17); + this.label10.Size = new System.Drawing.Size(103, 19); this.label10.TabIndex = 33; this.label10.Text = "discovery prefix"; // // label2 // this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label2.Location = new System.Drawing.Point(349, 309); + this.label2.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label2.Location = new System.Drawing.Point(349, 355); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(135, 13); this.label2.TabIndex = 34; @@ -221,23 +190,64 @@ private void InitializeComponent() // label3 // this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(178, 341); + this.label3.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label3.Location = new System.Drawing.Point(181, 419); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(358, 13); this.label3.TabIndex = 35; this.label3.Text = "Tip: specialized settings can be found in the Configuration window."; // + // NumMqttPort + // + this.NumMqttPort.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.NumMqttPort.BeforeTouchSize = new System.Drawing.Size(83, 25); + this.NumMqttPort.Border3DStyle = System.Windows.Forms.Border3DStyle.Flat; + this.NumMqttPort.BorderColor = System.Drawing.SystemColors.WindowFrame; + this.NumMqttPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumMqttPort.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.NumMqttPort.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.NumMqttPort.Location = new System.Drawing.Point(223, 206); + this.NumMqttPort.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.NumMqttPort.MaxLength = 10; + this.NumMqttPort.MetroColor = System.Drawing.SystemColors.WindowFrame; + this.NumMqttPort.Name = "NumMqttPort"; + this.NumMqttPort.Size = new System.Drawing.Size(83, 25); + this.NumMqttPort.TabIndex = 72; + this.NumMqttPort.ThemeName = "Metro"; + this.NumMqttPort.Value = new decimal(new int[] { + 1883, + 0, + 0, + 0}); + this.NumMqttPort.VisualStyle = Syncfusion.Windows.Forms.VisualStyle.Metro; + // + // PbShow + // + this.PbShow.Cursor = System.Windows.Forms.Cursors.Hand; + this.PbShow.Image = global::HASSAgent.Properties.Resources.show_24; + this.PbShow.Location = new System.Drawing.Point(541, 275); + this.PbShow.Name = "PbShow"; + this.PbShow.Size = new System.Drawing.Size(24, 24); + this.PbShow.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.PbShow.TabIndex = 100; + this.PbShow.TabStop = false; + this.PbShow.Click += new System.EventHandler(this.PbShow_Click); + // // MQTT // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.PbShow); + this.Controls.Add(this.NumMqttPort); this.Controls.Add(this.label3); this.Controls.Add(this.label2); this.Controls.Add(this.TbMqttDiscoveryPrefix); this.Controls.Add(this.label10); - this.Controls.Add(this.TbIntMqttPort); this.Controls.Add(this.TbMqttPassword); this.Controls.Add(this.TbMqttUsername); this.Controls.Add(this.TbMqttAddress); @@ -248,14 +258,14 @@ private void InitializeComponent() this.Controls.Add(this.label6); this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "MQTT"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.MQTT_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.TbIntMqttPort)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NumMqttPort)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PbShow)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -263,7 +273,6 @@ private void InitializeComponent() #endregion private System.Windows.Forms.PictureBox PbHassAgentLogo; - private Syncfusion.Windows.Forms.Tools.IntegerTextBox TbIntMqttPort; private System.Windows.Forms.TextBox TbMqttPassword; private System.Windows.Forms.TextBox TbMqttUsername; private System.Windows.Forms.TextBox TbMqttAddress; @@ -277,5 +286,7 @@ private void InitializeComponent() private System.Windows.Forms.Label label10; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; + internal Syncfusion.Windows.Forms.Tools.NumericUpDownExt NumMqttPort; + private PictureBox PbShow; } } diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.cs b/src/HASSAgent/Controls/Onboarding/6-MQTT.cs similarity index 80% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.cs rename to src/HASSAgent/Controls/Onboarding/6-MQTT.cs index 5e90871..06f6582 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/6-MQTT.cs +++ b/src/HASSAgent/Controls/Onboarding/6-MQTT.cs @@ -1,7 +1,4 @@ -using System; -using System.Globalization; -using System.Windows.Forms; -using Serilog; +using Serilog; namespace HASSAgent.Controls.Onboarding { @@ -13,15 +10,10 @@ public partial class MQTT : UserControl public MQTT() { InitializeComponent(); - - TbIntMqttPort.Culture = CultureInfo.InstalledUICulture; } private void MQTT_Load(object sender, EventArgs e) { - // hide group seperator - TbIntMqttPort.NumberGroupSeparator = ""; - // let's see if we can get the host from the provided HASS uri if (!string.IsNullOrEmpty(Variables.AppSettings.HassUri)) { @@ -41,7 +33,7 @@ private void MQTT_Load(object sender, EventArgs e) // optionally set default port if (Variables.AppSettings.MqttPort < 1) Variables.AppSettings.MqttPort = 1883; - TbIntMqttPort.IntegerValue = Variables.AppSettings.MqttPort; + NumMqttPort.Value = Variables.AppSettings.MqttPort; CbMqttTls.Checked = Variables.AppSettings.MqttUseTls; TbMqttUsername.Text = Variables.AppSettings.MqttUsername; @@ -56,7 +48,7 @@ private void MQTT_Load(object sender, EventArgs e) internal bool Store() { Variables.AppSettings.MqttAddress = TbMqttAddress.Text; - Variables.AppSettings.MqttPort = (int)TbIntMqttPort.IntegerValue; + Variables.AppSettings.MqttPort = (int)NumMqttPort.Value; Variables.AppSettings.MqttUseTls = CbMqttTls.Checked; Variables.AppSettings.MqttUsername = TbMqttUsername.Text; Variables.AppSettings.MqttPassword = TbMqttPassword.Text; @@ -67,7 +59,9 @@ internal bool Store() private void CbMqttTls_CheckedChanged(object sender, EventArgs e) { if (_initializing) return; - TbIntMqttPort.IntegerValue = CbMqttTls.Checked ? 8883 : 1883; + NumMqttPort.Value = CbMqttTls.Checked ? 8883 : 1883; } + + private void PbShow_Click(object sender, EventArgs e) => TbMqttPassword.UseSystemPasswordChar = !TbMqttPassword.UseSystemPasswordChar; } } diff --git a/src/HASSAgent/Controls/Onboarding/6-MQTT.resx b/src/HASSAgent/Controls/Onboarding/6-MQTT.resx new file mode 100644 index 0000000..d3f7923 --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/6-MQTT.resx @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Commands and sensors are sent through MQTT. Please provide credentials for your server. If you're using the HA addon, you can probably use the preset address. + +Leave empty if you're not going to use commands and sensors. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs b/src/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs similarity index 87% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs rename to src/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs index 3dfa5bd..0258daf 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/7-HotKey.Designer.cs @@ -52,9 +52,9 @@ private void InitializeComponent() // this.TbQuickActionsHotkey.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); this.TbQuickActionsHotkey.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TbQuickActionsHotkey.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.TbQuickActionsHotkey.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.TbQuickActionsHotkey.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.TbQuickActionsHotkey.Location = new System.Drawing.Point(183, 180); + this.TbQuickActionsHotkey.Location = new System.Drawing.Point(180, 197); this.TbQuickActionsHotkey.Name = "TbQuickActionsHotkey"; this.TbQuickActionsHotkey.Size = new System.Drawing.Size(248, 25); this.TbQuickActionsHotkey.TabIndex = 0; @@ -62,19 +62,19 @@ private void InitializeComponent() // label5 // this.label5.AutoSize = true; - this.label5.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label5.Location = new System.Drawing.Point(180, 160); + this.label5.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label5.Location = new System.Drawing.Point(180, 175); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(122, 17); + this.label5.Size = new System.Drawing.Size(131, 19); this.label5.TabIndex = 12; this.label5.Text = "hotkey combination"; // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(401, 119); + this.label1.Size = new System.Drawing.Size(598, 76); this.label1.TabIndex = 11; this.label1.Text = "An easy way to pull up your quick actions is to use a global hotkey.\r\n\r\nThis way," + " whatever you\'re doing on your machine, you can always interact with Home Assist" + @@ -84,9 +84,9 @@ private void InitializeComponent() // this.BtnClear.AccessibleName = "Button"; this.BtnClear.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); - this.BtnClear.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.BtnClear.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.BtnClear.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); - this.BtnClear.Location = new System.Drawing.Point(437, 180); + this.BtnClear.Location = new System.Drawing.Point(434, 197); this.BtnClear.Name = "BtnClear"; this.BtnClear.Size = new System.Drawing.Size(102, 25); this.BtnClear.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); @@ -103,9 +103,9 @@ private void InitializeComponent() // // LblLanguageWarning // - this.LblLanguageWarning.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.LblLanguageWarning.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.LblLanguageWarning.ForeColor = System.Drawing.Color.OrangeRed; - this.LblLanguageWarning.Location = new System.Drawing.Point(180, 231); + this.LblLanguageWarning.Location = new System.Drawing.Point(180, 247); this.LblLanguageWarning.Name = "LblLanguageWarning"; this.LblLanguageWarning.Size = new System.Drawing.Size(401, 89); this.LblLanguageWarning.TabIndex = 13; @@ -121,11 +121,10 @@ private void InitializeComponent() this.Controls.Add(this.label5); this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "HotKey"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.HotKey_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); this.ResumeLayout(false); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.cs b/src/HASSAgent/Controls/Onboarding/7-HotKey.cs similarity index 91% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.cs rename to src/HASSAgent/Controls/Onboarding/7-HotKey.cs index d75fe71..7592988 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/7-HotKey.cs +++ b/src/HASSAgent/Controls/Onboarding/7-HotKey.cs @@ -1,14 +1,11 @@ -using System; -using System.Drawing; -using System.Windows.Forms; -using HASSAgent.Functions; +using HASSAgent.Functions; using WK.Libraries.HotkeyListenerNS; namespace HASSAgent.Controls.Onboarding { public partial class HotKey : UserControl { - private readonly HotkeySelector _hotkeySelector = new HotkeySelector(); + private readonly HotkeySelector _hotkeySelector = new(); public HotKey() { diff --git a/src/HASSAgent/Controls/Onboarding/7-HotKey.resx b/src/HASSAgent/Controls/Onboarding/7-HotKey.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/7-HotKey.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs b/src/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs similarity index 86% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs rename to src/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs index a4e642f..63caaeb 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/8-Updates.Designer.cs @@ -50,10 +50,10 @@ private void InitializeComponent() // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label1.Location = new System.Drawing.Point(180, 20); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(401, 128); + this.label1.Size = new System.Drawing.Size(607, 108); this.label1.TabIndex = 12; this.label1.Text = resources.GetString("label1.Text"); // @@ -62,10 +62,10 @@ private void InitializeComponent() this.CbNofityOnUpdate.AutoSize = true; this.CbNofityOnUpdate.Checked = true; this.CbNofityOnUpdate.CheckState = System.Windows.Forms.CheckState.Checked; - this.CbNofityOnUpdate.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbNofityOnUpdate.Location = new System.Drawing.Point(183, 151); + this.CbNofityOnUpdate.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbNofityOnUpdate.Location = new System.Drawing.Point(180, 160); this.CbNofityOnUpdate.Name = "CbNofityOnUpdate"; - this.CbNofityOnUpdate.Size = new System.Drawing.Size(204, 21); + this.CbNofityOnUpdate.Size = new System.Drawing.Size(215, 23); this.CbNofityOnUpdate.TabIndex = 26; this.CbNofityOnUpdate.Text = "yes, notify me on new updates"; this.CbNofityOnUpdate.UseVisualStyleBackColor = true; @@ -75,20 +75,20 @@ private void InitializeComponent() this.CbExecuteUpdater.AutoSize = true; this.CbExecuteUpdater.Checked = true; this.CbExecuteUpdater.CheckState = System.Windows.Forms.CheckState.Checked; - this.CbExecuteUpdater.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.CbExecuteUpdater.Location = new System.Drawing.Point(183, 296); + this.CbExecuteUpdater.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.CbExecuteUpdater.Location = new System.Drawing.Point(180, 358); this.CbExecuteUpdater.Name = "CbExecuteUpdater"; - this.CbExecuteUpdater.Size = new System.Drawing.Size(292, 21); + this.CbExecuteUpdater.Size = new System.Drawing.Size(305, 23); this.CbExecuteUpdater.TabIndex = 27; this.CbExecuteUpdater.Text = "yes, download and launch the installer for me"; this.CbExecuteUpdater.UseVisualStyleBackColor = true; // // label8 // - this.label8.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label8.Location = new System.Drawing.Point(180, 200); + this.label8.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label8.Location = new System.Drawing.Point(180, 238); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(401, 79); + this.label8.Size = new System.Drawing.Size(584, 81); this.label8.TabIndex = 31; this.label8.Text = resources.GetString("label8.Text"); // @@ -102,11 +102,10 @@ private void InitializeComponent() this.Controls.Add(this.CbNofityOnUpdate); this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Updates"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.Updates_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); this.ResumeLayout(false); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.cs b/src/HASSAgent/Controls/Onboarding/8-Updates.cs similarity index 85% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.cs rename to src/HASSAgent/Controls/Onboarding/8-Updates.cs index 2c619ef..6222513 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.cs +++ b/src/HASSAgent/Controls/Onboarding/8-Updates.cs @@ -1,7 +1,4 @@ -using System; -using System.Windows.Forms; - -namespace HASSAgent.Controls.Onboarding +namespace HASSAgent.Controls.Onboarding { public partial class Updates : UserControl { diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.resx b/src/HASSAgent/Controls/Onboarding/8-Updates.resx similarity index 52% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.resx rename to src/HASSAgent/Controls/Onboarding/8-Updates.resx index c2c677f..0aff18a 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/8-Updates.resx +++ b/src/HASSAgent/Controls/Onboarding/8-Updates.resx @@ -1,64 +1,4 @@ - - - + @@ -125,6 +65,8 @@ You'll get a notification (once per update) , letting you know a new version is Do you want to enable this functionality? - When there's an update, HASS.Agent will offer the option to open the release page. But if you want, HASS.Agent can also download and launch the installer for you - even less to do! The certificate of the downloaded file will get checked. + When there's an update, HASS.Agent will offer the option to open the release page. But if you want, HASS.Agent can also download and launch the installer for you - even less to do! + +The certificate of the downloaded file will get checked. \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.Designer.cs b/src/HASSAgent/Controls/Onboarding/9-Done.Designer.cs similarity index 84% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.Designer.cs rename to src/HASSAgent/Controls/Onboarding/9-Done.Designer.cs index 777b616..c249918 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.Designer.cs +++ b/src/HASSAgent/Controls/Onboarding/9-Done.Designer.cs @@ -53,20 +53,20 @@ private void InitializeComponent() // this.LblGitHub.AutoSize = true; this.LblGitHub.Cursor = System.Windows.Forms.Cursors.Hand; - this.LblGitHub.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.LblGitHub.Location = new System.Drawing.Point(180, 299); + this.LblGitHub.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point); + this.LblGitHub.Location = new System.Drawing.Point(180, 349); this.LblGitHub.Name = "LblGitHub"; - this.LblGitHub.Size = new System.Drawing.Size(162, 17); + this.LblGitHub.Size = new System.Drawing.Size(164, 19); this.LblGitHub.TabIndex = 26; this.LblGitHub.Text = "HASS.Agent GitHub page"; this.LblGitHub.Click += new System.EventHandler(this.LblGitHub_Click); // // label1 // - this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(180, 186); + this.label1.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(180, 228); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(400, 82); + this.label1.Size = new System.Drawing.Size(534, 70); this.label1.TabIndex = 25; this.label1.Text = "Thank you for using HASS.Agent, hopefully it\'ll be useful for you. \r\n\r\nIf you enc" + "ounter any problems, please create a ticket on the GitHub page."; @@ -74,7 +74,7 @@ private void InitializeComponent() // PbUpdate // this.PbUpdate.Image = global::HASSAgent.Properties.Resources.update; - this.PbUpdate.Location = new System.Drawing.Point(514, 20); + this.PbUpdate.Location = new System.Drawing.Point(705, 20); this.PbUpdate.Name = "PbUpdate"; this.PbUpdate.Size = new System.Drawing.Size(70, 70); this.PbUpdate.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -83,11 +83,10 @@ private void InitializeComponent() // // label2 // - this.label2.AutoSize = true; - this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); this.label2.Location = new System.Drawing.Point(180, 20); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(399, 136); + this.label2.Size = new System.Drawing.Size(547, 152); this.label2.TabIndex = 28; this.label2.Text = resources.GetString("label2.Text"); // @@ -101,11 +100,10 @@ private void InitializeComponent() this.Controls.Add(this.label1); this.Controls.Add(this.PbHassAgentLogo); this.Controls.Add(this.label2); - this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "Done"; - this.Size = new System.Drawing.Size(610, 364); + this.Size = new System.Drawing.Size(803, 457); this.Load += new System.EventHandler(this.Done_Load); ((System.ComponentModel.ISupportInitialize)(this.PbHassAgentLogo)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PbUpdate)).EndInit(); diff --git a/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.cs b/src/HASSAgent/Controls/Onboarding/9-Done.cs similarity index 81% rename from src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.cs rename to src/HASSAgent/Controls/Onboarding/9-Done.cs index 4818c7a..83d9a4b 100644 --- a/src/HASS.Agent/HASSAgent/Controls/Onboarding/9-Done.cs +++ b/src/HASSAgent/Controls/Onboarding/9-Done.cs @@ -1,6 +1,4 @@ -using System; -using System.Windows.Forms; -using HASSAgent.Functions; +using HASSAgent.Functions; namespace HASSAgent.Controls.Onboarding { diff --git a/src/HASSAgent/Controls/Onboarding/9-Done.resx b/src/HASSAgent/Controls/Onboarding/9-Done.resx new file mode 100644 index 0000000..cda67c6 --- /dev/null +++ b/src/HASSAgent/Controls/Onboarding/9-Done.resx @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + All done! + + +HASS.Agent will now restart to activate your configuration. + + +If you've enabled notifications, an elevation request will popup. This is required to allow HASS.Agent to listen on the specified port. + + \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.Designer.cs b/src/HASSAgent/Controls/QuickActionControl.Designer.cs similarity index 91% rename from src/HASS.Agent/HASSAgent/Controls/QuickActionControl.Designer.cs rename to src/HASSAgent/Controls/QuickActionControl.Designer.cs index 483fe26..999679f 100644 --- a/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.Designer.cs +++ b/src/HASSAgent/Controls/QuickActionControl.Designer.cs @@ -51,7 +51,7 @@ private void InitializeComponent() // this.LblEntity.BackColor = System.Drawing.Color.Transparent; this.LblEntity.Cursor = System.Windows.Forms.Cursors.Hand; - this.LblEntity.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.LblEntity.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); this.LblEntity.Location = new System.Drawing.Point(9, 180); this.LblEntity.Name = "LblEntity"; this.LblEntity.Size = new System.Drawing.Size(131, 60); @@ -64,7 +64,7 @@ private void InitializeComponent() // this.LblAction.BackColor = System.Drawing.Color.Transparent; this.LblAction.Cursor = System.Windows.Forms.Cursors.Hand; - this.LblAction.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.LblAction.Font = new System.Drawing.Font("Segoe UI Semibold", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point); this.LblAction.ForeColor = System.Drawing.Color.DarkGray; this.LblAction.Location = new System.Drawing.Point(0, 144); this.LblAction.Name = "LblAction"; @@ -83,7 +83,6 @@ private void InitializeComponent() this.Controls.Add(this.LblEntity); this.Controls.Add(this.PbImage); this.Cursor = System.Windows.Forms.Cursors.Hand; - this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); this.Name = "QuickActionControl"; this.Size = new System.Drawing.Size(152, 255); diff --git a/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.cs b/src/HASSAgent/Controls/QuickActionControl.cs similarity index 70% rename from src/HASS.Agent/HASSAgent/Controls/QuickActionControl.cs rename to src/HASSAgent/Controls/QuickActionControl.cs index 29dbfdc..2f2a9c2 100644 --- a/src/HASS.Agent/HASSAgent/Controls/QuickActionControl.cs +++ b/src/HASSAgent/Controls/QuickActionControl.cs @@ -1,8 +1,4 @@ -using System; -using System.Drawing; -using System.Threading.Tasks; -using System.Windows.Forms; -using HASSAgent.Enums; +using HASSAgent.Enums; using HASSAgent.Forms.QuickActions; using HASSAgent.HomeAssistant; using HASSAgent.Models.Internal; @@ -53,39 +49,19 @@ private void QuickActionControl_Load(object sender, EventArgs e) LblAction.Text = $"[{_quickAction.Action.ToString().ToUpper()}]"; LblEntity.Text = string.IsNullOrEmpty(_quickAction.Description) ? _quickAction.Entity : _quickAction.Description; - switch (_quickAction.Domain) + PbImage.Image = _quickAction.Domain switch { - case HassDomain.Automation: - PbImage.Image = Resources.qa_automate_225; - break; - case HassDomain.Cover: - PbImage.Image = Resources.qa_cover_225; - break; - case HassDomain.Climate: - PbImage.Image = Resources.qa_climate_225; - break; - case HassDomain.Script: - PbImage.Image = Resources.qa_script_225; - break; - case HassDomain.InputBoolean: - PbImage.Image = Resources.qa_inputboolean_225; - break; - case HassDomain.MediaPlayer: - PbImage.Image = Resources.qa_mediaplayer_225; - break; - case HassDomain.Scene: - PbImage.Image = Resources.qa_scene_225; - break; - case HassDomain.Switch: - PbImage.Image = Resources.qa_switch_225; - break; - case HassDomain.Light: - PbImage.Image = Resources.qa_light_225; - break; - default: - PbImage.Image = Resources.hass_avatar; - break; - } + HassDomain.Automation => Resources.qa_automate_225, + HassDomain.Cover => Resources.qa_cover_225, + HassDomain.Climate => Resources.qa_climate_225, + HassDomain.Script => Resources.qa_script_225, + HassDomain.InputBoolean => Resources.qa_inputboolean_225, + HassDomain.MediaPlayer => Resources.qa_mediaplayer_225, + HassDomain.Scene => Resources.qa_scene_225, + HassDomain.Switch => Resources.qa_switch_225, + HassDomain.Light => Resources.qa_light_225, + _ => Resources.hass_avatar + }; } /// diff --git a/src/HASSAgent/Controls/QuickActionControl.resx b/src/HASSAgent/Controls/QuickActionControl.resx new file mode 100644 index 0000000..b5ae26c --- /dev/null +++ b/src/HASSAgent/Controls/QuickActionControl.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/HASSAgent/Controls/Service/Commands.Designer.cs b/src/HASSAgent/Controls/Service/Commands.Designer.cs new file mode 100644 index 0000000..5768087 --- /dev/null +++ b/src/HASSAgent/Controls/Service/Commands.Designer.cs @@ -0,0 +1,272 @@ +namespace HASSAgent.Controls.Service +{ + partial class Commands + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Commands)); + this.ImgLv = new System.Windows.Forms.ImageList(this.components); + this.label1 = new System.Windows.Forms.Label(); + this.PbLowIntegrity = new System.Windows.Forms.PictureBox(); + this.LvCommands = new System.Windows.Forms.ListView(); + this.ClmId = new System.Windows.Forms.ColumnHeader(); + this.ClmName = new System.Windows.Forms.ColumnHeader("(none)"); + this.ClmType = new System.Windows.Forms.ColumnHeader("(none)"); + this.ClmLowIntegrity = new System.Windows.Forms.ColumnHeader("shield_16_header"); + this.ClmPadding = new System.Windows.Forms.ColumnHeader(); + this.BtnRemove = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnModify = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnAdd = new Syncfusion.WinForms.Controls.SfButton(); + this.BtnStore = new Syncfusion.WinForms.Controls.SfButton(); + this.LblStored = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.PbLowIntegrity)).BeginInit(); + this.SuspendLayout(); + // + // ImgLv + // + this.ImgLv.ColorDepth = System.Windows.Forms.ColorDepth.Depth24Bit; + this.ImgLv.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ImgLv.ImageStream"))); + this.ImgLv.TransparentColor = System.Drawing.Color.Transparent; + this.ImgLv.Images.SetKeyName(0, "shield_16_header"); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(813, 499); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(73, 15); + this.label1.TabIndex = 51; + this.label1.Text = "low integrity"; + // + // PbLowIntegrity + // + this.PbLowIntegrity.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.PbLowIntegrity.Image = global::HASSAgent.Properties.Resources.shield_16; + this.PbLowIntegrity.Location = new System.Drawing.Point(791, 498); + this.PbLowIntegrity.Name = "PbLowIntegrity"; + this.PbLowIntegrity.Size = new System.Drawing.Size(16, 16); + this.PbLowIntegrity.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + this.PbLowIntegrity.TabIndex = 50; + this.PbLowIntegrity.TabStop = false; + // + // LvCommands + // + this.LvCommands.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.LvCommands.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.ClmId, + this.ClmName, + this.ClmType, + this.ClmLowIntegrity, + this.ClmPadding}); + this.LvCommands.Dock = System.Windows.Forms.DockStyle.Top; + this.LvCommands.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.LvCommands.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.LvCommands.FullRowSelect = true; + this.LvCommands.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.LvCommands.HideSelection = true; + this.LvCommands.LargeImageList = this.ImgLv; + this.LvCommands.Location = new System.Drawing.Point(0, 0); + this.LvCommands.Name = "LvCommands"; + this.LvCommands.OwnerDraw = true; + this.LvCommands.Size = new System.Drawing.Size(903, 490); + this.LvCommands.SmallImageList = this.ImgLv; + this.LvCommands.TabIndex = 49; + this.LvCommands.UseCompatibleStateImageBehavior = false; + this.LvCommands.View = System.Windows.Forms.View.Details; + this.LvCommands.DoubleClick += new System.EventHandler(this.LvCommands_DoubleClick); + // + // ClmId + // + this.ClmId.Text = "id"; + this.ClmId.Width = 0; + // + // ClmName + // + this.ClmName.Text = "name"; + this.ClmName.Width = 400; + // + // ClmType + // + this.ClmType.Text = "type"; + this.ClmType.Width = 350; + // + // ClmLowIntegrity + // + this.ClmLowIntegrity.Text = ""; + // + // ClmPadding + // + this.ClmPadding.Text = ""; + this.ClmPadding.Width = 10000; + // + // BtnRemove + // + this.BtnRemove.AccessibleName = "Button"; + this.BtnRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.BtnRemove.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRemove.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnRemove.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRemove.Location = new System.Drawing.Point(3, 523); + this.BtnRemove.Name = "BtnRemove"; + this.BtnRemove.Size = new System.Drawing.Size(197, 35); + this.BtnRemove.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRemove.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRemove.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRemove.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRemove.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnRemove.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnRemove.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnRemove.TabIndex = 48; + this.BtnRemove.Text = "remove"; + this.BtnRemove.UseVisualStyleBackColor = false; + this.BtnRemove.Click += new System.EventHandler(this.BtnRemove_Click); + // + // BtnModify + // + this.BtnModify.AccessibleName = "Button"; + this.BtnModify.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.BtnModify.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnModify.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnModify.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnModify.Location = new System.Drawing.Point(501, 523); + this.BtnModify.Name = "BtnModify"; + this.BtnModify.Size = new System.Drawing.Size(197, 35); + this.BtnModify.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnModify.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnModify.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnModify.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnModify.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnModify.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnModify.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnModify.TabIndex = 47; + this.BtnModify.Text = "modify"; + this.BtnModify.UseVisualStyleBackColor = false; + this.BtnModify.Click += new System.EventHandler(this.BtnModify_Click); + // + // BtnAdd + // + this.BtnAdd.AccessibleName = "Button"; + this.BtnAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.BtnAdd.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnAdd.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnAdd.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnAdd.Location = new System.Drawing.Point(704, 523); + this.BtnAdd.Name = "BtnAdd"; + this.BtnAdd.Size = new System.Drawing.Size(197, 35); + this.BtnAdd.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnAdd.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnAdd.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnAdd.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnAdd.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnAdd.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnAdd.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnAdd.TabIndex = 46; + this.BtnAdd.Text = "add new"; + this.BtnAdd.UseVisualStyleBackColor = false; + this.BtnAdd.Click += new System.EventHandler(this.BtnAdd_Click); + // + // BtnStore + // + this.BtnStore.AccessibleName = "Button"; + this.BtnStore.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStore.Dock = System.Windows.Forms.DockStyle.Bottom; + this.BtnStore.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BtnStore.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStore.Location = new System.Drawing.Point(0, 575); + this.BtnStore.Name = "BtnStore"; + this.BtnStore.Size = new System.Drawing.Size(903, 47); + this.BtnStore.Style.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStore.Style.DisabledForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStore.Style.FocusedBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStore.Style.FocusedForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStore.Style.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStore.Style.HoverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(70))))); + this.BtnStore.Style.HoverForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.BtnStore.Style.PressedForeColor = System.Drawing.Color.Black; + this.BtnStore.TabIndex = 52; + this.BtnStore.Text = "send and activate commands"; + this.BtnStore.UseVisualStyleBackColor = false; + this.BtnStore.Click += new System.EventHandler(this.BtnStore_Click); + // + // LblStored + // + this.LblStored.AutoSize = true; + this.LblStored.Font = new System.Drawing.Font("Segoe UI", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.LblStored.ForeColor = System.Drawing.Color.LimeGreen; + this.LblStored.Location = new System.Drawing.Point(259, 523); + this.LblStored.Name = "LblStored"; + this.LblStored.Size = new System.Drawing.Size(185, 30); + this.LblStored.TabIndex = 99; + this.LblStored.Text = "commands stored!"; + this.LblStored.Visible = false; + // + // Commands + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48))))); + this.Controls.Add(this.LblStored); + this.Controls.Add(this.BtnStore); + this.Controls.Add(this.label1); + this.Controls.Add(this.PbLowIntegrity); + this.Controls.Add(this.LvCommands); + this.Controls.Add(this.BtnRemove); + this.Controls.Add(this.BtnModify); + this.Controls.Add(this.BtnAdd); + this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241))))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "Commands"; + this.Size = new System.Drawing.Size(903, 622); + this.Load += new System.EventHandler(this.Commands_Load); + this.Layout += new System.Windows.Forms.LayoutEventHandler(this.Commands_Layout); + ((System.ComponentModel.ISupportInitialize)(this.PbLowIntegrity)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private ImageList ImgLv; + private Label label1; + private PictureBox PbLowIntegrity; + private ListView LvCommands; + private ColumnHeader ClmId; + private ColumnHeader ClmName; + private ColumnHeader ClmType; + private ColumnHeader ClmLowIntegrity; + private ColumnHeader ClmPadding; + private Syncfusion.WinForms.Controls.SfButton BtnRemove; + private Syncfusion.WinForms.Controls.SfButton BtnModify; + private Syncfusion.WinForms.Controls.SfButton BtnAdd; + private Syncfusion.WinForms.Controls.SfButton BtnStore; + private Label LblStored; + } +} diff --git a/src/HASSAgent/Controls/Service/Commands.cs b/src/HASSAgent/Controls/Service/Commands.cs new file mode 100644 index 0000000..69a4bef --- /dev/null +++ b/src/HASSAgent/Controls/Service/Commands.cs @@ -0,0 +1,223 @@ +using HASSAgent.Commands; +using HASSAgent.Forms.Commands; +using HASSAgent.Functions; +using HASSAgent.Shared.Models.Config; +using Serilog; +using Syncfusion.Windows.Forms; + +namespace HASSAgent.Controls.Service +{ + public partial class Commands : UserControl + { + private string _deviceName; + private readonly List _commands = new(); + + private bool _storing = false; + + public Commands() + { + InitializeComponent(); + + BindListViewTheme(); + } + + private void BindListViewTheme() + { + LvCommands.DrawItem += ListViewTheme.DrawItem; + LvCommands.DrawSubItem += ListViewTheme.DrawSubItem; + LvCommands.DrawColumnHeader += ListViewTheme.DrawColumnHeader; + } + + private void Commands_Load(object sender, EventArgs e) + { + // + } + + /// + /// Load the provided commands + /// + /// + /// + public void SetCommands(List configuredCommands, string deviceName) + { + _deviceName = deviceName; + foreach (var command in configuredCommands) _commands.Add(command); + + UpdateCommandsList(); + } + + /// + /// Reload the commands + /// + private void UpdateCommandsList() + { + try + { + LvCommands.BeginUpdate(); + + // reload data + LvCommands.Items.Clear(); + + foreach (var command in _commands) + { + var lviCommand = new ListViewItem(command.Id.ToString()); + lviCommand.SubItems.Add(command.Name); + lviCommand.SubItems.Add(CommandsManager.CommandInfoCards[command.Type].Name); + lviCommand.SubItems.Add(command.RunAsLowIntegrity ? "√" : ""); + + LvCommands.Items.Add(lviCommand); + } + + LvCommands.EndUpdate(); + } + catch (NullReferenceException) + { + // whatever + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICECONFIG_COMMANDS] Error while updating: {err}", ex.Message); + } + } + + /// + /// Open a new form to modify the selected command + /// + private void ModifySelectedCommand() + { + // are we currently storing them? + if (_storing) return; + + // check for selected rows + if (LvCommands.SelectedItems.Count == 0) return; + + // we can just modify one, so the first + var guid = Guid.Parse(LvCommands.SelectedItems[0].Text); + var selectedCommand = (_commands).Find(x => x.Id == guid); + + // show modding form + using var command = new CommandsMod(selectedCommand, true, _deviceName); + var res = command.ShowDialog(); + if (res != DialogResult.OK) return; + + // update in temp list + _commands[_commands.FindIndex(x => x.Id == command.Command.Id)] = command.Command; + + // reload the gui list + UpdateCommandsList(); + } + + /// + /// Delete all selected commands + /// Note: doesn't actually execute deletion, that's done after the user clicks 'store' + /// + private void DeleteSelectedCommands() + { + // check for selected rows + if (LvCommands.SelectedItems.Count == 0) return; + + // iterate them + foreach (ListViewItem row in LvCommands.SelectedItems) + { + // get object + var guid = Guid.Parse(row.Text); + + // remove from the list + _commands.RemoveAt(_commands.FindIndex(x => x.Id == guid)); + } + + // reload the gui list + UpdateCommandsList(); + } + + /// + /// Show a form to add a new command + /// + /// + /// + private void BtnAdd_Click(object sender, EventArgs e) + { + using var command = new CommandsMod(true, _deviceName); + var res = command.ShowDialog(); + if (res != DialogResult.OK) return; + + // add to the temp list + _commands.Add(command.Command); + + // reload the gui list + UpdateCommandsList(); + } + + private void BtnModify_Click(object sender, EventArgs e) => ModifySelectedCommand(); + + private void BtnRemove_Click(object sender, EventArgs e) => DeleteSelectedCommands(); + + /// + /// Sends the current list to the service + /// + /// + /// + private async void BtnStore_Click(object sender, EventArgs e) + { + // lock interface + LockUi(); + + // store + var (storedOk, _) = await Task.Run(async () => await Variables.RpcClient.SetConfiguredCommandsAsync(_commands).WaitAsync(Variables.RpcConnectionTimeout)); + if (!storedOk) MessageBoxAdv.Show("An error occured while saving the commands, check the logs for more info.", "HASS.Agent", MessageBoxButtons.OK, MessageBoxIcon.Error); + else await ShowStored(); + + // done, unlock ui + UnlockUi(); + } + + private void LvCommands_DoubleClick(object sender, EventArgs e) => ModifySelectedCommand(); + + private void LockUi() + { + if (InvokeRequired) + { + Invoke(new MethodInvoker(LockUi)); + return; + } + + BtnStore.Text = "storing and registering, please wait .. "; + _storing = true; + + foreach (var button in Controls.OfType /// /// - internal static async Task SubscribeAsync(AbstractCommand command) + public async Task SubscribeAsync(AbstractCommand command) { - if (_mqttClient == null) return; - if (IsConnected) await _mqttClient.SubscribeAsync(((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic); + if (IsConnected()) await _mqttClient.SubscribeAsync(((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic); else { - while (IsConnected == false) await Task.Delay(250); + while (IsConnected() == false) await Task.Delay(250); await _mqttClient.SubscribeAsync(((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic); } } @@ -507,13 +488,12 @@ internal static async Task SubscribeAsync(AbstractCommand command) /// /// /// - internal static async Task UnubscribeAsync(AbstractCommand command) + public async Task UnubscribeAsync(AbstractCommand command) { - if (_mqttClient == null) return; - if (IsConnected) await _mqttClient.UnsubscribeAsync(((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic); + if (IsConnected()) await _mqttClient.UnsubscribeAsync(((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic); else { - while (IsConnected == false) await Task.Delay(250); + while (IsConnected() == false) await Task.Delay(250); await _mqttClient.UnsubscribeAsync(((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic); } } @@ -525,14 +505,14 @@ internal static async Task UnubscribeAsync(AbstractCommand command) private static ManagedMqttClientOptions GetOptions() { if (string.IsNullOrEmpty(Variables.AppSettings.MqttAddress)) return null; - + // id can be random, but we'll store it for consistency (unless user-defined) if (string.IsNullOrEmpty(Variables.AppSettings.MqttClientId)) { - Variables.AppSettings.MqttClientId = Guid.NewGuid().ToString().Substring(0, 8); + Variables.AppSettings.MqttClientId = Guid.NewGuid().ToString()[..8]; SettingsManager.StoreAppSettings(); } - + // configure last will message // todo: cover other domains var lastWillMessageBuilder = new MqttApplicationMessageBuilder() @@ -601,7 +581,7 @@ private static void HandleMessageReceived(MqttApplicationMessage applicationMess { if (((CommandDiscoveryConfigModel)command.GetAutoDiscoveryConfig()).Command_topic != applicationMessage.Topic) continue; - switch (Encoding.UTF8.GetString(applicationMessage?.Payload)) + switch (Encoding.UTF8.GetString(applicationMessage.Payload)) { case "ON": command.TurnOn(); diff --git a/src/HASS.Agent/HASSAgent/Models/Config/AppSettings.cs b/src/HASSAgent/Models/Config/AppSettings.cs similarity index 57% rename from src/HASS.Agent/HASSAgent/Models/Config/AppSettings.cs rename to src/HASSAgent/Models/Config/AppSettings.cs index ce4b0c0..c06a1bf 100644 --- a/src/HASS.Agent/HASSAgent/Models/Config/AppSettings.cs +++ b/src/HASSAgent/Models/Config/AppSettings.cs @@ -1,7 +1,4 @@ -using System; -using System.Text.RegularExpressions; -using HASSAgent.Enums; -using HASSAgent.Functions; +using HASSAgent.Enums; namespace HASSAgent.Models.Config { @@ -17,41 +14,43 @@ public AppSettings() public string DeviceName { get; set; } = Environment.MachineName; public bool CheckForUpdates { get; set; } = true; - public string LastUpdateNotificationShown { get; set; } + public string LastUpdateNotificationShown { get; set; } = string.Empty; public bool EnableExecuteUpdateInstaller { get; set; } = true; public bool ShowBetaUpdates { get; set; } public int DisconnectedGracePeriodSeconds { get; set; } = 60; public int ImageCacheRetentionDays { get; set; } = 7; - public string BrowserName { get; set; } - public string BrowserBinary { get; set; } - public string BrowserIncognitoArg { get; set; } + public string ServiceAuthId { get; set; } = string.Empty; + + public string BrowserName { get; set; } = string.Empty; + public string BrowserBinary { get; set; } = string.Empty; + public string BrowserIncognitoArg { get; set; } = string.Empty; + + public string CustomExecutorName { get; set; } = string.Empty; + public string CustomExecutorBinary { get; set; } = string.Empty; - public string CustomExecutorName { get; set; } - public string CustomExecutorBinary { get; set; } - public bool NotificationsEnabled { get; set; } = true; public int NotifierApiPort { get; set; } = 5115; public string HassUri { get; set; } = "http://homeassistant.local:8123"; - public string HassToken { get; set; } + public string HassToken { get; set; } = string.Empty; public bool HassAutoClientCertificate { get; set; } = false; - public string HassClientCertificate { get; set; } + public string HassClientCertificate { get; set; } = string.Empty; public bool QuickActionsHotKeyEnabled { get; set; } = true; - public string QuickActionsHotKey { get; set; } + public string QuickActionsHotKey { get; set; } = string.Empty; public string MqttAddress { get; set; } = "homeassistant.local"; public int MqttPort { get; set; } = 1883; public bool MqttUseTls { get; set; } public bool MqttAllowUntrustedCertificates { get; set; } = true; - public string MqttUsername { get; set; } - public string MqttPassword { get; set; } + public string MqttUsername { get; set; } = string.Empty; + public string MqttPassword { get; set; } = string.Empty; public string MqttDiscoveryPrefix { get; set; } = "homeassistant"; public string MqttClientId { get; set; } = string.Empty; public bool MqttUseRetainFlag { get; set; } = true; - public string MqttRootCertificate { get; set; } - public string MqttClientCertificate { get; set; } + public string MqttRootCertificate { get; set; } = string.Empty; + public string MqttClientCertificate { get; set; } = string.Empty; } } diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs b/src/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs similarity index 91% rename from src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs rename to src/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs index ecb297e..fc8c810 100644 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs +++ b/src/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/LaunchUrlCommand.cs @@ -1,6 +1,6 @@ using HASSAgent.Functions; using HASSAgent.Models.Internal; -using HASSAgent.Sensors; +using HASSAgent.Shared.Models.HomeAssistant.Commands; using Newtonsoft.Json; namespace HASSAgent.Models.HomeAssistant.Commands.InternalCommands diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs b/src/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs similarity index 87% rename from src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs rename to src/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs index 9ab3a9d..de47be4 100644 --- a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs +++ b/src/HASSAgent/Models/HomeAssistant/Commands/InternalCommands/PublishAllSensorsCommand.cs @@ -1,4 +1,5 @@ using HASSAgent.Sensors; +using HASSAgent.Shared.Models.HomeAssistant.Commands; namespace HASSAgent.Models.HomeAssistant.Commands.InternalCommands { diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/HassEntity.cs b/src/HASSAgent/Models/HomeAssistant/HassEntity.cs similarity index 100% rename from src/HASS.Agent/HASSAgent/Models/HomeAssistant/HassEntity.cs rename to src/HASSAgent/Models/HomeAssistant/HassEntity.cs diff --git a/src/HASS.Agent/HASSAgent/Models/HomeAssistant/Notification.cs b/src/HASSAgent/Models/HomeAssistant/Notification.cs similarity index 100% rename from src/HASS.Agent/HASSAgent/Models/HomeAssistant/Notification.cs rename to src/HASSAgent/Models/HomeAssistant/Notification.cs diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/Action.cs b/src/HASSAgent/Models/Internal/Action.cs similarity index 100% rename from src/HASS.Agent/HASSAgent/Models/Internal/Action.cs rename to src/HASSAgent/Models/Internal/Action.cs diff --git a/src/HASSAgent/Models/Internal/CommandInfoCard.cs b/src/HASSAgent/Models/Internal/CommandInfoCard.cs new file mode 100644 index 0000000..5f8782a --- /dev/null +++ b/src/HASSAgent/Models/Internal/CommandInfoCard.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HASSAgent.Functions; +using HASSAgent.Shared.Enums; + +namespace HASSAgent.Models.Internal +{ + public class CommandInfoCard + { + public CommandInfoCard() + { + // + } + + public CommandInfoCard(CommandType commandType, string description, bool agentCompatible, bool satelliteCompatible) + { + CommandType = commandType; + Name = HelperFunctions.ConvertCapitalizedEntityNameToReadable(commandType.ToString()); + Description = description; + AgentCompatible = agentCompatible; + SatelliteCompatible = satelliteCompatible; + } + + public CommandType CommandType { get; set; } + public string Name { get; set; } + public string Description { get; set; } + + public bool AgentCompatible { get; set; } + public bool SatelliteCompatible { get; set; } + } +} diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/ComponentStatusUpdate.cs b/src/HASSAgent/Models/Internal/ComponentStatusUpdate.cs similarity index 100% rename from src/HASS.Agent/HASSAgent/Models/Internal/ComponentStatusUpdate.cs rename to src/HASSAgent/Models/Internal/ComponentStatusUpdate.cs diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/PendingUpdate.cs b/src/HASSAgent/Models/Internal/PendingUpdate.cs similarity index 76% rename from src/HASS.Agent/HASSAgent/Models/Internal/PendingUpdate.cs rename to src/HASSAgent/Models/Internal/PendingUpdate.cs index f694e70..3aad3b9 100644 --- a/src/HASS.Agent/HASSAgent/Models/Internal/PendingUpdate.cs +++ b/src/HASSAgent/Models/Internal/PendingUpdate.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Octokit; +using Octokit; namespace HASSAgent.Models.Internal { diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/QuickAction.cs b/src/HASSAgent/Models/Internal/QuickAction.cs similarity index 81% rename from src/HASS.Agent/HASSAgent/Models/Internal/QuickAction.cs rename to src/HASSAgent/Models/Internal/QuickAction.cs index 17dfba4..34963ee 100644 --- a/src/HASS.Agent/HASSAgent/Models/Internal/QuickAction.cs +++ b/src/HASSAgent/Models/Internal/QuickAction.cs @@ -1,5 +1,4 @@ -using System; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using HASSAgent.Enums; using HASSAgent.Models.HomeAssistant; using Newtonsoft.Json; @@ -9,10 +8,7 @@ namespace HASSAgent.Models.Internal { public static class QuickActionExtensions { - public static HassEntity ToHassEntity(this QuickAction quickAction) - { - return new HassEntity(quickAction.Domain, quickAction.Entity); - } + public static HassEntity ToHassEntity(this QuickAction quickAction) => new(quickAction.Domain, quickAction.Entity); } [SuppressMessage("ReSharper", "InconsistentNaming")] diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/QuickActionPanelControl.cs b/src/HASSAgent/Models/Internal/QuickActionPanelControl.cs similarity index 100% rename from src/HASS.Agent/HASSAgent/Models/Internal/QuickActionPanelControl.cs rename to src/HASSAgent/Models/Internal/QuickActionPanelControl.cs diff --git a/src/HASSAgent/Models/Internal/SensorInfoCard.cs b/src/HASSAgent/Models/Internal/SensorInfoCard.cs new file mode 100644 index 0000000..5bfc899 --- /dev/null +++ b/src/HASSAgent/Models/Internal/SensorInfoCard.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HASSAgent.Functions; +using HASSAgent.Shared.Enums; + +namespace HASSAgent.Models.Internal +{ + public class SensorInfoCard + { + public SensorInfoCard() + { + // + } + + public SensorInfoCard(SensorType sensorType, string description, int refreshTimer, bool multiValue, bool agentCompatible, bool satelliteCompatible) + { + SensorType = sensorType; + Name = HelperFunctions.ConvertCapitalizedEntityNameToReadable(sensorType.ToString()); + Description = description; + RefreshTimer = refreshTimer; + MultiValue = multiValue; + AgentCompatible = agentCompatible; + SatelliteCompatible = satelliteCompatible; + } + + public SensorType SensorType { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public int RefreshTimer { get; set; } + + public bool MultiValue { get; set; } + + public bool AgentCompatible { get; set; } + public bool SatelliteCompatible { get; set; } + } +} diff --git a/src/HASS.Agent/HASSAgent/Models/Internal/UrlInfo.cs b/src/HASSAgent/Models/Internal/UrlInfo.cs similarity index 51% rename from src/HASS.Agent/HASSAgent/Models/Internal/UrlInfo.cs rename to src/HASSAgent/Models/Internal/UrlInfo.cs index 153894e..c1fffed 100644 --- a/src/HASS.Agent/HASSAgent/Models/Internal/UrlInfo.cs +++ b/src/HASSAgent/Models/Internal/UrlInfo.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace HASSAgent.Models.Internal +namespace HASSAgent.Models.Internal { public class UrlInfo { diff --git a/src/HASS.Agent/HASSAgent/Notifications/NotifierConfiguration.cs b/src/HASSAgent/Notifications/NotifierConfiguration.cs similarity index 100% rename from src/HASS.Agent/HASSAgent/Notifications/NotifierConfiguration.cs rename to src/HASSAgent/Notifications/NotifierConfiguration.cs diff --git a/src/HASS.Agent/HASSAgent/Notifications/NotifierDeserialization.cs b/src/HASSAgent/Notifications/NotifierDeserialization.cs similarity index 86% rename from src/HASS.Agent/HASSAgent/Notifications/NotifierDeserialization.cs rename to src/HASSAgent/Notifications/NotifierDeserialization.cs index 7ce585f..530985d 100644 --- a/src/HASS.Agent/HASSAgent/Notifications/NotifierDeserialization.cs +++ b/src/HASSAgent/Notifications/NotifierDeserialization.cs @@ -1,8 +1,5 @@ using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; namespace HASSAgent.Notifications { @@ -12,7 +9,7 @@ namespace HASSAgent.Notifications [SuppressMessage("ReSharper", "UnusedMember.Global")] public abstract class NotifierDeserialization { - public static JsonSerializerOptions SerializerOptions = new JsonSerializerOptions() + public static JsonSerializerOptions SerializerOptions = new() { PropertyNameCaseInsensitive = true }; diff --git a/src/HASS.Agent/HASSAgent/Notifications/NotifierEndpoints.cs b/src/HASSAgent/Notifications/NotifierEndpoints.cs similarity index 91% rename from src/HASS.Agent/HASSAgent/Notifications/NotifierEndpoints.cs rename to src/HASSAgent/Notifications/NotifierEndpoints.cs index fa6a92c..7be8266 100644 --- a/src/HASS.Agent/HASSAgent/Notifications/NotifierEndpoints.cs +++ b/src/HASSAgent/Notifications/NotifierEndpoints.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using Grapevine; +using Grapevine; using HASSAgent.Models.HomeAssistant; using Serilog; diff --git a/src/HASS.Agent/HASSAgent/Notifications/NotifierManager.cs b/src/HASSAgent/Notifications/NotifierManager.cs similarity index 85% rename from src/HASS.Agent/HASSAgent/Notifications/NotifierManager.cs rename to src/HASSAgent/Notifications/NotifierManager.cs index 464e73b..ece11a6 100644 --- a/src/HASS.Agent/HASSAgent/Notifications/NotifierManager.cs +++ b/src/HASSAgent/Notifications/NotifierManager.cs @@ -1,16 +1,16 @@ -using System; -using System.Diagnostics; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text; -using System.Threading.Tasks; using Grapevine; using HASSAgent.Enums; using HASSAgent.Functions; using HASSAgent.Models.HomeAssistant; +using HASSAgent.Shared.Functions; using Microsoft.Toolkit.Uwp.Notifications; using Newtonsoft.Json; using Serilog; +#pragma warning disable CA1416 // Validate platform compatibility namespace HASSAgent.Notifications { /// @@ -55,7 +55,7 @@ internal static void Initialize() }; // register shutdown event - Variables.NotificationServer.AfterStopping += (s) => + Variables.NotificationServer.AfterStopping += (_) => { if (Variables.ShuttingDown) return; @@ -110,7 +110,7 @@ internal static void Stop() /// Show a notification object as a toast message /// /// - internal static void ShowNotification(Notification notification) + internal static async void ShowNotification(Notification notification) { try { @@ -127,8 +127,8 @@ internal static void ShowNotification(Notification notification) // prepare image if (!string.IsNullOrWhiteSpace(notification.Image)) { - var imageOk = StorageManager.DownloadImage(notification.Image, out var localPath); - if (imageOk) toastBuilder.AddInlineImage(new Uri(localPath)); + var (success, localFile) = await StorageManager.DownloadImageAsync(notification.Image); + if (success) toastBuilder.AddInlineImage(new Uri(localFile)); else Log.Error("[NOTIFIER] Image download failed, dropping: {img}", notification.Image); } @@ -142,7 +142,6 @@ internal static void ShowNotification(Notification notification) // todo: unreliable toastBuilder.Show(toast => { - toast.ExpiresOnReboot = true; toast.ExpirationTime = DateTime.Now.AddSeconds(notification.Duration); }); @@ -150,10 +149,7 @@ internal static void ShowNotification(Notification notification) } // show indefinitely, but clear on reboot - toastBuilder.Show(toast => - { - toast.ExpiresOnReboot = true; - }); + toastBuilder.Show(); } catch (Exception ex) { @@ -169,26 +165,24 @@ internal static bool ExecuteElevatedPortReservation() { try { - using (var p = new Process()) - { - p.StartInfo.Verb = "runas"; - p.StartInfo.FileName = Variables.ApplicationExecutable; - p.StartInfo.Arguments = "portreservation"; + using var p = new Process(); + p.StartInfo.Verb = "runas"; + p.StartInfo.FileName = Variables.ApplicationExecutable; + p.StartInfo.Arguments = "portreservation"; - var success = p.Start(); - if (!success) - { - Log.Error("[NOTIFIER] Error while executing elevated port reservation"); - return false; - } + var success = p.Start(); + if (!success) + { + Log.Error("[NOTIFIER] Error while executing elevated port reservation"); + return false; + } - p.WaitForExit(); + p.WaitForExit(); - if (p.ExitCode != 0) Log.Warning("[NOTIFIER] Elevated port reservation executed with non-standard exitcode: {exitcode}", p.ExitCode); - else Log.Information("[NOTIFIER] Elevated port reservation executed succesfully"); + if (p.ExitCode != 0) Log.Warning("[NOTIFIER] Elevated port reservation executed with non-standard exitcode: {exitcode}", p.ExitCode); + else Log.Information("[NOTIFIER] Elevated port reservation executed succesfully"); - return p.ExitCode == 0; - } + return p.ExitCode == 0; } catch (Exception ex) { @@ -280,3 +274,4 @@ internal static async Task ExecutePortReservationAsync(int port) } } } +#pragma warning restore CA1416 // Validate platform compatibility diff --git a/src/HASSAgent/Program.cs b/src/HASSAgent/Program.cs new file mode 100644 index 0000000..8270cb2 --- /dev/null +++ b/src/HASSAgent/Program.cs @@ -0,0 +1,246 @@ +using System.Diagnostics; +using HASSAgent.Enums; +using HASSAgent.Forms; +using HASSAgent.Forms.ChildApplications; +using HASSAgent.Functions; +using HASSAgent.Settings; +using Serilog; + +namespace HASSAgent +{ + internal static class Program + { + /// + /// Main entry point + /// + [STAThread] + private static void Main(string[] args) + { + try + { + // syncfusion license + Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense(Variables.SyncfusionLicense); + + // get logging settings + Variables.ExtendedLogging = SettingsManager.GetExtendedLoggingSetting(); + + // enable logging + LoggingManager.PrepareLogging(); + + if (Variables.ExtendedLogging) + { + // make sure we catch 'm all + AppDomain.CurrentDomain.FirstChanceException += LoggingManager.CurrentDomainOnFirstChanceException; + } + else Log.Information("[PROGRAM] Extended logging disabled"); + + // prepare application + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + // set scaling + Application.SetHighDpiMode(HighDpiMode.DpiUnawareGdiScaled); + + // set default font + Application.SetDefaultFont(Variables.DefaultFont); + + // check to see if we're launched as a child application + if (LaunchedAsChildApplication(args)) + { + // yep, nothing left to do + return; + } + + // nope, prepare default application + Variables.MainForm = new Main(); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run (hidden) + Application.Run(new CustomApplicationContext(Variables.MainForm)); + } + catch (AccessViolationException ex) + { + Log.Fatal(ex, "[PROGRAM] AccessViolationException: {err}", ex.Message); + Log.CloseAndFlush(); + } + catch (Exception ex) + { + Log.Fatal(ex, "[PROGRAM] {err}", ex.Message); + Log.CloseAndFlush(); + } + } + + /// + /// Checks the provided arguments to see if we need to launch as a task-specific child application + /// + /// + /// + private static bool LaunchedAsChildApplication(string[] args) + { + try + { + // post-update + if (args.Any(x => x == "update")) + { + Log.Information("[SYSTEM] Post-update mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var postUpdate = new PostUpdate(); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(postUpdate); + + // done + return true; + } + + // port reservation + if (args.Any(x => x == "portreservation")) + { + Log.Information("[SYSTEM] Port reservation mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var portReservation = new PortReservation(); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(portReservation); + + // done + return true; + } + + // restart hass.agent + if (args.Any(x => x == "restart")) + { + Log.Information("[SYSTEM] Restart mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var restart = new Restart(); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(restart); + + // done + return true; + } + + // disable service + if (args.Any(x => x == "service_disable")) + { + Log.Information("[SYSTEM] Set service disabled mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var serviceState = new ServiceSetState(ServiceDesiredState.Disabled); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(serviceState); + + // done + return true; + } + + // enable service + if (args.Any(x => x == "service_enabled")) + { + Log.Information("[SYSTEM] Set service enabled mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var serviceState = new ServiceSetState(ServiceDesiredState.Automatic); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(serviceState); + + // done + return true; + } + + // start service + if (args.Any(x => x == "service_start")) + { + Log.Information("[SYSTEM] Start service mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var serviceState = new ServiceSetState(ServiceDesiredState.Started); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(serviceState); + + // done + return true; + } + + // stop service + if (args.Any(x => x == "service_stop")) + { + Log.Information("[SYSTEM] Stop service mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var serviceState = new ServiceSetState(ServiceDesiredState.Stopped); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(serviceState); + + // done + return true; + } + + // reinstall service + if (args.Any(x => x == "service_reinstall")) + { + Log.Information("[SYSTEM] Reinstall service mode activated"); + Variables.ChildApplicationMode = true; + + // prepare form + var serviceReinstall = new ServiceReinstall(); + + // prepare msgbox + HelperFunctions.SetMsgBoxStyle(Variables.DefaultFont); + + // run + Application.Run(serviceReinstall); + + // done + return true; + } + + // nothing, launch normally + return false; + } + catch (Exception ex) + { + Log.Fatal(ex, "[PROGRAM] Error while trying to determine child-application mode: {err}", ex.Message); + return false; + } + } + } +} \ No newline at end of file diff --git a/src/HASS.Agent/HASSAgent/Properties/Resources.Designer.cs b/src/HASSAgent/Properties/Resources.Designer.cs similarity index 70% rename from src/HASS.Agent/HASSAgent/Properties/Resources.Designer.cs rename to src/HASSAgent/Properties/Resources.Designer.cs index 30fcc5e..04bd4d0 100644 --- a/src/HASS.Agent/HASSAgent/Properties/Resources.Designer.cs +++ b/src/HASSAgent/Properties/Resources.Designer.cs @@ -60,6 +60,26 @@ internal Resources() { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap agent_16 { + get { + object obj = ResourceManager.GetObject("agent_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap agent_16_header { + get { + object obj = ResourceManager.GetObject("agent_16_header", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -150,6 +170,26 @@ internal static System.Drawing.Bitmap github_avatar { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap githubsponsors { + get { + object obj = ResourceManager.GetObject("githubsponsors", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap githubsponsors1 { + get { + object obj = ResourceManager.GetObject("githubsponsors1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -170,6 +210,26 @@ internal static System.Drawing.Bitmap hide_32 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap hotkey_16 { + get { + object obj = ResourceManager.GetObject("hotkey_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap hotkey_16_header { + get { + object obj = ResourceManager.GetObject("hotkey_16_header", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -200,6 +260,26 @@ internal static System.Drawing.Bitmap logo_32 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap multivalue_16 { + get { + object obj = ResourceManager.GetObject("multivalue_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap multivalue_16_header { + get { + object obj = ResourceManager.GetObject("multivalue_16_header", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -320,6 +400,26 @@ internal static System.Drawing.Bitmap radar_48 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap refresh_16 { + get { + object obj = ResourceManager.GetObject("refresh_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap refresh_16_header { + get { + object obj = ResourceManager.GetObject("refresh_16_header", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -330,6 +430,16 @@ internal static System.Drawing.Bitmap remote_48 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap reset_24 { + get { + object obj = ResourceManager.GetObject("reset_24", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -340,6 +450,66 @@ internal static System.Drawing.Bitmap restart_32 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap service_16 { + get { + object obj = ResourceManager.GetObject("service_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap service_16_header { + get { + object obj = ResourceManager.GetObject("service_16_header", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap service_48 { + get { + object obj = ResourceManager.GetObject("service_48", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap shield_16 { + get { + object obj = ResourceManager.GetObject("shield_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap shield_16_header { + get { + object obj = ResourceManager.GetObject("shield_16_header", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap show_24 { + get { + object obj = ResourceManager.GetObject("show_24", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/src/HASS.Agent/HASSAgent/Properties/Resources.resx b/src/HASSAgent/Properties/Resources.resx similarity index 76% rename from src/HASS.Agent/HASSAgent/Properties/Resources.resx rename to src/HASSAgent/Properties/Resources.resx index b386ad9..b1db95b 100644 --- a/src/HASS.Agent/HASSAgent/Properties/Resources.resx +++ b/src/HASSAgent/Properties/Resources.resx @@ -118,6 +118,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\agent_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\agent_16_header.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\bmac_logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -142,6 +148,12 @@ ..\Resources\gear_48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\githubsponsors.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\githubsponsors.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\github_avatar.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -151,6 +163,12 @@ ..\Resources\hide_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\hotkey_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\hotkey_16_header.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\logo_128.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -160,6 +178,12 @@ ..\Resources\logo_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\multivalue_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\multivalue_16_header.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\qa_automate_225.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -196,12 +220,39 @@ ..\Resources\radar_48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\refresh_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\refresh_16_header.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\remote_48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\reset_24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\restart_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\service_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\service_16_header.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\service_48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\shield_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\shield_16_header.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\show_24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\small_loader_32.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/src/HASSAgent/Resources/agent_16.png b/src/HASSAgent/Resources/agent_16.png new file mode 100644 index 0000000000000000000000000000000000000000..e523fdcd912222fbd9fe65520863e72ab6d6dd88 GIT binary patch literal 584 zcmV-O0=NB%P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0o_SNK~y+Tjgmh| zLQxdP-+Mmf4Pm;dLqkJDTT5d>TQ;@U&{R=FP!0`E4H69wP7)zOL(q^-5f%jz6$H5z z6x7gQq$2nSK@rq`M_(^r8Ti5BoOAE_zI*PuSLp?%QfatYEIwe{=8^@?^#4N0jYi|D z*=!z@j*&;&J3Szi$@CQph0lCGzb1LPT=tV!$Ol^mKsCJuAsL1d=EM)|KvmTTP1D9J zl}d{B1bNcsas|zDyMRef5T-G|6xZwZI|L$#rSSKiWPwe9A?@JY6wPI`S+v?GGJ|sj z{2q^Izg_u*-$N{5148!seC2AjIt6i*lP9~81(txcPw^gMT27X{Q-tBIv@7js3CL4H zdM3P~Sf0xg@p`>g$+^lZA~Wn8!uf_OWEL;DXVBqrJV}f#LYQaYkEO{c$fLyb_)7+R zTC3I0q(hC(Lu{Qp#^tGqQxpy{$XWcYkg+X@{p9b=V*`sholc!xQJH)U@1}!AHclwC zy)$hu<2G4;lX*Z~pwkh$xTcG^g1U~#5ti@vP1!eOpWo*eG2%yj0RJjn>mSH0IQhj) zZII#7L6|TJX;)%=6hHmvD|bUKmmAP^U8Wy^6q14Cm&i|B1-(M9BTq~F2`r>2it+{h WI5j<}D`RH>0000K$7(W+H#xNwqHqyc{u!UhTD_c$m zhG84q7y~Y5Gryvbx$ziYG2(mNckem(oO{PU*jY28pT)h!+4wyx#%7dXrS7fEi4t69 zDwX`V(&>z4y^KaTtyVJ9vF-g_?z~zJg5b1VejAUk8V#Ww=JS8KC#BN&V&S^(QK9fT zo1IlEsBD|&^KeLqyG|!g!3O!=Oa>TWC|~nA;D=sM@~@s3rvUSPpCsllYPH9HA4|j^ z(!|cFPBSTbbw-Kvlu`N7|t^K6j(B-U{6D;C!S?G1&)ueU@ExpcAo|VY+wc=U}j+_3ZMl76H9;@ zkV)BCf(jH=_~?6%!*bYz($bo1PhhNz{gY?;VHnau!)Q;ML%FQiWfraa?-R=VWWwI! HRm1oJ3>G7n literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/bmac_logo.png b/src/HASSAgent/Resources/bmac_logo.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/bmac_logo.png rename to src/HASSAgent/Resources/bmac_logo.png diff --git a/src/HASS.Agent/HASSAgent/Resources/bmac_logo_32.png b/src/HASSAgent/Resources/bmac_logo_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/bmac_logo_32.png rename to src/HASSAgent/Resources/bmac_logo_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/discord_avatar.png b/src/HASSAgent/Resources/discord_avatar.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/discord_avatar.png rename to src/HASSAgent/Resources/discord_avatar.png diff --git a/src/HASS.Agent/HASSAgent/Resources/done_32.png b/src/HASSAgent/Resources/done_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/done_32.png rename to src/HASSAgent/Resources/done_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/exit_24.png b/src/HASSAgent/Resources/exit_24.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/exit_24.png rename to src/HASSAgent/Resources/exit_24.png diff --git a/src/HASS.Agent/HASSAgent/Resources/exit_32.png b/src/HASSAgent/Resources/exit_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/exit_32.png rename to src/HASSAgent/Resources/exit_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/failed_32.png b/src/HASSAgent/Resources/failed_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/failed_32.png rename to src/HASSAgent/Resources/failed_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/gear_48.png b/src/HASSAgent/Resources/gear_48.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/gear_48.png rename to src/HASSAgent/Resources/gear_48.png diff --git a/src/HASS.Agent/HASSAgent/Resources/github_avatar.png b/src/HASSAgent/Resources/github_avatar.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/github_avatar.png rename to src/HASSAgent/Resources/github_avatar.png diff --git a/src/HASSAgent/Resources/githubsponsors.png b/src/HASSAgent/Resources/githubsponsors.png new file mode 100644 index 0000000000000000000000000000000000000000..fff038519f895eb38340ff2a7950a2754f0e7c26 GIT binary patch literal 9340 zcmcI~cQ{<#_wNXjs0ku^e?ycpX7pi*7DO-6q76n1M(-^IL68JN^qz$1C8GD5Ac#K7 z=q0-7?(rt?dwP>)sKTe>D1)-LQSf#~X?d$^n|nVs z7qwuOlwcP3gaZofQLad4PkTED7q};a^>4j!;QHz|gq8Vk5!a^(R;jBAne|lEnPt$< zC}tsEKCn3-pAfUKC@)k8;81?%KR>L%Y|a*za822V zf93+dAy}Nh=+#Bhn1*=89kikp4Eo-tk|x4laLa0tkb6A{`-6UcM`n{t;AB`JYAY?f;c_ zag}oiX8D8nzg6s_?d6DqXrf%uZqDW?Id_zUE89PlS(yJj*3r$`?r%#i%poW{lszEk z0sw>lJC&m~+7<0$jsCyb@$ch*t#O3QIHQoRXlHFS+U_4mssE#e83yC!XTGm%<6wdI zaN)c{^k)D{7U_yYumWC#f%*8sd?MOVz-2HvpC~sU6wb%@TT}&z0}G@p@;?(sTi957 z{U@R-DsV*y7gwZ%IZ9C$!3u!lwXv~)3z(S+A_W8l!R9DYAutRnfC7u~!vw)XFbkBW zC`=d%MZ*5Z1&o(Po4Z}ncQyWZ*jk{?0UiG`1Q!(*uoUL!=LZW|3JHRdFaapo%)$}{ z=7(9pkb)utqGqC&|7cTlwgFZS((b=%y+UOHXyk`lhzJUZK*8qx<|wcrN&pEq6Sfop zi<ZumHB_8kwM#`omJ2l0O$Pw^}eEv zjJh-0(#8&W;G!un&8#RVBLo!{0_^97UWGjX129*?#s%=P*Pn%?g>w3HWoN_ucXYy$ z=2wdX!D@aL4JZrNKeuiE8=C(!gMO>^utot&|A#2~E#`u@boD?wqok|=m;67Y5b}Qm z?}BvypP~O}5%T{L`X5@&t&t8^C?LZ^Sg(wMT;-zQPJ#TN{`&jbf5}__hy%&+>hj+# z41D=FkE0v_)y_bcCY!D)1A!Q!in3DLo++ED9=>`%SNF2jXE`a!%F-h})z95MW=@23$r<}&6N8T*A}<<^i`%3f3`6zAagNdl zBWG7uw%3TFXw#l2DX6f(xGZTvfml!|j+FwZR-STFSyYK}%-LCxJDF~ljQ(4{?`2-w zu;w{BtCiOp(B38|b*^|9aRkB?jlM+*)8ruE~vSkjk z9?2SqflQy3CDqi1ozh1=B$1bwSNMw@`4R1U0*uI0uCYu)>33PctOaa8*Vcx(&@a2* zgS+#ZIhSOo zL|xAMx4v;5eXe*`F|kuKcU97{pq7?wP=^>C{%)23_v4PFU(&HYyd!xjxXK~1}9472Bm zo)pAy@&t*gb!$K+jt9SW=|G>l?$E2)Jkomiy+SANddB*|6<^0QEp;->rtf}FV$j77 zbxr;<@cSDVjOg3!tY`)gugq_JbQF^0Dj|gNm-aOtmlE#hB{xDs@TtX*7zF$>6;+b8 zKWQ2ozMOwU?(g0Ug30S&-CQTrmc7HQb{;|jWdZQWx&mLk;D)O-~iO9W9h&J!}jQVme}52u%ycm`l;whTu=() zmvHpuMZsJ(`A17N#Se^fAtAE?3yHzO!EAb=oYi#=+A%FztRQ;O^+R{}SJVv$Mn+hE zpPw8ePP>1-B&YPEA;wLf2vF;+Q=naRdyn z8k=Zeb~AZoAQE28x7mRL3m+r83`TDQVOc9mIAv0Xj*@ zvkBHF^b&DWihYUklb02g`L8R%(vC|Y^_0Zmjp;#!)By6_FJ{u0gJ-c_7z#EK7f@G> zZ(!f21n_=AD`wi~m)Y1h*&^HpbmZMDymD$8kdv1?-gl&V;o<0@%4^x56xqK7saWg7 zc~CHdJP(cX6fER$z|`4jq?c=ke@hi3I3WoRx=l^3P*MH#7vpnRZyJ_VI9tw8?`IE5 zsbPuwhB)gd{j1y?xAK>}V7VvD{Qm4_M5o0Q)It||D_F{W4bMGjp`w!+DPyq+NqrHu zw-EtjvABwe^V5?N)C|C?UV~Y@oETvU{nwyiaFvy%rCCqKYFB@M@!LaAt#AGPowJ#( z+ml-X50vi^*0c+K(h1w4;J`Kq-(Y`oe4bCCE zXYR65!;eoIKc3aC7t_4G)^Q}74!dq?o9Je>l`X<~gA%|bRQ9Wl`oc)mZ?gvPKHN5K z9D}YxbFBURQOVu$k|z8i37u3+S=Z2-CI0OEq1nboTI9k zQWuUlTADAgC2Hxye0D3h@vdK&=89+L;GmMc^u;Ssk!DUxN=n=r1rjV>OJ`@k=3%Z? z4))u$=Txl+)A;!K_ODT9K4#Db4o*pRIR!X9F7f&PKC$C0^J|5HI(>c+aakFRjFK`W zx!R$%x0mSRg0{kLke;~pt(dW{c`*wVO4iNEX-eJHJ48eqK=Ka%MldqTc@x6L+fsi@ z@Y!RF@#l2yt=#Vf2e|9m{^t*XOdeU)xhg6v*Z!b?wHdU1a1fH8&k+$B>3FdAxUH?N zMT1?Y(cf=w#nfc={L^Rx>!K9lJa&sk;(~GC8$m1ZJ_ZyJaCCh93`sq>D~z6!_Vln4~tB!!kmptf_}HdOES$@*l=3j-Sqtr9u5@LvQ&c z1PoXW=yJtV3)$U|dvs6YNs0PEz0)51{QS=>so)do%4+P-+3r{lQ;>*=NQTW&9!Nyo zcmFm%zMSWoNU${o%1J}ahSLg4OG|r2$M~gX?RiW@DhvlEj@YGGS6yQ?@cmVY!sG|Kt(I;a5KJ#iab2$`)T&Wac0ftM!G7e z6nn?HPp;w+&bs)EzQf$S*O|nszTC;*yUoOO z3$!u}#akc!)P9Cf^yk`IL~bP2 zTy6qfFK*@(>wi|_Q=LKQbF>NzO=Ui*OOgpQIjO7Q6@3%iic zaA;H0gTAz5vWaRm2i%wnV$@RCzr-des8ZqE*xAX&nV zaB6CLXSJ^X#qP8TNl0*gf!t-g2$YjxZy6%H5YL@eB|t>l@ur<9Q>Osjle{%5M?_`X z_I^-7L80Qk)okEJqL5oeGmFko `YIvKm6JVC&JqaXd#CD5~y`Koin9~z&-I8@VQ zgRdXppW_oz%}rFUgFq07+Svtn0C9t`S=`D+BHTW7dkZzEv}4fE7#gZr-;-vtWcIGn z{rq~0sEbZlWJDd0!OZrrhd1G=@X*=FD7v1t>XOLTyssv6$)6^9Cj2v<%nOamX)zd# z;Lls!7QtU#8BVk!o=$(kn~9EWt!cb`*!k)HNGyQDVP-x58m0qHD6^nA`5yvLOCV9sR|sRZ62H zj)^_yIj}$qyc5{i2yUo9K3?CqX+ef7D%F<%Mz3tM=1Z`%0YLpo=REU*IlHlTX^YDtI~c9rom1$L5f}VU681YWXA`s z{8tGHx{D_`vsYQ|n_;#_w#%}rqnq2k2}M=K=BmvZgE*5a-`o)XEg+cBPY&nMVk!%@ zTONspePrnkzQ4{%K@W!VRJMD1Ay3Af#CS;?FP#kU=Z~(J+Ok6jI}2ndy?R zDvRleG9ll5C@1$s#3kxsl)vBU?E(mhSx}G!$d~*tpB;Pdn*HpnuM@`s70!iG^-eOW zrHMCpG6g(})9qTkxsG8#_&nEtd9|EgrKYM3Tfx&_>lQI{anXVXitL{}uiGc@TMV17 zCE3}Ih@q-ChV)(FNYssfapNvHdFbxs1iU?3w}DVw8D}H@nk-B)C`?5Pep2xua_KAh zgn^p+#a-~bY`MrK_E`EIZ!U4B!Z?aGiX@}RQ4V8cp37d9WSnh}B8G|Tu;NE@3r{QI zh5EHc&WDpAI?I(aoNs&`4|Kkkr%ur1(!j-Um1>FUM%HWPD_12ppC6twwL}C1jdlNVWbQbt>3;CO`RyCR^Q02OczjrFd7cWmfQ^|-jS~we|7qKUe?cTA0A$BnjJRD z-}!aCC*4p`z}+yhk53C^$Kg_cEY%TaHV22<_n2_w(kX^T^}a*r53otLO7ag-U{KIC z-?MJp3AYLBV)O81Skub!zp_Ovk-J+*Gm3G+#V)_9*-PinVnm{Qe#1 zl>_fWJ;fqwTA1f;i4>?&$=0{jTI$ng&pDjE#TPeIM2?wU0|bZd#CzLxb6e`vB&8;+ z?3>DXM4~D7dnOy7G>j8|D%v=DI#PD;N0B~>mDR;q_t&rOK$(S|&s72)QCt=jSDSv@ z&}YXgOi%!XN3D+%AV11~_&|;D=Gjr->o}kb(&FrIsHo7+atH{xv=zVX3u)d(&4G>< ztCJhKA}5QDYf?-mtn<*ky>E+|d%_jR@dwNNN^J|w0=$kXI9_(HXt0Hx1&5KE56<6{ zz6c?@l+)H0FsQJ0$d#Bxa+=a6%-wQ-qQF4wlQG*PGsv)AI6wBC`j?-On90v6npk$# zCMpvLa{Fa>LwbkK_BkM$GJ*2acHw57u&;>T+k0!!bnln6qSxwu4#;W0Cu^Kx+ z@L7XRLyTP|B~ZxTfXE$qqnVyma6Xq&Q&uM5)z^`Zv(mroU2nVs0bOOdtE)zBF8ofX z&vZ;Nbi!ytl;2~nzC;NU@^IPrjlfI1FBL(=Z`Dt>?=R|3Tpa37vBsZ3vOdbn%$(74 z`fD~*Mivoy7aXYh;ZBFv2W_*#7W|d*g6fQNAl4EQPuW2)qL=g2`$8T)R8}mmUAuhw=0G z8nKzA-CPduA~v$~{b+UxWHmf1hhd*`6O*>~c4R+>3BO+Q@`MOjd<9O8)?mTI*vgg6 zs26qF*9-fK%-XpKxyysid)FfAq8SCrYu$ZgMty#9>8b%0a%%?!YTKuGhl(npKx`%T zS=MA2F|BOLDtx}y0~=mf@^c#8Q_d5~65I`c6Z_`V#9*eMPo%xSzdxQ83Po_~?!t!d z%+AUlTt5&lu|KVT5gjchC55B+Hbj<{?4ocSYWg66b>{x`7q<{;m?yvFmxC%F@+)jhQ`VG#}iR?J?c?DyEuDVD^`6+-U69PFLE z$q(bSU>F%l`+Ta+P|jYaN?YPwYg<`uGsLb}XU($ImlOpoVxSOXWo0E#VB?u#jEacp z@R-?ZN*v67aq<$_0nPpV$vctuFq_2{0MdkW9}K=H&G76Q&Z|ecS%)VlC**EZYRZ4@ zsihZ^^V3SyirMp%Bf%OmsPYi@47%8vEM>jYF(RGAmgWp|O8 z6OMCy==6AnS*BS?VVi=gqLhi#-qwmF$8yhkmU#j~!rml$^@?z;Ep0c2Pi)+cnax&`sa?~gpJw0*kL0ny; zqn#a(zl3vz!9=m0*JU7RaJQjh;fVcSWK8iVr}1h-V%(=n8^gcw?-+XN*_XP8C)4*d zK(@E(Hy(E_u27S=NN$@^FDxz0E_7ec?g>5(_uRlR{X+I74oZ7zeOT8V{phEv>UMLw zu#krjRAB%voo*j*|5)F#7%k1vF=_hx$>Y#x)&X+uuOxlPY605x&W~v|D#yn3+B!PS zhL*nSRXXEK8+#Mb2lA93*)RmBnr+s8{(SpOjapjM*RNl*z;BUhwgHx?*m4UF4vvD8 zZPd2-0hS?I;e^y-sJ!C)c+yKgH&%LkyW0eIPQhzmdQtYLPvmB6^ zz08alv0@C~KRgVArah$%RZvnYw>7c6t{)cTH2$uV=2hi|KG(Hb^G=yC;*J?BHS^;# z$NlwDT>-<)ku^S-CA&;D2@FQIVF!==spQuUhO7O}pr~iBT5~-1aLn3-tg z#4u-Dh%CS`{#R5C_#RIO7kkemD5R|KCp2jTttYA^ZAbPDW{2t-%mai zA)yCVGI=4#tI?8a;@#!emjiRH&yBM~r7REi4RjZ=D!f!b3USYf*mbkAc=n5pYgOx{ z*4EYtbH6JJEST0Kppo2GTkl`9g*yv7VA>|!)-}u$bKkAc)TRf9MBXJsy%VxAn@)Q) z<|BMj^!SwLY}YhIgF^BVRXg)fDPSVs@)zj|7wS6OQ^ATbSqG%l6%{_9h}50 zw=WELRPhSo^`?LSQ2Wx3L|@*ma&o9=gQU~%^cGMpIm^n*W|aUt%SP`_T6SgTRJ|=s zJ#aRPcH4D2J0jpQtiy{LVhYBJOsOd}wJB=7xDiHJLvQq@fwkm#EgsS^^&BWJ2&yw| zY+|6u`M>6c%ASt$ZVUSi7>r*;cE`WJube7mbaZNg5noZ!F^OAK0$Wye#A@e$4Es54 zLRt0H4gNA+gzOg6u9B{jlG4uJV0N2u6^`l3084yTG1sZb{(BAC9}C@DPWRR#93$!I z=psK1EuLnR-;8ScP;0J$HLPmMH|mXJhKIE`#%hSr_0#DC zn-i6h-MtF&B{9!RNN4WfAf=b}J*&4}Rg<&xr>b^7;JP9K*ss>q)QnXJNDA4VW$kVT zH{MiDf-@*8D$X{s07dzpM6w#st?Plp##{DU7X!3PQB+`w#U`2`KF%*UOL?BpWQzKj zH7zDI?#H|yZ}w8>+v-aXM)=!G)*V<%(u=$5S?@JHyKKd271j<43VM|s+Zu2=r5sAi zs2pAWf?nc`f|Ti^+xD^}nhv){*)l~oQ!4m6HOzv~eG9|3!lO?ceNU-1JWMPPWHu^L2q%02IYequIrasGmzCvterm0Hld@HPxq zEuXD{-K@q`z|(a4i>)d=0KbTM?^Dg21zenYr3ia&!y9nD_0S_ob}0 zD;xCx1bdOtKss`XQwYq+>2-XmNJxs-^y;w4Tv zwFn$;Hd>UrGFh#L?-s9UY6=nxs3dSGTH+4os>(N-tg@bvJ@a@N8L7m@V={86+-`!6 zdCi7_RJY|QQh+78k)I^uAB6zt0llA!?I){_W^u7{*-Pgp$98K2qKOa9?cQyk#W^OA z&}d5T9>(;$giaQ!mh8Fs|2$O4A-9_nCPjA^)TewWLU&I($Tuht~WR@ zYw&%k#SUwsL1~KxiO2W_^Jc>BU+QxBchY#o+!;Nrri0t)*D^@kU-!d z&3Eni!6FuyBlo-Q@dfU6LMH_P1)C%T`L5gXv4XO~14KOGqu7Iic*RIUqSuLW&wY&~ z>ip{F=6+tpL@P=8OEBi=vzo7b|&VrVzF@} zsUyhc!VK>Q2qLstJVu;okYI^kp6POB9PeS@_+UE`z`QyTaIyMIWlZj>1>~O7(SH3h zVklTnYV?=W(-Qn zPVWPaE2X0|xr{jXK(h}3FmZVTpQbsZGPN?LLwXuzmFd3>_Wtf`O?0u7rsA|F za{Xz7wH1Qf{H(8fSaEs%X%lDY2+hCyUp>&?XSkr?gc|@fW#A~;LT7u6`1PNrR)=&~ zZq8>s5QnEXX6J9cs3%Kr-jE04UaD)eyZF*Q@RX8bQ9i4e`g?R4*ag^mfu8qTlvR)4 zZB`+5o?Td_S)C>R+4xT<%sz?9DhC&2fF~^4bq&;80=G{SI@92~<#l;SUwR3o^DHU84YXbt#xoc`TE{%3&IYhQx_RWWN!Abw+Bil$Dh^a`2MU z&?L>#i_`$eq8&D3pff+H8E4P7IjQ0JNRvABcXQ8)bh)WpKXim9Rn+v5ZIETtAmAEE zqjVJ0(+~N}Oh{;$?26-ybQE8pA$z1X+0+7a-@+vh30GEv!6KjD)&B=6%Bjj0Nt*`! EFV~VooB#j- literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/hass_avatar.png b/src/HASSAgent/Resources/hass_avatar.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/hass_avatar.png rename to src/HASSAgent/Resources/hass_avatar.png diff --git a/src/HASS.Agent/HASSAgent/Resources/hide_32.png b/src/HASSAgent/Resources/hide_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/hide_32.png rename to src/HASSAgent/Resources/hide_32.png diff --git a/src/HASSAgent/Resources/hotkey_16.png b/src/HASSAgent/Resources/hotkey_16.png new file mode 100644 index 0000000000000000000000000000000000000000..39be96b79d6425162b821330e8976fb6444f32e0 GIT binary patch literal 341 zcmV-b0jmCqP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0P0CZK~y+T<&d!s z!B7~5drbzT&CYT+uq>!<&q@XTK-Bo=Uj;I@PQnbmZfo;&6kjM@i4gF)lo?fO=Z4pM%Hkj<+}IM zy*gcxCW{DS*gzHLwpN}(84BRLd_j~B=&`Yf5}SQoZy1srmb=)9^@7|Yr`>i=1;QDQ z=K43C#pNl-_`%j$*FUS*BmV&8LHUz(CMP3g$m0+pJD^XpUgarghd5^M2t}q&RCp(P nHEcy^t&G?Gfcxz~RS?_&e-Wk0R49&;00000NkvXXu0mjfo1u^% literal 0 HcmV?d00001 diff --git a/src/HASSAgent/Resources/hotkey_16_header.bmp b/src/HASSAgent/Resources/hotkey_16_header.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a6b1d211fbd472de0ee41f29c12522a27e2d05d5 GIT binary patch literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7>E=;{swbnWWZyLUj~=8YRSu3ra| zKy>~3_1m{^-@0`RNCFigd-MDE?>l$w*uHIBRYgT%etvObArR%~=5E}uVM2fZl*yC- z|NoDy{@K%~yLRr}x@AjSOG|laDNt8!b#+Nm(T?rgCr_L>W7@QL@7^J+fAsL->Xj>( zEm;yD8@p=d%8s@+pe~?wX(=g-7cE+|diBGH57E@GShj4*;>FRCkt>!j?`Urass~z^ zm7cz6;lhFk*^Ky>cxSu_Sv3a9{C K{m^AIFaQAgRvsn* literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/logo_128.png b/src/HASSAgent/Resources/logo_128.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/logo_128.png rename to src/HASSAgent/Resources/logo_128.png diff --git a/src/HASS.Agent/HASSAgent/Resources/logo_256.png b/src/HASSAgent/Resources/logo_256.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/logo_256.png rename to src/HASSAgent/Resources/logo_256.png diff --git a/src/HASS.Agent/HASSAgent/Resources/logo_32.png b/src/HASSAgent/Resources/logo_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/logo_32.png rename to src/HASSAgent/Resources/logo_32.png diff --git a/src/HASSAgent/Resources/multivalue_16.png b/src/HASSAgent/Resources/multivalue_16.png new file mode 100644 index 0000000000000000000000000000000000000000..4ae33b33d3d5054c28fd4ae00a14765e47dcd78d GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc!AMUR#}EtuQ{?-H5LY&bk4&n1 ljm$y9LT#5li&>eO8TNbl?te7f*9&L~gQu&X%Q~loCIBYwH_re7 literal 0 HcmV?d00001 diff --git a/src/HASSAgent/Resources/multivalue_16_header.bmp b/src/HASSAgent/Resources/multivalue_16_header.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2a7405a9a5ceaf67077c17f30eb78582046faa96 GIT binary patch literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=ALfH#umF%S(A9;bk3;~tVju&k9GQ#BhAV&@ zjHw1$1X(>$9L_~ngUp5-3sFg=dbr7>>X8Ez5-i9e31kxk;Ngj88ZsAX4ulI~5NRw) OCd17qXgIRN7#IMx>SN{r literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_automate_225.png b/src/HASSAgent/Resources/qa_automate_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_automate_225.png rename to src/HASSAgent/Resources/qa_automate_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_climate_225.png b/src/HASSAgent/Resources/qa_climate_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_climate_225.png rename to src/HASSAgent/Resources/qa_climate_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_cover_225.png b/src/HASSAgent/Resources/qa_cover_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_cover_225.png rename to src/HASSAgent/Resources/qa_cover_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_inputboolean_225.png b/src/HASSAgent/Resources/qa_inputboolean_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_inputboolean_225.png rename to src/HASSAgent/Resources/qa_inputboolean_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_light_225.png b/src/HASSAgent/Resources/qa_light_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_light_225.png rename to src/HASSAgent/Resources/qa_light_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_mediaplayer_225.png b/src/HASSAgent/Resources/qa_mediaplayer_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_mediaplayer_225.png rename to src/HASSAgent/Resources/qa_mediaplayer_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_scene_225.png b/src/HASSAgent/Resources/qa_scene_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_scene_225.png rename to src/HASSAgent/Resources/qa_scene_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_script_225.png b/src/HASSAgent/Resources/qa_script_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_script_225.png rename to src/HASSAgent/Resources/qa_script_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/qa_switch_225.png b/src/HASSAgent/Resources/qa_switch_225.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/qa_switch_225.png rename to src/HASSAgent/Resources/qa_switch_225.png diff --git a/src/HASS.Agent/HASSAgent/Resources/question_24.png b/src/HASSAgent/Resources/question_24.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/question_24.png rename to src/HASSAgent/Resources/question_24.png diff --git a/src/HASS.Agent/HASSAgent/Resources/question_32.png b/src/HASSAgent/Resources/question_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/question_32.png rename to src/HASSAgent/Resources/question_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/radar_48.png b/src/HASSAgent/Resources/radar_48.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/radar_48.png rename to src/HASSAgent/Resources/radar_48.png diff --git a/src/HASSAgent/Resources/refresh_16.png b/src/HASSAgent/Resources/refresh_16.png new file mode 100644 index 0000000000000000000000000000000000000000..474f1f015278165716194985f9ff43a0b8462d9c GIT binary patch literal 569 zcmV-90>=G`P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0nSN8K~y+Tjgmb` zf>9WSKlM`-92^=O9D;%tgP;bXh6ceJ0*8hmm$rt6#)g)rmY^wWC>$!HsUV`3XedaB zrUHd%N+@thF#mhb=QRx!I&e7mzW4pR@4Z$pG@DJkR;#_jrdX|33)q6@_^*|T5u;_NXC(tOi zPm<3E0)dH-Na;knv}Uogc! z3EOih!Gt8#Qp?VSWZpYH%E@`>W; zrfj{y{r3qRfJ0Q@Hs%)06PCF98k&Gd@Eum^@E$J0BwPKFSrgXz%7T6v?WI`exu;$u z4K*;?)wU+T?Dcvt(B8l)NQDimU84n6WPQhcw$#3HGq9{5ePW7(tg=h&00000NkvXX Hu0mjfR!RGf literal 0 HcmV?d00001 diff --git a/src/HASSAgent/Resources/refresh_16_header.bmp b/src/HASSAgent/Resources/refresh_16_header.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8817d6f0f64f4f9f8163c4ef67714fe2af89a653 GIT binary patch literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7>E=<3oFRaI1M+^}Kw%9Sfutk|@1 zV{>C89^2>6o_*}tv1wDL%$z=b!TkAiX3svbfB%YQ%MA7OFm+W|R-Qa@V)m?AH*ehd z0|t*CJ(@LR#=!#zdb+zY)$iZ8Z^rcLpFVwpD29+9KYoO0!Bh`)EfB3+yLQ9+^}l}o zg6rC~bLZMMYcSPs-?nY%jva~d@j$8g*x1jXKSQ(t)vsT-4paT1Lxw@8;ri_|TzcOP4NQ zv}o1JmB5e$Y6LPaUA*Yw>WZm8JTw#-L_lRghXFmZeA%)+yLSUaz~9#wQ!!A)#Ly5J r1!2L#o^Eb`|NaF!J~BKUt4cJ%l*Gj6&!4}3{W>Qr3r&g+Tm}XJRqH7Z literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/remote_48.png b/src/HASSAgent/Resources/remote_48.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/remote_48.png rename to src/HASSAgent/Resources/remote_48.png diff --git a/src/HASSAgent/Resources/reset_24.png b/src/HASSAgent/Resources/reset_24.png new file mode 100644 index 0000000000000000000000000000000000000000..4b047f47484125bf5a5e18c75f2be8c85a3bdc08 GIT binary patch literal 818 zcmV-21I_%2P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0>?>2K~zXf)s;PH zQ&AMhUtSzung%*3c8K5*p+km-CLu!x1483gkwU>mCkc{4P^3c#aZu1w2M0l+h1Nlg zD0DF55XXFy4jCL;x@73kL1;l_=oe(x#!$>&OPUzd#~}Y;nMt6 zMEI1l4|9dR7W z;9!1gYHCv%`=D4X&QZGOh<+AvKN^j`bSw^f0#K6kuqq_ZXG#0B=+8p6S{-Y(TI(z( zPBv*Wd8JK;iPKeGYXjpOm>*gg)VUxO3jOqWJl7F72(pB~3CBVJoJv=GLb;7`23o=S zGsiqQg2CWEEai-hCCycUk6MKlZ{SFYm3et85xmM*fJ21 zK>)Vw^?K(V&Cqx+9~woK-IUbGA}a&1fxJMFD|Ew})(r&?UsnF_-e}bYl}bfc{{Nxp z9Mo#HQQZx{1^K_xXh;iK0F8H$#pFlMaB#$8vASf=B4@QqL6u6&3Z$BY z#W`#t+O+0q2ZPkV*=&|@8X!;_)wEQkI|D%qqs{I3t@}PX3v%jh+x~#V2^Kd`Hm~(w zUh2s}fMdB4zc5*@ipLzB7pJ{irBdlC>3yh)#b|C59H7ho8_0A#W*VTwBG_W%F@07*qoM6N<$g8grH5C8xG literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/restart_32.png b/src/HASSAgent/Resources/restart_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/restart_32.png rename to src/HASSAgent/Resources/restart_32.png diff --git a/src/HASSAgent/Resources/service_16.png b/src/HASSAgent/Resources/service_16.png new file mode 100644 index 0000000000000000000000000000000000000000..d37bd3b5bd5d72fa4a5e5284b1730d27b4fd55c3 GIT binary patch literal 519 zcmV+i0{H!jP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0h~!hK~y+TbyG1* z!%z@TN+}MN#-gC0;Nak3po`$p(ZSKd#ofit!9{TC=HTAZQHOw|tKi^Ze?SL8!KKBt zNkhOuLgRPueSJ2y{or`_-MhPYcez-zh~s!Y48!Ywzh9+EAqavK-}g63=L1fc2>uz3 zMtKxPcQjkW;jk$-N;}W+r?LcnKf5-czYWJov;MaL`R&`Q&E3(jlc=irm%Rrp>|w`>gM z1?M)zOc()I=<$YB0qq?j*%PVY8PbykA5bKL!FW7g0YXv(_juU@ZrNsEwQ7+ZFR?|qMXtkSIJBYz?8j%gw+>lgb&&eAb|jJf~-002ov JPDHLkV1g=G<1PRI literal 0 HcmV?d00001 diff --git a/src/HASSAgent/Resources/service_16_header.bmp b/src/HASSAgent/Resources/service_16_header.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1cc122b6e0fe9b61251f62a756869693ea1533cb GIT binary patch literal 824 zcmZuv&r1S96yE9{9s3iy2n)&5!a}mp%@&eQLO1CkN#aey4x)%*NH^(bCp#GS2N=p` zU>Is(7{;?L`%cHhqLp4Hk926--O=YrV|0U z)L4wRu4z}r;#0SKXc&a-tLj6$eUZ&FhXpf{cpr~{qxIbDomke9Y2LS5gun@GnGE49 zohH@VI}Ag35c!ZlCX=;ffWyH+A|ssVdCdP>EN0UwKanc)Q6@HWCavQ*$c?mCGWj{5 z6Molh8oCbrd%0vk5TtIvMARav#Mk0+4o!lX7z&s86jU_%S*hF0 ykO>pec4R9eg?wHLQL9#iAb`nZr$Z|KRQRQme%D9Rt?aPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Vu?iK~!i%)tWtM z6j2bzb4Q9RQlvN`g<=H36cGYOh>#+MMZgq+D4d`W!6u!Bg=HX!g@r{5?a~MqA}T3T zSVTx5g#-h!P@NQ znqlE^qF=ds|KX$%}g5L1XHKL!+0Cn)`OW8{N|8Mo`nF!A13%bdK}TK z&s^XzwIDOX-2$hk06noJ_$Wr-Eb`Vpq;c@*w zU8fH5^toi@5K0(99sdu{n?5>sDFzpSelK&P(9t2klRB`GaL*?&9-eJ$C9P% z;oA#wbAuK2Xx<7LK^u0+@dWZ)*VT1^&Ya>7d7Py)0brk}^*NF3y z;xe*@Xvf(@{Q!D`d&6iai1jX?&!4qRuc8lef)3DPR_&QaXrz(NvX>LJjv(NyRi*;} zdE~f-iv*W$?6r8M2LC4(&TGIMt51xQw=jvpH+9G1yNl}b0#Q(pEO>VkfX_A(yXWg6 zL>K;{3s*BNdH-~!LM!ln&mumNb3O`UjFdyggB&-JL30m+%_Iix zZ3=dasKBN#0EUs1(HVYIYepp4l^@ze zgf$@UL;1zDGjxU)yhyMM92^81fYBc-Hid@9vWrRT^P#YB;vLgX3F{39q9074(*h$E zHUhC406K}w3hk33Avc}u`S3M>7J6%eT{Z>VOICD-SQA!k3U(K*7=)Wel27z0iM{jj zAYlfG6S?kG2z`B1uOMlbbnPl5U%8FIS0k=(-9+G{(~{~wNI_C>Z}FY;0;K@=>2j3h z@Vo1%@^KFruG?w(2Nsz|VB3jI;}?7C)PwJmh4UKFZ}q7mhNj?%g=`2mny!hbO+Cc8 ztayh%DHnN7MJ5mhv0tE`5v%e^DT>tVwW~K*iF<*Qz9bOq8!=8HwZ)VMl+?2SggcgY zZ3L*)yxgQ!u~x-aL5_RmsACmxbgK)Qh695#N3&bUTe)!J)dTqx>3mgZg8XuOGgb6~x>^rjQHB zBg8v86qJ?I)%xU{!f@#TY6j=PXPoM|7wbDV3gYY{I!y3wNx0UD#Z6=dxnL8j1~=~U)XT~ O0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0Xa!TK~y+Tm6D-u z!eA7I+XgX#m>3=s5)5Jjfv8~bz>AO|cn8cJau0y0nVA|1OCSM3f*6K?n1ciaf@Dd% z@814U^3%Y2lGA&8&$+j^{p;L97=}&w7DZ9sl>P^r>M)>DK|YsZq&Z_b!<7qy4{M|q z=)104mAVZ)KZJL<#50CpDlq*MF%#%nNw01o1DMv39BoF}OP+!Ue053itv$~xY1P_5 z2ic(B!B>kd$p)UP))Uc-HYqRQQ4KM+aybpqn+wQvn*r-T5l@g08V^8NO3a9404ok8 zX2geF^b`bql#N;O1*E<8lBgP*5)h+|>16Ve;`=IBUh9Ml0`=)HcasB|nk4E=<3oL#Y9G)JaOXO*|Vw1$po#Q zI(hQHfB*i20g$n3Z0>Dtw+moHxil5H(5A3l8e@%=ld`kz03 z01XWE_lHY4*xIJ2rhfhU6(|lDgfk${0D5ro!i7r~Edu&_)5eWQj~s!B!0xl!7b6WSAKnPo6k& R&8k&S_V$>vv=(7t007bTIuHN= literal 0 HcmV?d00001 diff --git a/src/HASSAgent/Resources/show_24.png b/src/HASSAgent/Resources/show_24.png new file mode 100644 index 0000000000000000000000000000000000000000..e8e6ad5901ef70acc9fa01a049c206daed21b725 GIT binary patch literal 693 zcmV;m0!safP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0!m3lK~zXf?UX%e zQ&AMhZ(iPDNCFNH9SUY}=#asXPd5V{>QJblD7fe#xCku>PDLC-3Q{aMxU`#tL&1(6 z3K^DffGVV7sd5*< z#`Y!aJpx^b%(>4DhTMd*#JRZ^!P#IiNN2OzV-YYs(^?-)Y~)&O+fKuth)l3eDk)k_ zz->_&v?Gzo(quns$K-hYioqsLUMD`+$tF_J40^ts+u>ag4GzPOwsb5$Q;ZD@dDfw9|R>|EZ2 z&6`+59~WEDK6J}fZ+?>P8~K(~x~3hYT!kD&MTQbu$J3j<7GuH!yVV#ees+<)g4g00000NkvXXu0mjfi#s{V literal 0 HcmV?d00001 diff --git a/src/HASS.Agent/HASSAgent/Resources/small_loader_32.gif b/src/HASSAgent/Resources/small_loader_32.gif similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/small_loader_32.gif rename to src/HASSAgent/Resources/small_loader_32.gif diff --git a/src/HASS.Agent/HASSAgent/Resources/ti_exit_32.png b/src/HASSAgent/Resources/ti_exit_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/ti_exit_32.png rename to src/HASSAgent/Resources/ti_exit_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/ti_gear_32.png b/src/HASSAgent/Resources/ti_gear_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/ti_gear_32.png rename to src/HASSAgent/Resources/ti_gear_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/ti_radar_32.png b/src/HASSAgent/Resources/ti_radar_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/ti_radar_32.png rename to src/HASSAgent/Resources/ti_radar_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/ti_remote_32.png b/src/HASSAgent/Resources/ti_remote_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/ti_remote_32.png rename to src/HASSAgent/Resources/ti_remote_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/ti_update_32.png b/src/HASSAgent/Resources/ti_update_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/ti_update_32.png rename to src/HASSAgent/Resources/ti_update_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/ti_workflow_32.png b/src/HASSAgent/Resources/ti_workflow_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/ti_workflow_32.png rename to src/HASSAgent/Resources/ti_workflow_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/todo_32.png b/src/HASSAgent/Resources/todo_32.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/todo_32.png rename to src/HASSAgent/Resources/todo_32.png diff --git a/src/HASS.Agent/HASSAgent/Resources/update.png b/src/HASSAgent/Resources/update.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/update.png rename to src/HASSAgent/Resources/update.png diff --git a/src/HASS.Agent/HASSAgent/Resources/workflow_48.png b/src/HASSAgent/Resources/workflow_48.png similarity index 100% rename from src/HASS.Agent/HASSAgent/Resources/workflow_48.png rename to src/HASSAgent/Resources/workflow_48.png diff --git a/src/HASSAgent/Sensors/SensorsManager.cs b/src/HASSAgent/Sensors/SensorsManager.cs new file mode 100644 index 0000000..729fb5e --- /dev/null +++ b/src/HASSAgent/Sensors/SensorsManager.cs @@ -0,0 +1,559 @@ +using HASSAgent.Extensions; +using HASSAgent.Models.Internal; +using HASSAgent.Settings; +using HASSAgent.Shared.Enums; +using HASSAgent.Shared.Extensions; +using HASSAgent.Shared.Models.Config; +using Serilog; + +namespace HASSAgent.Sensors +{ + /// + /// Continuously performs sensor autodiscovery and state publishing + /// + internal static class SensorsManager + { + internal static readonly Dictionary SensorInfoCards = new(); + + private static bool _active = true; + private static bool _pause; + + private static DateTime _lastAutoDiscoPublish = DateTime.MinValue; + + /// + /// Initializes the sensor manager + /// + internal static async void Initialize() + { + // wait while mqtt's connecting + while (Variables.MqttManager.GetStatus() == MqttStatus.Connecting) await Task.Delay(250); + + // start background processing + _ = Task.Run(Process); + } + + /// + /// Stop processing sensor states + /// + internal static void Stop() => _active = false; + + /// + /// Pause processing sensor states + /// + internal static void Pause() => _pause = true; + + /// + /// Resume processing sensor states + /// + internal static void Unpause() => _pause = false; + + /// + /// Unpublishes all single- and multivalue sensors + /// + /// + internal static async Task UnpublishAllSensors() + { + // unpublish the autodisco's + if (SingleValueSensorsPresent()) foreach (var sensor in Variables.SingleValueSensors) await sensor.UnPublishAutoDiscoveryConfigAsync(); + if (MultiValueSensorsPresent()) foreach (var sensor in Variables.MultiValueSensors) await sensor.UnPublishAutoDiscoveryConfigAsync(); + } + + /// + /// Continously processes sensors (autodiscovery, states) + /// + private static async void Process() + { + // we use the firstrun flag to publish our state without respecting the time elapsed/value change check + // otherwise, the state might stay in 'unknown' in HA until the value changes + var firstRun = true; + var firstRunDone = false; + + while (_active) + { + try + { + await Task.Delay(TimeSpan.FromMilliseconds(750)); + + // are we paused? + if (_pause) continue; + + // is mqtt available? + if (Variables.MqttManager.GetStatus() != MqttStatus.Connected) + { + // nothing to do + continue; + } + + // optionally flag as the first real run + if (!firstRunDone) firstRunDone = true; + + // publish availability & sensor autodisco's every 30 sec + if ((DateTime.Now - _lastAutoDiscoPublish).TotalSeconds > 30) + { + // let hass know we're still here + await Variables.MqttManager.AnnounceAvailabilityAsync(); + + // publish the autodisco's + if (SingleValueSensorsPresent()) + { + foreach (var sensor in Variables.SingleValueSensors.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await sensor.PublishAutoDiscoveryConfigAsync(); + } + } + + if (MultiValueSensorsPresent()) + { + foreach (var sensor in Variables.MultiValueSensors.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await sensor.PublishAutoDiscoveryConfigAsync(); + } + } + + // log moment + _lastAutoDiscoPublish = DateTime.Now; + } + + if (_pause) continue; + + // publish sensor states (they have their own time-based scheduling) + if (SingleValueSensorsPresent()) + { + foreach (var sensor in Variables.SingleValueSensors.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await sensor.PublishStateAsync(!firstRun); + } + } + + // check if there are multivalue sensors + if (!MultiValueSensorsPresent()) continue; + + foreach (var sensor in Variables.MultiValueSensors.TakeWhile(_ => !_pause).TakeWhile(_ => _active)) + { + if (_pause || Variables.MqttManager.GetStatus() != MqttStatus.Connected) continue; + await sensor.PublishStatesAsync(!firstRun); + } + } + catch (Exception ex) + { + Log.Fatal(ex, "[SENSORSMANAGER] Error while publishing: {err}", ex.Message); + } + finally + { + // check if we need to take down the 'first run' flag + if (firstRunDone && firstRun) firstRun = false; + } + } + } + + /// + /// Resets all sensor checks (last sent and previous value), so they'll all be published again + /// + internal static void ResetAllSensorChecks() + { + try + { + // pause processing + Pause(); + + // reset single-value sensors + if (SingleValueSensorsPresent()) + { + foreach (var sensor in Variables.SingleValueSensors) sensor.ResetChecks(); + } + + // reset multi-value sensors + if (MultiValueSensorsPresent()) + { + foreach (var sensor in Variables.MultiValueSensors) sensor.ResetChecks(); + } + + // done + } + catch (Exception ex) + { + Log.Fatal(ex, "[SENSORSMANAGER] Error while resetting all sensor checks: {err}", ex.Message); + } + finally + { + // resume processing + Unpause(); + } + } + + /// + /// Stores the provided sensors, and (re)publishes them + /// + /// + /// + /// + internal static async Task StoreAsync(List sensors, List toBeDeletedSensors = null) + { + toBeDeletedSensors ??= new List(); + + try + { + // pause processing + Pause(); + + // process the to-be-removed + if (toBeDeletedSensors.Any()) + { + foreach (var sensor in toBeDeletedSensors.Where(sensor => sensor != null)) + { + if (sensor.IsSingleValue()) + { + var abstractSensor = StoredSensors.ConvertConfiguredToAbstractSingleValue(sensor); + + // remove and unregister + await abstractSensor.UnPublishAutoDiscoveryConfigAsync(); + Variables.SingleValueSensors.RemoveAt(Variables.SingleValueSensors.FindIndex(x => x.Id == abstractSensor.Id)); + + Log.Information("[SENSORS] Removed single-value sensor: {sensor}", abstractSensor.Name); + } + else + { + var abstractSensor = StoredSensors.ConvertConfiguredToAbstractMultiValue(sensor); + + // remove and unregister + await abstractSensor.UnPublishAutoDiscoveryConfigAsync(); + Variables.MultiValueSensors.RemoveAt(Variables.MultiValueSensors.FindIndex(x => x.Id == abstractSensor.Id)); + + Log.Information("[SENSORS] Removed multi-value sensor: {sensor}", abstractSensor.Name); + } + } + } + + // copy our list to the main one + foreach (var sensor in sensors.Where(sensor => sensor != null)) + { + if (sensor.IsSingleValue()) + { + var abstractSensor = StoredSensors.ConvertConfiguredToAbstractSingleValue(sensor); + if (Variables.SingleValueSensors.All(x => x.Id != abstractSensor.Id)) + { + // new, add and register + Variables.SingleValueSensors.Add(abstractSensor); + await abstractSensor.PublishAutoDiscoveryConfigAsync(); + await abstractSensor.PublishStateAsync(false); + + Log.Information("[SENSORS] Added single-value sensor: {sensor}", abstractSensor.Name); + continue; + } + + // existing, update and re-register + var currentSensorIndex = Variables.SingleValueSensors.FindIndex(x => x.Id == abstractSensor.Id); + if (Variables.SingleValueSensors[currentSensorIndex].Name != abstractSensor.Name) + { + // name changed, unregister + Log.Information("[SENSORS] Single-value sensor changed name, re-registering as new entity: {old} to {new}", Variables.SingleValueSensors[currentSensorIndex].Name, abstractSensor.Name); + + await Variables.SingleValueSensors[currentSensorIndex].UnPublishAutoDiscoveryConfigAsync(); + } + + Variables.SingleValueSensors[currentSensorIndex] = abstractSensor; + await abstractSensor.PublishAutoDiscoveryConfigAsync(); + await abstractSensor.PublishStateAsync(false); + + Log.Information("[SENSORS] Modified single-value sensor: {sensor}", abstractSensor.Name); + } + else + { + var abstractSensor = StoredSensors.ConvertConfiguredToAbstractMultiValue(sensor); + if (Variables.MultiValueSensors.All(x => x.Id != abstractSensor.Id)) + { + // new, add and register + Variables.MultiValueSensors.Add(abstractSensor); + await abstractSensor.PublishAutoDiscoveryConfigAsync(); + await abstractSensor.PublishStatesAsync(false); + + Log.Information("[SENSORS] Added multi-value sensor: {sensor}", abstractSensor.Name); + continue; + } + + // existing, update and re-register + var currentSensorIndex = Variables.MultiValueSensors.FindIndex(x => x.Id == abstractSensor.Id); + if (Variables.MultiValueSensors[currentSensorIndex].Name != abstractSensor.Name) + { + // name changed, unregister + Log.Information("[SENSORS] Multi-value sensor changed name, re-registering as new entity: {old} to {new}", Variables.MultiValueSensors[currentSensorIndex].Name, abstractSensor.Name); + + await Variables.MultiValueSensors[currentSensorIndex].UnPublishAutoDiscoveryConfigAsync(); + } + + Variables.MultiValueSensors[currentSensorIndex] = abstractSensor; + await abstractSensor.PublishAutoDiscoveryConfigAsync(); + await abstractSensor.PublishStatesAsync(false); + + Log.Information("[SENSORS] Modified multi-value sensor: {sensor}", abstractSensor.Name); + } + } + + // annouce ourselves + await Variables.MqttManager.AnnounceAvailabilityAsync(); + + // store to file + StoredSensors.Store(); + + // done + return true; + } + catch (Exception ex) + { + Log.Fatal(ex, "[SENSORSMANAGER] Error while storing: {err}", ex.Message); + return false; + } + finally + { + // resume processing + Unpause(); + } + } + + private static bool SingleValueSensorsPresent() => Variables.SingleValueSensors != null && Variables.SingleValueSensors.Any(); + private static bool MultiValueSensorsPresent() => Variables.MultiValueSensors != null && Variables.MultiValueSensors.Any(); + + /// + /// Returns default information for the specified sensor type, or null if not found + /// + /// + /// + internal static SensorInfoCard GetSensorDefaultInfo(SensorType type) => SensorInfoCards.ContainsKey(type) ? SensorInfoCards[type] : null; + + /// + /// Loads info regarding the various sensor types + /// + internal static void LoadSensorInfo() + { + // ================================= + + var sensorInfoCard = new SensorInfoCard(SensorType.ActiveWindowSensor, + "Provides the title of the current active window.", + 15, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.AudioSensors, + "Provides information various aspects of your device's audio:\r\n\r\nCurrent peak volume level (can be used as a simple 'is something playing' value).\r\n\r\nDefault audiodevice: name, state and volume.\r\n\r\nSummary of your audio sessions: application name, muted state, volume and current peak volume.", + 20, true, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.BatterySensors, + "Provides a sensor with the current charging status, estimated amount of minutes on a full charge, remaining charge in percentage, remaining charge in minutes and the powerline status.", + 30, true, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.CpuLoadSensor, + "Provides the current load of the first CPU as a percentage.", + 30, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.CurrentClockSpeedSensor, + "Provides the current clockspeed of the first CPU.", + 300, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.CurrentVolumeSensor, + "Provides the current volume level as a percentage.\r\n\r\nCurrently takes the volume of your default device.", + 15, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.DisplaySensors, + "Provides a sensor with the amount of displays, name of the primary display, and per display its name, resolution and bits per pixel.", + 15, true, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.DummySensor, + "Dummy sensor for testing purposes, sends a random integer value between 0 and 100.", + 5, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.GpuLoadSensor, + "Provides the current load of the first GPU as a percentage.", + 30, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.GpuTemperatureSensor, + "Provides the current temperature of the first GPU.", + 30, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.LastActiveSensor, + "Provides a datetime value containing the last moment the user provided any input.", + 10, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.LastBootSensor, + "Provides a datetime value containing the last moment the system (re)booted.\r\n\r\nImportant: Windows' FastBoot option can throw this value off, because that's a form of hibernation. You can disable it through Power Options -> 'Choose what the power buttons do' -> uncheck 'Turn on fast start-up'. It doesn't make much difference for modern machines with SSDs, but disabling makes sure you get a clean state after rebooting.", + 10, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.LastSystemStateChangeSensor, + "Provides the last system state change:\r\n\r\nHassAgentStarted, Logoff, SystemShutdown, Resume, Suspend, ConsoleConnect, ConsoleDisconnect, RemoteConnect, RemoteDisconnect, SessionLock, SessionLogoff, SessionLogon, SessionRemoteControl and SessionUnlock.", + 10, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.LoggedUserSensor, + "Returns the name of the currently logged user.", + 10, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.LoggedUsersSensor, + "Returns a json-formatted list of currently logged users.", + 30, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.MemoryUsageSensor, + "Provides the amount of used memory as a percentage.", + 30, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.MicrophoneActiveSensor, + "Provides a bool value based on whether the microphone is currently being used.", + 10, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.NamedWindowSensor, + "Provides an ON/OFF value based on whether the window is currently open (doesn't have to be active).", + 30, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.NetworkSensors, + "Provides card info, configuration, transfer- & package statistics and addresses (ip, mac, dhcp, dns) of all present network cards.\r\n\r\nThis is a multi-value sensor.", + 30, true, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.PerformanceCounterSensor, + "Provides the values of a performance counter.\r\n\r\nFor example, the built-in CPU load sensor uses these values:\r\n\r\nCategory: Processor\r\nCounter: % Processor Time\r\nInstance: _Total\r\n\r\nYou can explore the counters through Windows' 'perfmon.exe' tool.", + 30, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.ProcessActiveSensor, + "Provides the number of active instances of the process.", + 10, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.ServiceStateSensor, + "Returns the state of the provided service: NotFound, Stopped, StartPending, StopPending, Running, ContinuePending, PausePending or Paused.\r\n\r\nMake sure to provide the 'Service name', not the 'Display name'.", + 10, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.SessionStateSensor, + "Provides the current session state:\r\n\r\nLocked, Unlocked or Unknown.\r\n\r\nUse a LastSystemStateChangeSensor to monitor session state changes.", + 10, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.StorageSensors, + "Provides the labels, total size (MB), available space (MB), used space (MB) and file system of all present non-removable disks.", + 30, true, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.UserNotificationStateSensor, + "Provides the current user state:\r\n\r\nNotPresent, Busy, RunningDirect3dFullScreen, PresentationMode, AcceptsNotifications, QuietTime or RunningWindowsStoreApp.\r\n\r\nCan for instance be used to determine whether to send notifications or TTS messages.", + 10, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.WebcamActiveSensor, + "Provides a bool value based on whether the webcam is currently being used.", + 10, false, true, false); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + // Provides a sensor with the amount of pending driver updates, a sensor with the amount of pending software updates, a sensor containing all pending driver updates information (title, kb article id's, hidden, type and categories) and a sensor containing the same for pending software updates.\r\n\r\nThis is a costly request, so the recommended interval is 15 minutes (900 seconds). But it's capped at 10 minutes, if you provide a lower value, you'll get the last known list. + sensorInfoCard = new SensorInfoCard(SensorType.WindowsUpdatesSensors, + "Provides a sensor with the amount of pending driver updates and a sensor with the amount of pending software updates.\r\n\r\nThis is a costly request, so the recommended interval is 15 minutes (900 seconds). But it's capped at 10 minutes, if you provide a lower value, you'll get the last known list.", + 900, true, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + + sensorInfoCard = new SensorInfoCard(SensorType.WmiQuerySensor, + "Provides the result of the WMI query.", + 10, false, true, true); + + SensorInfoCards.Add(sensorInfoCard.SensorType, sensorInfoCard); + + // ================================= + } + } +} diff --git a/src/HASSAgent/Service/Protos/hassagentsatellite.proto b/src/HASSAgent/Service/Protos/hassagentsatellite.proto new file mode 100644 index 0000000..87e1145 --- /dev/null +++ b/src/HASSAgent/Service/Protos/hassagentsatellite.proto @@ -0,0 +1,144 @@ +syntax = "proto3"; + +service HassAgentSatelliteRpcCalls { + rpc Ping (PingRequest) returns (PingResponse); + rpc ShutdownService (ShutdownServiceRequest) returns (AckResponse); + rpc ClearEntities (ClearEntitiesRequest) returns (AckResponse); + rpc SetDeviceName (SetDeviceNameRequest) returns (AckResponse); + rpc SetServiceSettings (SetServiceSettingsRequest) returns (AckResponse); + rpc SetServiceMqttSettings (SetServiceMqttSettingsRequest) returns (AckResponse); + rpc SetConfiguredCommands (SetConfiguredCommandsRequest) returns (AckResponse); + rpc SetConfiguredSensors (SetConfiguredSensorsRequest) returns (AckResponse); + rpc GetDeviceName (GetDeviceNameRequest) returns (GetDeviceNameResponse); + rpc GetServiceSettings (GetServiceSettingsRequest) returns (GetServiceSettingsResponse); + rpc GetServiceMqttSettings (GetServiceMqttSettingsRequest) returns (GetServiceMqttSettingsResponse); + rpc GetConfiguredCommands (GetConfiguredCommandsRequest) returns (GetConfiguredCommandsResponse); + rpc GetConfiguredSensors (GetConfiguredSensorsRequest) returns (GetConfiguredSensorsResponse); + rpc GetMqttStatus (GetMqttStatusRequest) returns (GetMqttStatusResponse); +} + +message PingRequest {} + +message PingResponse { + bool ok = 1; + string version = 2; + string error = 3; +} + +message AckResponse { + bool ok = 1; + string error = 2; +} + +message SetDeviceNameRequest { + string auth = 1; + string devicename = 2; +} + +message GetDeviceNameRequest { string auth = 1; } +message GetDeviceNameResponse { + bool ok = 1; + string error = 2; + string deviceName = 3; +} + +message GetMqttStatusRequest { string auth = 1; } +message GetMqttStatusResponse { + bool ok = 1; + string error = 2; + int32 mqttStatus = 3; +} + +message ShutdownServiceRequest { string auth = 1; } + +message ClearEntitiesRequest { string auth = 1; } + +message SetServiceSettingsRequest { + string auth = 1; + RpcServiceSettings serviceSettings = 2; +} + +message GetServiceSettingsRequest { string auth = 1; } +message GetServiceSettingsResponse { + bool ok = 1; + string error = 2; + RpcServiceSettings serviceSettings = 3; +} + +message SetServiceMqttSettingsRequest { + string auth = 1; + RpcServiceMqttSettings serviceMqttSettings = 2; +} + +message GetServiceMqttSettingsRequest { string auth = 1; } +message GetServiceMqttSettingsResponse { + bool ok = 1; + string error = 2; + RpcServiceMqttSettings serviceMqttSettings = 3; +} + +message SetConfiguredCommandsRequest { + string auth = 1; + repeated RpcConfiguredServerCommand configuredServerCommands = 2; +} + +message GetConfiguredCommandsRequest { string auth = 1; } +message GetConfiguredCommandsResponse { + bool ok = 1; + string error = 2; + repeated RpcConfiguredServerCommand configuredServerCommands = 3; +} + +message SetConfiguredSensorsRequest { + string auth = 1; + repeated RpcConfiguredServerSensor configuredServerSensors = 2; +} + +message GetConfiguredSensorsRequest { string auth = 1; } +message GetConfiguredSensorsResponse { + bool ok = 1; + string error = 2; + repeated RpcConfiguredServerSensor configuredServerSensors = 3; +} + +message RpcServiceSettings { + string authId = 1; + string customExecutorName = 2; + string customExecutorBinary = 3; + int32 disconnectedGracePeriodSeconds = 4; +} + +message RpcServiceMqttSettings { + string mqttAddress = 1; + int32 mqttPort = 2; + bool mqttUseTls = 3; + bool mqttAllowUntrustedCertificates = 4; + string mqttUsername = 5; + string mqttPassword = 6; + string mqttDiscoveryPrefix = 7; + bool mqttUseRetainFlag = 8; + string mqttRootCertificate = 9; + string mqttClientCertificate = 10; + string mqttClientId = 11; +} + +message RpcConfiguredServerSensor { + int32 type = 1; + string id = 2; + int32 updateInterval = 3; + string query = 4; + string scope = 5; + string windowName = 6; + string category = 7; + string counter = 8; + string instance = 9; + string name = 10; +} + +message RpcConfiguredServerCommand { + int32 type = 1; + string id = 2; + string command = 3; + bool runAsLowIntegrity = 4; + string name = 5; +} \ No newline at end of file diff --git a/src/HASSAgent/Service/Requests/RpcGetRequests.cs b/src/HASSAgent/Service/Requests/RpcGetRequests.cs new file mode 100644 index 0000000..51a8b70 --- /dev/null +++ b/src/HASSAgent/Service/Requests/RpcGetRequests.cs @@ -0,0 +1,168 @@ +using Grpc.Core; +using HASSAgent.Extensions; +using HASSAgent.Shared.Enums; +using HASSAgent.Shared.Models.Config; +using HASSAgent.Shared.Models.Config.Service; +using Serilog; + +namespace HASSAgent.Service +{ + internal partial class RpcClientService + { + /// + /// Returns the service's current devicename as registered in HA + /// + /// + internal async Task<(bool result, string output, string error)> GetDeviceNameAsync() + { + try + { + var response = await _rpcClient.GetDeviceNameAsync(new GetDeviceNameRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, response.DeviceName, string.Empty); + + Log.Error("[SERVICE] GetDeviceName request failed: {err}", response.Error); + return (false, string.Empty, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, string.Empty, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, string.Empty, "fatal error"); + } + } + + /// + /// Returns the service's MQTT connection state + /// + /// + internal async Task<(bool result, MqttStatus status, string error)> GetMqttStatusAsync() + { + try + { + var response = await _rpcClient.GetMqttStatusAsync(new GetMqttStatusRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, (MqttStatus)response.MqttStatus, string.Empty); + + Log.Error("[SERVICE] GetMqttStatus request failed: {err}", response.Error); + return (false, MqttStatus.Error, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, MqttStatus.Error, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, MqttStatus.Error, "fatal error"); + } + } + + /// + /// Returns the service's current active settings + /// + /// + internal async Task<(bool result, ServiceSettings output, string error)> GetServiceSettingsAsync() + { + try + { + var response = await _rpcClient.GetServiceSettingsAsync(new GetServiceSettingsRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, response.ServiceSettings.ConvertToServiceSettings(), string.Empty); + + Log.Error("[SERVICE] GetServiceSettings request failed: {err}", response.Error); + return (false, null, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, null, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, null, "fatal error"); + } + } + + /// + /// Returns the service's current active MQTT settings + /// + /// + internal async Task<(bool result, ServiceMqttSettings output, string error)> GetServiceMqttSettingsAsync() + { + try + { + var response = await _rpcClient.GetServiceMqttSettingsAsync(new GetServiceMqttSettingsRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, response.ServiceMqttSettings.ConvertToServiceMqttSettings(), string.Empty); + + Log.Error("[SERVICE] GetServiceMqttSettings request failed: {err}", response.Error); + return (false, null, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, null, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, null, "fatal error"); + } + } + + /// + /// Returns the service's current active configured commands + /// + /// + internal async Task<(bool result, List output, string error)> GetConfiguredCommandsAsync() + { + try + { + var response = await _rpcClient.GetConfiguredCommandsAsync(new GetConfiguredCommandsRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, response.ConfiguredServerCommands.ConvertToConfiguredCommands(), string.Empty); + + Log.Error("[SERVICE] GetConfiguredCommands request failed: {err}", response.Error); + return (false, null, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, null, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, null, "fatal error"); + } + } + + /// + /// Returns the service's current active sensors + /// + /// + internal async Task<(bool result, List output, string error)> GetConfiguredSensorsAsync() + { + try + { + var response = await _rpcClient.GetConfiguredSensorsAsync(new GetConfiguredSensorsRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, response.ConfiguredServerSensors.ConvertToConfiguredSensors(), string.Empty); + + Log.Error("[SERVICE] GetConfiguredSensors request failed: {err}", response.Error); + return (false, null, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, null, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, null, "fatal error"); + } + } + } +} diff --git a/src/HASSAgent/Service/Requests/RpcSetRequests.cs b/src/HASSAgent/Service/Requests/RpcSetRequests.cs new file mode 100644 index 0000000..ec68e01 --- /dev/null +++ b/src/HASSAgent/Service/Requests/RpcSetRequests.cs @@ -0,0 +1,179 @@ +using Grpc.Core; +using HASSAgent.Extensions; +using HASSAgent.Shared.Models.Config; +using HASSAgent.Shared.Models.Config.Service; +using Serilog; + +namespace HASSAgent.Service +{ + internal partial class RpcClientService + { + /// + /// Sets the provided devicename, triggering a re-registering of the service (and all entities) with HA + /// + /// + /// + internal async Task<(bool result, string error)> SetDeviceNameAsync(string deviceName) + { + try + { + var setDeviceNameRequest = new SetDeviceNameRequest + { + Auth = Variables.AppSettings.ServiceAuthId, + Devicename = deviceName + }; + + var response = await _rpcClient.SetDeviceNameAsync(setDeviceNameRequest); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] SetDeviceName request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + + /// + /// Sets and activates the provided settings + /// DeviceName will be ignored, use SetDeviceNameAsync + /// + /// + /// + internal async Task<(bool result, string error)> SetServiceSettingsAsync(ServiceSettings serviceSettings) + { + try + { + var setServiceSettingsRequest = new SetServiceSettingsRequest + { + Auth = Variables.AppSettings.ServiceAuthId, + ServiceSettings = serviceSettings.ConvertToRpcServiceSettings() + }; + + var response = await _rpcClient.SetServiceSettingsAsync(setServiceSettingsRequest); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] SetServiceSettings request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + + /// + /// Sets and activates the provided settings, triggering a reconnect of the MQTT client + /// + /// + /// + internal async Task<(bool result, string error)> SetServiceMqttSettingsAsync(ServiceMqttSettings serviceMqttSettings) + { + try + { + var setServiceMqttSettingsRequest = new SetServiceMqttSettingsRequest + { + Auth = Variables.AppSettings.ServiceAuthId, + ServiceMqttSettings = serviceMqttSettings.ConvertToRpcServiceMqttSettings() + }; + + var response = await _rpcClient.SetServiceMqttSettingsAsync(setServiceMqttSettingsRequest); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] SetServiceMqttSettings request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + + /// + /// Syncs the service's command list with the provided list + /// + /// + /// + internal async Task<(bool result, string error)> SetConfiguredCommandsAsync(List configuredCommands) + { + try + { + var setConfiguredCommandsRequest = new SetConfiguredCommandsRequest + { + Auth = Variables.AppSettings.ServiceAuthId + }; + + foreach (var configuredCommand in configuredCommands.ConvertToRpcConfiguredCommands()) setConfiguredCommandsRequest.ConfiguredServerCommands.Add(configuredCommand); + + var response = await _rpcClient.SetConfiguredCommandsAsync(setConfiguredCommandsRequest); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] SetConfiguredCommands request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + + /// + /// Syncs the service's sensor list with the provided list + /// + /// + /// + internal async Task<(bool result, string error)> SetConfiguredSensorsAsync(List configuredSensors) + { + try + { + var setConfiguredSensorsRequest = new SetConfiguredSensorsRequest + { + Auth = Variables.AppSettings.ServiceAuthId + }; + + foreach (var configuredSensor in configuredSensors.ConvertToRpcConfiguredSensors()) setConfiguredSensorsRequest.ConfiguredServerSensors.Add(configuredSensor); + + var response = await _rpcClient.SetConfiguredSensorsAsync(setConfiguredSensorsRequest); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] SetConfiguredSensors request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + } +} diff --git a/src/HASSAgent/Service/RpcClientService.cs b/src/HASSAgent/Service/RpcClientService.cs new file mode 100644 index 0000000..b962081 --- /dev/null +++ b/src/HASSAgent/Service/RpcClientService.cs @@ -0,0 +1,101 @@ +using System.Security.Principal; +using Grpc.Core; +using GrpcDotNetNamedPipes; +using Serilog; + +namespace HASSAgent.Service +{ + internal partial class RpcClientService + { + private readonly NamedPipeChannel _serviceChannel = new(".", Variables.PipeName, new NamedPipeChannelOptions + { + CurrentUserOnly = false, + ConnectionTimeout = (int)TimeSpan.FromSeconds(10).TotalMilliseconds + }); + + private readonly HassAgentSatelliteRpcCalls.HassAgentSatelliteRpcCallsClient _rpcClient; + + /// + /// Initialize our RPC client + /// + internal RpcClientService() => _rpcClient = new HassAgentSatelliteRpcCalls.HassAgentSatelliteRpcCallsClient(_serviceChannel); + + /// + /// Sends a PING request + /// + /// + internal async Task<(bool success, string version, string error)> PingAsync() + { + try + { + var response = await _rpcClient.PingAsync(new PingRequest()); + if (response.Ok) return (true, response.Version, string.Empty); + + Log.Error("[SERVICE] Ping request failed: {err}", response.Error); + return (false, string.Empty, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex .StatusCode.ToString(), ex.Message); + return (false, string.Empty, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, string.Empty, "fatal error"); + } + } + + /// + /// Asks the service to clear all its entities locally and in HA + /// + /// + internal async Task<(bool success, string error)> ClearEntitiesAsync() + { + try + { + var response = await _rpcClient.ClearEntitiesAsync(new ClearEntitiesRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] ClearEntities request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + + /// + /// Asks the service to nicely shutdown + /// + /// + internal async Task<(bool success, string error)> ShutdownServiceAsync() + { + try + { + var response = await _rpcClient.ShutdownServiceAsync(new ShutdownServiceRequest { Auth = Variables.AppSettings.ServiceAuthId }); + if (response.Ok) return (true, string.Empty); + + Log.Error("[SERVICE] ShutdownService request failed: {err}", response.Error); + return (false, response.Error); + } + catch (RpcException ex) + { + Log.Error("[SERVICE] RPC error [{code}]: {err}", ex.StatusCode.ToString(), ex.Message); + return (false, $"failed with status: {ex.StatusCode}"); + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error: {err}", ex.Message); + return (false, "fatal error"); + } + } + } +} diff --git a/src/HASSAgent/Service/ServiceManager.cs b/src/HASSAgent/Service/ServiceManager.cs new file mode 100644 index 0000000..95cae77 --- /dev/null +++ b/src/HASSAgent/Service/ServiceManager.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.ServiceProcess; +using System.Text; +using System.Threading.Tasks; +using HASSAgent.Enums; +using HASSAgent.Functions; +using HASSAgent.Shared.Functions; +using Microsoft.Win32; +using Serilog; + +namespace HASSAgent.Service +{ + internal static class ServiceManager + { + /// + /// Initializes the satellite service manager + /// + internal static void Initialize() + { + try + { + // fetch the local installation path and set the log path etc + var ioLoaded = SetSatelliteServiceLocalStorage(); + if (!ioLoaded) + { + Variables.MainForm?.SetServiceStatus(ComponentStatus.Failed); + return; + } + + // does it exist? + if (!ServiceControllerManager.ServiceExists()) + { + Variables.MainForm?.SetServiceStatus(ComponentStatus.Disabled); + return; + } + + // yep, get state + var state = ServiceControllerManager.GetServiceState(); + + // process accordingly + switch (state) + { + case ServiceControllerStatus.Running: + Variables.MainForm?.SetServiceStatus(ComponentStatus.Ok); + return; + case ServiceControllerStatus.Stopped: + Variables.MainForm?.SetServiceStatus(ComponentStatus.Stopped); + return; + default: + Variables.MainForm?.SetServiceStatus(ComponentStatus.Failed); + return; + } + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error initializing: {err}", ex.Message); + } + } + + /// + /// Sets the local install paths (if found) + /// By default handled by Initialize(), only call on child applications + /// + /// + internal static bool SetSatelliteServiceLocalStorage() + { + // get service binary & log path + var installPath = GetInstallPath(); + if (string.IsNullOrEmpty(installPath)) return false; + + // set local io + Variables.SatelliteServiceRootPath = installPath; + Variables.SatelliteServiceBinary = Path.Combine(installPath, "HASS.Agent.Satellite.Service.exe"); + Variables.SatelliteServiceLogPath = Path.Combine(installPath, "logs"); + + // done + return true; + } + + /// + /// Gets the 'extended logging' setting from registry, or the default location + /// + /// + internal static string GetInstallPath() + { + try + { + // should be in reg + var installPath = (string)Registry.GetValue(Variables.SatelliteMachineRootRegKey, "InstallPath", string.Empty); + if (!string.IsNullOrEmpty(installPath)) + { + Log.Information("[SERVICE] Local install path: {path}", installPath); + return installPath; + } + + // not found, probably first launch, try defaults + var defaultDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "LAB02 Research", "HASS.Agent Satellite Service"); + if (Directory.Exists(defaultDir)) return defaultDir; + + defaultDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "LAB02 Research", "HASS.Agent Satellite Service"); + if (Directory.Exists(defaultDir)) return defaultDir; + + defaultDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "LAB02 Research", "HASS.Agent Satellite Service"); + if (Directory.Exists(defaultDir)) return defaultDir; + + // nothing + Log.Error("[SERVICE] Unable to retrieve install path from service, and default path not found"); + return string.Empty; + } + catch (Exception ex) + { + Log.Fatal(ex, "[SERVICE] Error retrieving startup path: {err}", ex.Message); + return string.Empty; + } + } + } +} diff --git a/src/HASS.Agent/HASSAgent/Settings/SettingsManager.cs b/src/HASSAgent/Settings/SettingsManager.cs similarity index 77% rename from src/HASS.Agent/HASSAgent/Settings/SettingsManager.cs rename to src/HASSAgent/Settings/SettingsManager.cs index e25f688..15bbb77 100644 --- a/src/HASS.Agent/HASSAgent/Settings/SettingsManager.cs +++ b/src/HASSAgent/Settings/SettingsManager.cs @@ -1,12 +1,11 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; +using HASSAgent.Commands; using HASSAgent.Enums; using HASSAgent.Models.Config; -using HASSAgent.Models.HomeAssistant.Commands; -using HASSAgent.Models.HomeAssistant.Sensors; using HASSAgent.Models.Internal; +using HASSAgent.Sensors; +using HASSAgent.Shared; +using HASSAgent.Shared.Models.HomeAssistant.Commands; +using HASSAgent.Shared.Models.HomeAssistant.Sensors; using Microsoft.Win32; using Newtonsoft.Json; using Serilog; @@ -22,11 +21,23 @@ internal class SettingsManager /// /// Load all stored settings and objects /// + /// + /// /// - internal static async Task LoadAsync(bool createInitialSettings = true) + internal static async Task LoadAsync(bool createInitialSettings = true, bool loadEntities = true) { Log.Information("[SETTINGS] Config storage path: {path}", Variables.ConfigPath); + // load command & sensor info cards + if (loadEntities) + { + await Task.Run(delegate + { + CommandsManager.LoadCommandInfo(); + SensorsManager.LoadSensorInfo(); + }); + } + // check config dir if (!Directory.Exists(Variables.ConfigPath)) { @@ -56,17 +67,21 @@ internal static async Task LoadAsync(bool createInitialSettings = true) var ok = LoadAppSettings(); if (!ok) allGood = false; - // load quick actions - ok = StoredQuickActions.Load(); - if (!ok) allGood = false; + // only load other entities if we're asked to + if (loadEntities) + { + // load quick actions + ok = StoredQuickActions.Load(); + if (!ok) allGood = false; - // load commands - ok = await StoredCommands.LoadAsync(); - if (!ok) allGood = false; + // load commands + ok = await StoredCommands.LoadAsync(); + if (!ok) allGood = false; - // load sensors - ok = await StoredSensors.LoadAsync(); - if (!ok) allGood = false; + // load sensors + ok = await StoredSensors.LoadAsync(); + if (!ok) allGood = false; + } // done return allGood; @@ -111,6 +126,10 @@ private static bool LoadAppSettings() StoreAppSettings(); } + // set shared config + AgentSharedBase.SetDeviceName(Variables.AppSettings.DeviceName); + AgentSharedBase.SetCustomExecutorBinary(Variables.AppSettings.CustomExecutorBinary); + // load the hotkey Variables.QuickActionsHotKey = string.IsNullOrEmpty(Variables.AppSettings.QuickActionsHotKey) ? null : HotkeyListener.Convert(Variables.AppSettings.QuickActionsHotKey); @@ -140,6 +159,7 @@ private static bool StoreInitialSettings(bool storeSettings = true) Variables.QuickActions = new List(); Variables.Commands = new List(); Variables.SingleValueSensors = new List(); + Variables.MultiValueSensors = new List(); // default settings Variables.AppSettings = new AppSettings(); @@ -166,13 +186,6 @@ private static bool StoreInitialSettings(bool storeSettings = true) /// internal static bool Store() { - // check config dir - if (!Directory.Exists(Variables.ConfigPath)) - { - // create - Directory.CreateDirectory(Variables.ConfigPath); - } - // start positive var allGood = true; @@ -204,6 +217,13 @@ internal static bool StoreAppSettings() { try { + // check config dir + if (!Directory.Exists(Variables.ConfigPath)) + { + // create + Directory.CreateDirectory(Variables.ConfigPath); + } + // serialize to file var appSettings = JsonConvert.SerializeObject(Variables.AppSettings, Formatting.Indented); File.WriteAllText(Variables.AppSettingsFile, appSettings); @@ -255,41 +275,5 @@ internal static void SetExtendedLoggingSetting(bool enabled) Log.Fatal(ex, "[SETTINGS] Error storing extended logging setting: {err}", ex.Message); } } - - /// - /// Gets the 'exception reporting' setting from registry - /// - /// - internal static bool GetExceptionReportingSetting() - { - try - { - var setting = (string)Registry.GetValue(Variables.RootRegKey, "ExceptionReporting", "0"); - if (string.IsNullOrEmpty(setting)) return false; - - return setting == "1"; - } - catch (Exception ex) - { - Log.Fatal(ex, "[SETTINGS] Error retrieving exception reporting setting: {err}", ex.Message); - return false; - } - } - - /// - /// Stores the 'exception reporting' setting in registry - /// - /// - internal static void SetExceptionReportingSetting(bool enabled) - { - try - { - Registry.SetValue(Variables.RootRegKey, "ExceptionReporting", enabled ? "1" : "0", RegistryValueKind.String); - } - catch (Exception ex) - { - Log.Fatal(ex, "[SETTINGS] Error storing exception reporting setting: {err}", ex.Message); - } - } } } diff --git a/src/HASS.Agent/HASSAgent/Settings/StoredCommands.cs b/src/HASSAgent/Settings/StoredCommands.cs similarity index 92% rename from src/HASS.Agent/HASSAgent/Settings/StoredCommands.cs rename to src/HASSAgent/Settings/StoredCommands.cs index 1ea263d..6848058 100644 --- a/src/HASS.Agent/HASSAgent/Settings/StoredCommands.cs +++ b/src/HASSAgent/Settings/StoredCommands.cs @@ -1,14 +1,11 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using HASSAgent.Enums; -using HASSAgent.Models.Config; -using HASSAgent.Models.HomeAssistant.Commands; -using HASSAgent.Models.HomeAssistant.Commands.CustomCommands; +using HASSAgent.Enums; using HASSAgent.Models.HomeAssistant.Commands.InternalCommands; -using HASSAgent.Models.HomeAssistant.Commands.KeyCommands; +using HASSAgent.Shared.Enums; +using HASSAgent.Shared.Models.Config; +using HASSAgent.Shared.Models.HomeAssistant.Commands; +using HASSAgent.Shared.Models.HomeAssistant.Commands.CustomCommands; +using HASSAgent.Shared.Models.HomeAssistant.Commands.InternalCommands; +using HASSAgent.Shared.Models.HomeAssistant.Commands.KeyCommands; using Newtonsoft.Json; using Serilog; @@ -40,7 +37,7 @@ internal static async Task LoadAsync() } // read the content - var commandsRaw = File.ReadAllText(Variables.CommandsFile); + var commandsRaw = await File.ReadAllTextAsync(Variables.CommandsFile); if (string.IsNullOrWhiteSpace(commandsRaw)) { Log.Information("[SETTINGS_COMMANDS] Config is empty, no entities loaded"); @@ -241,6 +238,13 @@ internal static bool Store() { try { + // check config dir + if (!Directory.Exists(Variables.ConfigPath)) + { + // create + Directory.CreateDirectory(Variables.ConfigPath); + } + // convert commands var configuredCommands = Variables.Commands.Select(ConvertAbstractToConfigured).Where(configuredCommand => configuredCommand != null).ToList(); diff --git a/src/HASS.Agent/HASSAgent/Settings/StoredQuickActions.cs b/src/HASSAgent/Settings/StoredQuickActions.cs similarity index 91% rename from src/HASS.Agent/HASSAgent/Settings/StoredQuickActions.cs rename to src/HASSAgent/Settings/StoredQuickActions.cs index e721459..38a21d3 100644 --- a/src/HASS.Agent/HASSAgent/Settings/StoredQuickActions.cs +++ b/src/HASSAgent/Settings/StoredQuickActions.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using HASSAgent.Enums; +using HASSAgent.Enums; using HASSAgent.Models.Internal; using Newtonsoft.Json; using Serilog; @@ -77,6 +74,13 @@ internal static bool Store() { try { + // check config dir + if (!Directory.Exists(Variables.ConfigPath)) + { + // create + Directory.CreateDirectory(Variables.ConfigPath); + } + // serialize to file var quickActions = JsonConvert.SerializeObject(Variables.QuickActions, Formatting.Indented); File.WriteAllText(Variables.QuickActionsFile, quickActions); diff --git a/src/HASS.Agent/HASSAgent/Settings/StoredSensors.cs b/src/HASSAgent/Settings/StoredSensors.cs similarity index 93% rename from src/HASS.Agent/HASSAgent/Settings/StoredSensors.cs rename to src/HASSAgent/Settings/StoredSensors.cs index 0f19139..84f6b59 100644 --- a/src/HASS.Agent/HASSAgent/Settings/StoredSensors.cs +++ b/src/HASSAgent/Settings/StoredSensors.cs @@ -1,16 +1,13 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Windows.Devices.Perception.Provider; -using HASSAgent.Enums; -using HASSAgent.Models.Config; -using HASSAgent.Models.HomeAssistant.Sensors; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue; -using HASSAgent.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue; -using HASSAgent.Models.HomeAssistant.Sensors.PerfCounterSensors.SingleValue; -using HASSAgent.Models.HomeAssistant.Sensors.WmiSensors.SingleValue; +using HASSAgent.Enums; +using HASSAgent.Extensions; +using HASSAgent.Shared.Enums; +using HASSAgent.Shared.Extensions; +using HASSAgent.Shared.Models.Config; +using HASSAgent.Shared.Models.HomeAssistant.Sensors; +using HASSAgent.Shared.Models.HomeAssistant.Sensors.GeneralSensors.MultiValue; +using HASSAgent.Shared.Models.HomeAssistant.Sensors.GeneralSensors.SingleValue; +using HASSAgent.Shared.Models.HomeAssistant.Sensors.PerfCounterSensors.SingleValue; +using HASSAgent.Shared.Models.HomeAssistant.Sensors.WmiSensors.SingleValue; using Newtonsoft.Json; using Serilog; @@ -43,7 +40,7 @@ internal static async Task LoadAsync() } // read the content - var sensorsRaw = File.ReadAllText(Variables.SensorsFile); + var sensorsRaw = await File.ReadAllTextAsync(Variables.SensorsFile); if (string.IsNullOrWhiteSpace(sensorsRaw)) { Log.Information("[SETTINGS_SENSORS] Config is empty, no entities loaded"); @@ -226,7 +223,7 @@ internal static ConfiguredSensor ConvertAbstractSingleValueToConfigured(Abstract Id = Guid.Parse(wmiSensor.Id), Name = wmiSensor.Name, Type = type, - UpdateInterval = wmiSensor.UpdateIntervalSeconds, + UpdateInterval = wmiSensor.UpdateIntervalSeconds, Scope = wmiSensor.Scope, Query = wmiSensor.Query }; @@ -388,6 +385,13 @@ internal static bool Store() { try { + // check config dir + if (!Directory.Exists(Variables.ConfigPath)) + { + // create + Directory.CreateDirectory(Variables.ConfigPath); + } + // convert single-value sensors var configuredSensors = Variables.SingleValueSensors.Select(ConvertAbstractSingleValueToConfigured).Where(configuredSensor => configuredSensor != null).ToList(); diff --git a/src/HASS.Agent/HASSAgent/Variables.cs b/src/HASSAgent/Variables.cs similarity index 59% rename from src/HASS.Agent/HASSAgent/Variables.cs rename to src/HASSAgent/Variables.cs index db2ced6..dc64470 100644 --- a/src/HASS.Agent/HASSAgent/Variables.cs +++ b/src/HASSAgent/Variables.cs @@ -1,23 +1,19 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Net; +using System.Diagnostics.CodeAnalysis; using System.Reflection; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using System.Windows.Threading; using CoreAudio; using Grapevine; using HASSAgent.Forms; using HASSAgent.Functions; -using HASSAgent.Models.HomeAssistant; -using HASSAgent.Models.HomeAssistant.Commands; -using HASSAgent.Models.HomeAssistant.Sensors; +using HASSAgent.Models.Config; using HASSAgent.Models.Internal; +using HASSAgent.MQTT; +using HASSAgent.Service; +using HASSAgent.Shared.Models.HomeAssistant; +using HASSAgent.Shared.Models.HomeAssistant.Commands; +using HASSAgent.Shared.Models.HomeAssistant.Sensors; +using HASSAgent.Shared.Mqtt; using MQTTnet; using WK.Libraries.HotkeyListenerNS; -using AppSettings = HASSAgent.Models.Config.AppSettings; namespace HASSAgent { @@ -27,14 +23,15 @@ public static class Variables /// /// Application info /// - public static string ApplicationName { get; } = Assembly.GetExecutingAssembly().GetName().Name; - public static string ApplicationExecutable { get; } = Assembly.GetExecutingAssembly().Location; - public static string Version { get; } = $"{Assembly.GetExecutingAssembly().GetName().Version.Major}.{Assembly.GetExecutingAssembly().GetName().Version.Minor}.{Assembly.GetExecutingAssembly().GetName().Version.Build}.{Assembly.GetExecutingAssembly().GetName().Version.Revision}"; - + public static string ApplicationName { get; } = Assembly.GetExecutingAssembly().GetName().Name ?? "HASS.Agent"; + public static string ApplicationExecutable { get; } = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".exe"); + public static string Version { get; } = $"{Assembly.GetExecutingAssembly().GetName().Version?.Major}.{Assembly.GetExecutingAssembly().GetName().Version?.Minor}.{Assembly.GetExecutingAssembly().GetName().Version?.Build}.{Assembly.GetExecutingAssembly().GetName().Version?.Revision}"; + public static bool Beta { get; set; } = false; + /// /// Constants /// - internal const string SyncfusionLicense = "NTA2NTgzQDMxMzkyZTMyMmUzMEhrMG96Rmx5N3JCTmJYT1o0R0g1ZjVlUVdoSDJvRFNSS0QvcktBSXhsb1U9"; + internal const string SyncfusionLicense = "NTk0MzAyQDMxMzkyZTM0MmUzMGpOM2NCRmROQWpybDZPYnBBa0twMWdqTFFRMGRUTERqa1laazRST2N6N1E9"; internal const string RootRegKey = @"HKEY_CURRENT_USER\SOFTWARE\LAB02Research\HASSAgent"; internal const string CertificateHash = "E4C76406BD0AC3937014764596B1697E4EB4A953"; @@ -42,20 +39,32 @@ public static class Variables /// Internal references /// internal static Main MainForm { get; set; } - internal static Dispatcher UiDispatcher { get; set; } - internal static WebClient WebClient { get; } = new WebClient(); - internal static Hotkey QuickActionsHotKey { get; set; } = new Hotkey(Keys.Control | Keys.Alt, Keys.Q); - internal static HotKeyManager HotKeyManager { get; } = new HotKeyManager(); + internal static HttpClient HttpClient { get; } = new(); + internal static Hotkey QuickActionsHotKey { get; set; } = new(Keys.Control | Keys.Alt, Keys.Q); + internal static HotKeyManager HotKeyManager { get; } = new(); internal static HotkeyListener HotKeyListener { get; set; } - internal static MMDeviceEnumerator AudioDeviceEnumerator { get; } = new MMDeviceEnumerator(); - internal static Random Rnd { get; } = new Random(); + internal static Random Rnd { get; } = new(); + internal static Font DefaultFont { get; } = new("Segoe UI", 10F, FontStyle.Regular, GraphicsUnit.Point); /// /// MQTT /// - internal static MqttFactory MqttFactory { get; } = new MqttFactory(); + internal static IMqttManager MqttManager { get; } = new MqttManager(); + internal static MqttFactory MqttFactory { get; } = new(); internal static DeviceConfigModel DeviceConfig { get; set; } = null; + /// + /// RPC (satellite service) + /// + internal static string PipeName => "5aaac90b-d046-4db2-be76-af225e0d249f"; + internal static string SatelliteServiceName => "HASS.Agent Satellite Service"; + internal static string SatelliteMachineRootRegKey => @"HKEY_LOCAL_MACHINE\SOFTWARE\LAB02Research\HASSAgent\SatelliteService"; + internal static string SatelliteServiceRootPath { get; set; } = string.Empty; + internal static string SatelliteServiceBinary { get; set; } = string.Empty; + internal static string SatelliteServiceLogPath { get; set; } = string.Empty; + internal static RpcClientService RpcClient => new(); + internal static TimeSpan RpcConnectionTimeout { get; } = TimeSpan.FromSeconds(15); + /// /// Internal state /// @@ -63,7 +72,6 @@ public static class Variables internal static bool ShuttingDown { get; set; } = false; internal static bool OnboardingLaunchOnLoginKeyCreated { get; set; } = false; internal static bool ExtendedLogging { get; set; } = false; - internal static bool ExceptionLogging { get; set; } = false; /// /// Local IO diff --git a/src/HASS.Agent/HASSAgent/app.manifest b/src/HASSAgent/app.manifest similarity index 84% rename from src/HASS.Agent/HASSAgent/app.manifest rename to src/HASSAgent/app.manifest index 6a39c83..95e0470 100644 --- a/src/HASS.Agent/HASSAgent/app.manifest +++ b/src/HASSAgent/app.manifest @@ -1,5 +1,5 @@  - + @@ -21,6 +21,14 @@ + + - + - --> +