diff --git a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs index 7b9fcabe..080b932e 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs @@ -22,10 +22,10 @@ public override string ToString() { - if(SwitchingDevice is IRouting) - return string.Format("{0} switches output '{1}' to input '{2}'", SwitchingDevice.Key, OutputPort.Selector, InputPort.Selector); - else - return string.Format("{0} switches to input '{1}'", SwitchingDevice.Key, InputPort.Selector); + if (SwitchingDevice is IRouting) + return $"{SwitchingDevice?.Key} switches output {OutputPort.Key} to input {InputPort.Key}"; + else + return $"{SwitchingDevice.Key} switches to input {InputPort.Key}"; } } diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs index ec09e08a..dbb2129a 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs @@ -1,22 +1,19 @@ -using Org.BouncyCastle.Crypto.Prng; -using PepperDash.Core; +using PepperDash.Core; using PepperDash.Essentials.Core.Config; using System; -using System.Collections; -using System.Collections.Generic; using System.Linq; -using System.Reflection; namespace PepperDash.Essentials.Core.Routing { public class RoutingFeedbackManager:EssentialsDevice { public RoutingFeedbackManager(string key, string name): base(key, name) - { - AddPostActivationAction(SubscribeForMidpointFeedback); - AddPostActivationAction(SubscribeForSinkFeedback); + { + AddPreActivationAction(SubscribeForMidpointFeedback); + AddPreActivationAction(SubscribeForSinkFeedback); } + private void SubscribeForMidpointFeedback() { var midpointDevices = DeviceManager.AllDevices.OfType(); @@ -39,11 +36,18 @@ namespace PepperDash.Essentials.Core.Routing private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute) { - var devices = DeviceManager.AllDevices.OfType(); - - foreach(var device in devices) + try { - UpdateDestination(device, device.CurrentInputPort); + var devices = DeviceManager.AllDevices.OfType(); + + foreach (var device in devices) + { + UpdateDestination(device, device.CurrentInputPort); + } + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Error handling midpoint update from {midpointKey}:{Exception}", this, midpoint.Key, ex); } } @@ -60,30 +64,68 @@ namespace PepperDash.Essentials.Core.Routing } private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort) - { - var tieLines = TieLineCollection.Default; + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key); - var firstTieLine = tieLines.FirstOrDefault(tl => tl.DestinationPort.Key == inputPort.Key); - - if (firstTieLine == null) + if(inputPort == null) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No tieline found for inputPort {inputPort}. Clearing current source", this, inputPort); + Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "Destination {destination} has not reported an input port yet", this,destination.Key); + return; + } - destination.CurrentSourceInfo = null; - destination.CurrentSourceInfoKey = string.Empty; + TieLine firstTieLine; + try + { + var tieLines = TieLineCollection.Default; + + firstTieLine = tieLines.FirstOrDefault(tl => tl.DestinationPort.Key == inputPort.Key && tl.DestinationPort.ParentDevice.Key == inputPort.ParentDevice.Key); + + if (firstTieLine == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No tieline found for inputPort {inputPort}. Clearing current source", this, inputPort); + + var tempSourceListItem = new SourceListItem + { + SourceKey = "$transient", + Name = inputPort.Key, + }; + + + destination.CurrentSourceInfo = tempSourceListItem; ; + destination.CurrentSourceInfoKey = "$transient"; + return; + } + } catch (Exception ex) + { + Debug.LogMessage(ex, "Error getting first tieline: {Exception}", this, ex); return; } Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Getting source for first TieLine {tieLine}", this, firstTieLine); - var sourceTieLine = GetRootTieLine(firstTieLine); - - if (sourceTieLine == null) + TieLine sourceTieLine; + try { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route found to source for inputPort {inputPort}. Clearing current source", this, inputPort); + sourceTieLine = GetRootTieLine(firstTieLine); - destination.CurrentSourceInfo = null; - destination.CurrentSourceInfoKey = string.Empty; + if (sourceTieLine == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route found to source for inputPort {inputPort}. Clearing current source", this, inputPort); + + var tempSourceListItem = new SourceListItem + { + SourceKey = "$transient", + Name = "None", + }; + + destination.CurrentSourceInfo = tempSourceListItem; + destination.CurrentSourceInfoKey = string.Empty; + return; + } + } catch(Exception ex) + { + Debug.LogMessage(ex, "Error getting sourceTieLine: {Exception}", this, ex); + return; } Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine); @@ -136,10 +178,16 @@ namespace PepperDash.Essentials.Core.Routing if (source == null) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No source found for device {key}. Clearing current source on {destination}", this, sourceTieLine.SourcePort.ParentDevice.Key, destination); + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No source found for device {key}. Creating transient source for {destination}", this, sourceTieLine.SourcePort.ParentDevice.Key, destination); - destination.CurrentSourceInfo = null; - destination.CurrentSourceInfoKey = string.Empty; + var tempSourceListItem = new SourceListItem + { + SourceKey = "$transient", + Name = sourceTieLine.SourcePort.Key, + }; + + destination.CurrentSourceInfo = tempSourceListItem; ; + destination.CurrentSourceInfoKey = "$transient"; return; } @@ -152,43 +200,67 @@ namespace PepperDash.Essentials.Core.Routing private TieLine GetRootTieLine(TieLine tieLine) { TieLine nextTieLine = null; - - if(tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint) + try { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device is midpoint", this); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine); - var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => route.OutputPort.Key == tieLine.SourcePort.Key); - - if(currentRoute == null) + if (tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route through midpoint {midpoint} for outputPort {outputPort}", this, midpoint.Key, tieLine.SourcePort); - return null; + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device {sourceDevice} is midpoint", this, midpoint); + + if(midpoint.CurrentRoutes == null || midpoint.CurrentRoutes.Count == 0) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Midpoint {midpointKey} has no routes",this, midpoint.Key); + return null; + } + + var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); + + return route.OutputPort.Key == tieLine.SourcePort.Key && route.OutputPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; + }); + + if (currentRoute == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route through midpoint {midpoint} for outputPort {outputPort}", this, midpoint.Key, tieLine.SourcePort); + return null; + } + + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint); + + nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", tl.DestinationPort.Key, currentRoute.InputPort.Key); + return tl.DestinationPort.Key == currentRoute.InputPort.Key && tl.DestinationPort.ParentDevice.Key == currentRoute.InputPort.ParentDevice.Key; }); + + if (nextTieLine != null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine); + return GetRootTieLine(nextTieLine); + } + + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine); + return nextTieLine; } - nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => tl.DestinationPort.Key == currentRoute.InputPort.Key); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLIne Source Device {sourceDeviceKey} is IRoutingSource: {isIRoutingSource}", this, tieLine.SourcePort.ParentDevice.Key, tieLine.SourcePort.ParentDevice is IRoutingSource); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source Device interfaces: {typeFullName}:{interfaces}", this, tieLine.SourcePort.ParentDevice.GetType().FullName, tieLine.SourcePort.ParentDevice.GetType().GetInterfaces().Select(i => i.Name)); - if(tieLine != null) + if (tieLine.SourcePort.ParentDevice is IRoutingSource || tieLine.SourcePort.ParentDevice is IRoutingOutputs) //end of the chain + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine); + return tieLine; + } + + nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => tl.DestinationPort.Key == tieLine.SourcePort.Key && tl.DestinationPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key ); + + if (nextTieLine != null) { return GetRootTieLine(nextTieLine); } - - return tieLine; - } - - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLIne Source Device {sourceDeviceKey} is IRoutingSource: {isIRoutingSource}", this,tieLine.SourcePort.ParentDevice.Key, tieLine.SourcePort.ParentDevice is IRoutingSource); - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source Device interfaces: {typeFullName}:{interfaces}",this, tieLine.SourcePort.ParentDevice.GetType().FullName, tieLine.SourcePort.ParentDevice.GetType().GetInterfaces().Select(i => i.Name)); - - if(tieLine.SourcePort.ParentDevice is IRoutingSource || tieLine.SourcePort.ParentDevice is IRoutingOutputs) //end of the chain + } catch (Exception ex) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine); - return tieLine; - } - - nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => tl.SourcePort.Key == tieLine.SourcePort.Key); - - if(nextTieLine != null) - { - return GetRootTieLine(nextTieLine); + Debug.LogMessage(ex, "Error walking tieLines: {Exception}", this, ex); + return null; } return null; diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs index 7da945cb..9e3bb1d9 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs @@ -38,7 +38,12 @@ namespace PepperDash.Essentials.Core throw new ArgumentNullException(nameof(parent)); ParentDevice = parent; } - } + + public override string ToString() + { + return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; + } + } /*/// /// Basic RoutingInput with no statuses. diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs index 445b3072..bebcb287 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs @@ -34,7 +34,7 @@ namespace PepperDash.Essentials.Core public override string ToString() { - return ParentDevice.Key + ":" + Key; + return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; } } diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs index b687f6fe..04e804f1 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs @@ -23,8 +23,8 @@ namespace PepperDash.Essentials.Core ConnectionType = connType; Selector = selector; IsInternal = isInternal; - } - } + } + } /*public abstract class RoutingPort:IKeyed { diff --git a/src/PepperDash.Essentials.Core/Routing/TieLine.cs b/src/PepperDash.Essentials.Core/Routing/TieLine.cs index 65804eb3..245194a9 100644 --- a/src/PepperDash.Essentials.Core/Routing/TieLine.cs +++ b/src/PepperDash.Essentials.Core/Routing/TieLine.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Newtonsoft.Json; using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM; @@ -93,19 +94,21 @@ namespace PepperDash.Essentials.Core } } - //******************************************************************************** + //******************************************************************************** - public class TieLineCollection : List - { - public static TieLineCollection Default - { - get - { - if (_Default == null) - _Default = new TieLineCollection(); - return _Default; - } - } + public class TieLineCollection : List + { + public static TieLineCollection Default + { + get + { + if (_Default == null) + _Default = new TieLineCollection(); + return _Default; + } + } + + [JsonIgnore] static TieLineCollection _Default; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs b/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs index eb5fee37..0ce6b209 100644 --- a/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs +++ b/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs @@ -163,6 +163,11 @@ namespace PepperDash.Essentials.Core.Web { Name = "Load Config", RouteHandler = new LoadConfigRequestHandler() + }, + new HttpCwsRoute("getTielines") + { + Name = "Get TieLines", + RouteHandler = new GetTieLinesRequestHandler() } }; @@ -233,32 +238,32 @@ namespace PepperDash.Essentials.Core.Web /// public void GetPaths() { - Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", new String('-', 50)); + Debug.LogMessage(LogEventLevel.Information, this, new string('-', 50)); var currentIp = CrestronEthernetHelper.GetEthernetParameter( CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); var hostname = CrestronEthernetHelper.GetEthernetParameter( CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); + + var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server + ? $"http(s)://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{BasePath}" + : $"http(s)://{currentIp}/cws{BasePath}"; - var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server - ? string.Format("http(s)://{0}/VirtualControl/Rooms/{1}/cws{2}", hostname, InitialParametersClass.RoomId, BasePath) - : string.Format("http(s)://{0}/cws{1}", currentIp, BasePath); - - Debug.LogMessage(LogEventLevel.Verbose, this, "Server:{0}", path); + Debug.LogMessage(LogEventLevel.Information, this, "Server:{path:l}", path); var routeCollection = _server.GetRouteCollection(); if (routeCollection == null) { - Debug.LogMessage(LogEventLevel.Verbose, this, "Server route collection is null"); + Debug.LogMessage(LogEventLevel.Information, this, "Server route collection is null"); return; } - Debug.LogMessage(LogEventLevel.Verbose, this, "Configured Routes:"); + Debug.LogMessage(LogEventLevel.Information, this, "Configured Routes:"); foreach (var route in routeCollection) { - Debug.LogMessage(LogEventLevel.Verbose, this, "{0}: {1}/{2}", route.Name, path, route.Url); + Debug.LogMessage(LogEventLevel.Information, this, "{routeName:l}: {routePath:l}/{routeUrl:l}", route.Name, path, route.Url); } - Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", new String('-', 50)); + Debug.LogMessage(LogEventLevel.Information, this, new string('-', 50)); } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs index a78b88ce..3599eb23 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -1,5 +1,6 @@ using System; using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; using Serilog.Events; @@ -28,7 +29,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers if (context.Request.ContentLength < 0) { context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusDescription = "Bad Request: no body"; context.Response.End(); return; @@ -38,7 +39,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers if (string.IsNullOrEmpty(data)) { context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; + context.Response.StatusDescription = "Bad Request: no body"; context.Response.End(); return; @@ -46,6 +47,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers try { + var daw = JsonConvert.DeserializeObject(data); DeviceJsonApi.DoDeviceActionWithJson(data); context.Response.StatusCode = 200; @@ -54,12 +56,11 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers } catch (Exception ex) { - Debug.LogMessage(LogEventLevel.Error, "Exception Message: {0}", ex.Message); - Debug.LogMessage(LogEventLevel.Verbose, "Exception Stack Trace: {0}", ex.StackTrace); - if(ex.InnerException != null) Debug.LogMessage(LogEventLevel.Error, "Exception Inner: {0}", ex.InnerException); + Debug.LogMessage(ex, "Error handling device command: {Exception}"); context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; + context.Response.Write(JsonConvert.SerializeObject(new { error = ex.Message }), false); context.Response.End(); } } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs index c08544cb..263eb161 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs @@ -1,6 +1,7 @@ using System.Text; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers @@ -25,6 +26,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers protected override void HandleGet(HttpCwsContext context) { var routeData = context.Request.RouteData; + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting DevMethods: {@routeData}", routeData); if (routeData == null) { context.Response.StatusCode = 400; diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs new file mode 100644 index 00000000..d5de5ad0 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs @@ -0,0 +1,34 @@ +using Crestron.SimplSharp.WebScripting; +using Newtonsoft.Json; +using PepperDash.Core.Web.RequestHandlers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers +{ + public class GetTieLinesRequestHandler:WebApiBaseRequestHandler + { + public GetTieLinesRequestHandler() : base(true) { } + + protected override void HandleGet(HttpCwsContext context) + { + var tieLineString = JsonConvert.SerializeObject(TieLineCollection.Default.Select((tl) => new { + sourceKey = tl.SourcePort.ParentDevice.Key, + sourcePort = tl.SourcePort.Key, + destinationKey = tl.DestinationPort.ParentDevice.Key, + destinationPort = tl.DestinationPort.Key + })); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = Encoding.UTF8; + context.Response.Write(tieLineString, false); + context.Response.End(); + + } + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index db14aa4d..bd141ed2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -171,7 +171,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays CurrentInputPort = inputPort; } catch (Exception ex) { - Debug.LogMessage(ex, "Error making switch: {Exception}", this); + Debug.LogMessage(ex, "Error making switch: {Exception}", this, ex); } } diff --git a/src/PepperDash.Essentials/ControlSystem.cs b/src/PepperDash.Essentials/ControlSystem.cs index d2b7a2b9..e16e7b6d 100644 --- a/src/PepperDash.Essentials/ControlSystem.cs +++ b/src/PepperDash.Essentials/ControlSystem.cs @@ -92,6 +92,8 @@ namespace PepperDash.Essentials private void StartSystem(object preventInitialization) { + Debug.SetErrorLogMinimumDebugLevel(Serilog.Events.LogEventLevel.Verbose); + DeterminePlatform(); if (Debug.DoNotLoadConfigOnNextBoot)