SEBWIN-445: Implemented reporting of power supply and wireless adapter status to server.

This commit is contained in:
Damian Büchel 2020-12-03 19:47:17 +01:00
parent 4d05ef8cad
commit 79a221cf21
3 changed files with 94 additions and 12 deletions

View file

@ -37,6 +37,8 @@ using SafeExamBrowser.Settings.UserInterface;
using SafeExamBrowser.SystemComponents; using SafeExamBrowser.SystemComponents;
using SafeExamBrowser.SystemComponents.Audio; using SafeExamBrowser.SystemComponents.Audio;
using SafeExamBrowser.SystemComponents.Contracts; using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using SafeExamBrowser.SystemComponents.Keyboard; using SafeExamBrowser.SystemComponents.Keyboard;
using SafeExamBrowser.SystemComponents.PowerSupply; using SafeExamBrowser.SystemComponents.PowerSupply;
using SafeExamBrowser.SystemComponents.WirelessNetwork; using SafeExamBrowser.SystemComponents.WirelessNetwork;
@ -68,12 +70,14 @@ namespace SafeExamBrowser.Client
private ILogger logger; private ILogger logger;
private IMessageBox messageBox; private IMessageBox messageBox;
private INativeMethods nativeMethods; private INativeMethods nativeMethods;
private IPowerSupply powerSupply;
private IRuntimeProxy runtimeProxy; private IRuntimeProxy runtimeProxy;
private ISystemInfo systemInfo; private ISystemInfo systemInfo;
private ITaskbar taskbar; private ITaskbar taskbar;
private ITaskview taskview; private ITaskview taskview;
private IText text; private IText text;
private IUserInterfaceFactory uiFactory; private IUserInterfaceFactory uiFactory;
private IWirelessAdapter wirelessAdapter;
internal ClientController ClientController { get; private set; } internal ClientController ClientController { get; private set; }
@ -89,10 +93,12 @@ namespace SafeExamBrowser.Client
actionCenter = uiFactory.CreateActionCenter(); actionCenter = uiFactory.CreateActionCenter();
messageBox = BuildMessageBox(); messageBox = BuildMessageBox();
nativeMethods = new NativeMethods(); nativeMethods = new NativeMethods();
powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply)));
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client); runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client);
systemInfo = new SystemInfo(); systemInfo = new SystemInfo();
taskbar = uiFactory.CreateTaskbar(ModuleLogger("Taskbar")); taskbar = uiFactory.CreateTaskbar(ModuleLogger("Taskbar"));
taskview = uiFactory.CreateTaskview(); taskview = uiFactory.CreateTaskview();
wirelessAdapter = new WirelessAdapter(ModuleLogger(nameof(WirelessAdapter)));
var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory))); var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory)));
var applicationMonitor = new ApplicationMonitor(TWO_SECONDS, ModuleLogger(nameof(ApplicationMonitor)), nativeMethods, processFactory); var applicationMonitor = new ApplicationMonitor(TWO_SECONDS, ModuleLogger(nameof(ApplicationMonitor)), nativeMethods, processFactory);
@ -241,7 +247,7 @@ namespace SafeExamBrowser.Client
private IOperation BuildServerOperation() 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); var operation = new ServerOperation(actionCenter, context, logger, server, taskbar);
context.Server = server; context.Server = server;
@ -257,8 +263,6 @@ namespace SafeExamBrowser.Client
var keyboard = new Keyboard(ModuleLogger(nameof(Keyboard))); var keyboard = new Keyboard(ModuleLogger(nameof(Keyboard)));
var logInfo = new LogNotificationInfo(text); var logInfo = new LogNotificationInfo(text);
var logController = new LogNotificationController(logger, uiFactory); var logController = new LogNotificationController(logger, uiFactory);
var powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply)));
var wirelessAdapter = new WirelessAdapter(ModuleLogger(nameof(WirelessAdapter)));
var operation = new ShellOperation( var operation = new ShellOperation(
actionCenter, actionCenter,
audio, audio,

View file

@ -79,6 +79,10 @@
<Project>{30b2d907-5861-4f39-abad-c4abf1b3470e}</Project> <Project>{30b2d907-5861-4f39-abad-c4abf1b3470e}</Project>
<Name>SafeExamBrowser.Settings</Name> <Name>SafeExamBrowser.Settings</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.SystemComponents.Contracts\SafeExamBrowser.SystemComponents.Contracts.csproj">
<Project>{903129c6-e236-493b-9ad6-c6a57f647a3a}</Project>
<Name>SafeExamBrowser.SystemComponents.Contracts</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

View file

@ -27,6 +27,8 @@ using SafeExamBrowser.Server.Contracts.Events;
using SafeExamBrowser.Server.Data; using SafeExamBrowser.Server.Data;
using SafeExamBrowser.Settings.Logging; using SafeExamBrowser.Settings.Logging;
using SafeExamBrowser.Settings.Server; using SafeExamBrowser.Settings.Server;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
namespace SafeExamBrowser.Server namespace SafeExamBrowser.Server
@ -43,21 +45,29 @@ namespace SafeExamBrowser.Server
private ConcurrentQueue<ILogContent> logContent; private ConcurrentQueue<ILogContent> logContent;
private string oauth2Token; private string oauth2Token;
private int pingNumber; private int pingNumber;
private IPowerSupply powerSupply;
private ServerSettings settings; private ServerSettings settings;
private Task task; private Task task;
private Timer timer; private Timer timer;
private IWirelessAdapter wirelessAdapter;
public event TerminationRequestedEventHandler TerminationRequested; 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.api = new ApiVersion1();
this.appConfig = appConfig; this.appConfig = appConfig;
this.cancellationTokenSource = new CancellationTokenSource(); this.cancellationTokenSource = new CancellationTokenSource();
this.httpClient = new HttpClient(); this.httpClient = new HttpClient();
this.logger = logger;
this.logContent = new ConcurrentQueue<ILogContent>(); this.logContent = new ConcurrentQueue<ILogContent>();
this.logger = logger;
this.powerSupply = powerSupply;
this.timer = new Timer(); this.timer = new Timer();
this.wirelessAdapter = wirelessAdapter;
} }
public ServerResponse Connect() public ServerResponse Connect()
@ -252,31 +262,40 @@ namespace SafeExamBrowser.Server
} }
logger.Subscribe(this); logger.Subscribe(this);
task = new Task(SendLog, cancellationTokenSource.Token); task = new Task(SendLog, cancellationTokenSource.Token);
task.Start(); task.Start();
logger.Info("Started sending log items."); logger.Info("Started sending log items.");
timer.AutoReset = false; timer.AutoReset = false;
timer.Elapsed += Timer_Elapsed; timer.Elapsed += Timer_Elapsed;
timer.Interval = 1000; timer.Interval = 1000;
timer.Start(); timer.Start();
logger.Info("Starting sending pings."); 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() 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); logger.Unsubscribe(this);
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
task?.Wait(); task?.Wait();
logger.Info("Stopped sending log items."); logger.Info("Stopped sending log items.");
timer.Stop(); timer.Stop();
timer.Elapsed -= Timer_Elapsed; timer.Elapsed -= Timer_Elapsed;
logger.Info("Stopped sending pings."); logger.Info("Stopped sending pings.");
} }
@ -299,7 +318,8 @@ namespace SafeExamBrowser.Server
["text"] = message.Message ["text"] = message.Message
}; };
var content = json.ToString(); 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) 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"] = $"<battery> {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) private void Timer_Elapsed(object sender, ElapsedEventArgs args)
{ {
try try
@ -344,6 +390,34 @@ namespace SafeExamBrowser.Server
timer.Start(); 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"] = $"<wlan> {network.Name}: {network.Status}, {network.SignalStrength}%";
json["numericValue"] = network.SignalStrength;
}
else
{
json["text"] = "<wlan> 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) private bool TryParseApi(HttpContent content)
{ {
var success = false; var success = false;
@ -384,7 +458,7 @@ namespace SafeExamBrowser.Server
success = true; success = true;
} }
if (!success) if (!success)
{ {
logger.Error("The selected SEB server instance does not support the required API version!"); logger.Error("The selected SEB server instance does not support the required API version!");