From 79a221cf218ce0e088166f621316079b221559b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20B=C3=BCchel?= Date: Thu, 3 Dec 2020 19:47:17 +0100 Subject: [PATCH] SEBWIN-445: Implemented reporting of power supply and wireless adapter status to server. --- SafeExamBrowser.Client/CompositionRoot.cs | 10 +- .../SafeExamBrowser.Server.csproj | 4 + SafeExamBrowser.Server/ServerProxy.cs | 92 +++++++++++++++++-- 3 files changed, 94 insertions(+), 12 deletions(-) diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index 600ce9b0..9557e9b0 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -37,6 +37,8 @@ using SafeExamBrowser.Settings.UserInterface; using SafeExamBrowser.SystemComponents; using SafeExamBrowser.SystemComponents.Audio; using SafeExamBrowser.SystemComponents.Contracts; +using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; +using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using SafeExamBrowser.SystemComponents.Keyboard; using SafeExamBrowser.SystemComponents.PowerSupply; using SafeExamBrowser.SystemComponents.WirelessNetwork; @@ -68,12 +70,14 @@ namespace SafeExamBrowser.Client private ILogger logger; private IMessageBox messageBox; private INativeMethods nativeMethods; + private IPowerSupply powerSupply; private IRuntimeProxy runtimeProxy; private ISystemInfo systemInfo; private ITaskbar taskbar; private ITaskview taskview; private IText text; private IUserInterfaceFactory uiFactory; + private IWirelessAdapter wirelessAdapter; internal ClientController ClientController { get; private set; } @@ -89,10 +93,12 @@ namespace SafeExamBrowser.Client actionCenter = uiFactory.CreateActionCenter(); messageBox = BuildMessageBox(); nativeMethods = new NativeMethods(); + powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply))); runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client); systemInfo = new SystemInfo(); taskbar = uiFactory.CreateTaskbar(ModuleLogger("Taskbar")); taskview = uiFactory.CreateTaskview(); + wirelessAdapter = new WirelessAdapter(ModuleLogger(nameof(WirelessAdapter))); var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory))); var applicationMonitor = new ApplicationMonitor(TWO_SECONDS, ModuleLogger(nameof(ApplicationMonitor)), nativeMethods, processFactory); @@ -241,7 +247,7 @@ namespace SafeExamBrowser.Client private IOperation BuildServerOperation() { - var server = new ServerProxy(context.AppConfig, ModuleLogger(nameof(ServerProxy))); + var server = new ServerProxy(context.AppConfig, ModuleLogger(nameof(ServerProxy)), powerSupply, wirelessAdapter); var operation = new ServerOperation(actionCenter, context, logger, server, taskbar); context.Server = server; @@ -257,8 +263,6 @@ namespace SafeExamBrowser.Client var keyboard = new Keyboard(ModuleLogger(nameof(Keyboard))); var logInfo = new LogNotificationInfo(text); var logController = new LogNotificationController(logger, uiFactory); - var powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply))); - var wirelessAdapter = new WirelessAdapter(ModuleLogger(nameof(WirelessAdapter))); var operation = new ShellOperation( actionCenter, audio, diff --git a/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj b/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj index 22fc33de..00c2b6a8 100644 --- a/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj +++ b/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj @@ -79,6 +79,10 @@ {30b2d907-5861-4f39-abad-c4abf1b3470e} SafeExamBrowser.Settings + + {903129c6-e236-493b-9ad6-c6a57f647a3a} + SafeExamBrowser.SystemComponents.Contracts + diff --git a/SafeExamBrowser.Server/ServerProxy.cs b/SafeExamBrowser.Server/ServerProxy.cs index e93a348d..5b89c8f4 100644 --- a/SafeExamBrowser.Server/ServerProxy.cs +++ b/SafeExamBrowser.Server/ServerProxy.cs @@ -27,6 +27,8 @@ using SafeExamBrowser.Server.Contracts.Events; using SafeExamBrowser.Server.Data; using SafeExamBrowser.Settings.Logging; using SafeExamBrowser.Settings.Server; +using SafeExamBrowser.SystemComponents.Contracts.PowerSupply; +using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork; using Timer = System.Timers.Timer; namespace SafeExamBrowser.Server @@ -43,21 +45,29 @@ namespace SafeExamBrowser.Server private ConcurrentQueue logContent; private string oauth2Token; private int pingNumber; + private IPowerSupply powerSupply; private ServerSettings settings; private Task task; private Timer timer; + private IWirelessAdapter wirelessAdapter; public event TerminationRequestedEventHandler TerminationRequested; - public ServerProxy(AppConfig appConfig, ILogger logger) + public ServerProxy( + AppConfig appConfig, + ILogger logger, + IPowerSupply powerSupply = default(IPowerSupply), + IWirelessAdapter wirelessAdapter = default(IWirelessAdapter)) { this.api = new ApiVersion1(); this.appConfig = appConfig; this.cancellationTokenSource = new CancellationTokenSource(); this.httpClient = new HttpClient(); - this.logger = logger; this.logContent = new ConcurrentQueue(); + this.logger = logger; + this.powerSupply = powerSupply; this.timer = new Timer(); + this.wirelessAdapter = wirelessAdapter; } public ServerResponse Connect() @@ -252,31 +262,40 @@ namespace SafeExamBrowser.Server } logger.Subscribe(this); - task = new Task(SendLog, cancellationTokenSource.Token); task.Start(); - logger.Info("Started sending log items."); timer.AutoReset = false; timer.Elapsed += Timer_Elapsed; timer.Interval = 1000; timer.Start(); - logger.Info("Starting sending pings."); + + if (powerSupply != default(IPowerSupply) && wirelessAdapter != default(IWirelessAdapter)) + { + powerSupply.StatusChanged += PowerSupply_StatusChanged; + wirelessAdapter.NetworksChanged += WirelessAdapter_NetworksChanged; + logger.Info("Started monitoring system components."); + } } public void StopConnectivity() { + if (powerSupply != default(IPowerSupply) && wirelessAdapter != default(IWirelessAdapter)) + { + powerSupply.StatusChanged -= PowerSupply_StatusChanged; + wirelessAdapter.NetworksChanged -= WirelessAdapter_NetworksChanged; + logger.Info("Stopped monitoring system components."); + } + logger.Unsubscribe(this); cancellationTokenSource.Cancel(); task?.Wait(); - logger.Info("Stopped sending log items."); timer.Stop(); timer.Elapsed -= Timer_Elapsed; - logger.Info("Stopped sending pings."); } @@ -299,7 +318,8 @@ namespace SafeExamBrowser.Server ["text"] = message.Message }; var content = json.ToString(); - var success = TryExecute(HttpMethod.Post, api.LogEndpoint, out var response, content, contentType, authorization, token); + + TryExecute(HttpMethod.Post, api.LogEndpoint, out var response, content, contentType, authorization, token); } } catch (Exception e) @@ -309,6 +329,32 @@ namespace SafeExamBrowser.Server } } + private void PowerSupply_StatusChanged(IPowerSupplyStatus status) + { + try + { + var authorization = ("Authorization", $"Bearer {oauth2Token}"); + var chargeInfo = $"{status.BatteryChargeStatus} at {Convert.ToInt32(status.BatteryCharge * 100)}%"; + var contentType = "application/json;charset=UTF-8"; + var gridInfo = $"{(status.IsOnline ? "connected to" : "disconnected from")} the power grid"; + var token = ("SEBConnectionToken", connectionToken); + var json = new JObject + { + ["type"] = ToLogType(LogLevel.Info), + ["timestamp"] = ToUnixTimestamp(DateTime.Now), + ["text"] = $" {chargeInfo}, {status.BatteryTimeRemaining} remaining, {gridInfo}", + ["numericValue"] = Convert.ToInt32(status.BatteryCharge * 100) + }; + var content = json.ToString(); + + TryExecute(HttpMethod.Post, api.LogEndpoint, out var response, content, contentType, authorization, token); + } + catch (Exception e) + { + logger.Error("Failed to send power supply status!", e); + } + } + private void Timer_Elapsed(object sender, ElapsedEventArgs args) { try @@ -344,6 +390,34 @@ namespace SafeExamBrowser.Server timer.Start(); } + private void WirelessAdapter_NetworksChanged() + { + try + { + var authorization = ("Authorization", $"Bearer {oauth2Token}"); + var contentType = "application/json;charset=UTF-8"; + var network = wirelessAdapter.GetNetworks().FirstOrDefault(n => n.Status == WirelessNetworkStatus.Connected); + var token = ("SEBConnectionToken", connectionToken); + var json = new JObject { ["type"] = ToLogType(LogLevel.Info), ["timestamp"] = ToUnixTimestamp(DateTime.Now) }; + + if (network != default(IWirelessNetwork)) + { + json["text"] = $" {network.Name}: {network.Status}, {network.SignalStrength}%"; + json["numericValue"] = network.SignalStrength; + } + else + { + json["text"] = " not connected"; + } + + TryExecute(HttpMethod.Post, api.LogEndpoint, out var response, json.ToString(), contentType, authorization, token); + } + catch (Exception e) + { + logger.Error("Failed to send wireless status!", e); + } + } + private bool TryParseApi(HttpContent content) { var success = false; @@ -384,7 +458,7 @@ namespace SafeExamBrowser.Server success = true; } - + if (!success) { logger.Error("The selected SEB server instance does not support the required API version!");