diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 9a48000a..1ab3b28e 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -83,10 +83,10 @@ namespace PepperDash.Essentials CrestronConsole.AddNewConsoleCommand(BridgeHelper.PrintJoinMap, "getjoinmap", "map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s); - }, "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(BridgeHelper.JoinmapMarkdown, "getjoinmapmarkdown" + , "generate markdown of map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(s => Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s), "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => { @@ -103,12 +103,16 @@ namespace PepperDash.Essentials (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r\n" + - "System URL: {0}\r\n" + - "Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl); - }, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + CrestronConsole.ConsoleCommandResponse( + "This system can be found at the following URLs:\r\n" + + "System URL: {0}\r\n" + + "Template URL: {1}", + ConfigReader.ConfigObject.SystemUrl, + ConfigReader.ConfigObject.TemplateUrl), + "portalinfo", + "Shows portal URLS from configuration", + ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts, @@ -298,6 +302,10 @@ namespace PepperDash.Essentials if (!Directory.Exists(pluginDir)) Directory.Create(pluginDir); + var joinmapDir = Global.FilePathPrefix + "joinmaps"; + if(!Directory.Exists(joinmapDir)) + Directory.Create(joinmapDir); + return configExists; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index 252c9c48..11b8f4ff 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -46,6 +46,33 @@ namespace PepperDash.Essentials.Core.Bridges bridge.PrintJoinMaps(); } } + public static void JoinmapMarkdown(string command) + { + var targets = command.Split(' '); + + var bridgeKey = targets[0].Trim(); + + var bridge = DeviceManager.GetDeviceForKey(bridgeKey) as EiscApiAdvanced; + + if (bridge == null) + { + Debug.Console(0, "Unable to find advanced bridge with key: '{0}'", bridgeKey); + return; + } + + if (targets.Length > 1) + { + var deviceKey = targets[1].Trim(); + + if (string.IsNullOrEmpty(deviceKey)) return; + bridge.MarkdownJoinMapForDevice(deviceKey, bridgeKey); + } + else + { + bridge.MarkdownForBridge(bridgeKey); + + } + } } @@ -227,6 +254,19 @@ namespace PepperDash.Essentials.Core.Bridges joinMap.Value.PrintJoinMapInfo(); } } + /// + /// Generates markdown for all join maps on this bridge + /// + public virtual void MarkdownForBridge(string bridgeKey) + { + Debug.Console(0, this, "Writing Joinmaps to files for EISC IPID: {0}", Eisc.ID.ToString("X")); + + foreach (var joinMap in JoinMaps) + { + Debug.Console(0, "Generating markdown for device '{0}':", joinMap.Key); + joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey); + } + } /// /// Prints the join map for a device by key @@ -242,9 +282,26 @@ namespace PepperDash.Essentials.Core.Bridges return; } - Debug.Console(0, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); + Debug.Console(0, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); joinMap.PrintJoinMapInfo(); } + /// + /// Prints the join map for a device by key + /// + /// + public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey) + { + var joinMap = JoinMaps[deviceKey]; + + if (joinMap == null) + { + Debug.Console(0, this, "Unable to find joinMap for device with key: '{0}'", deviceKey); + return; + } + + Debug.Console(0, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); + joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey); + } /// /// Used for debugging to trigger an action based on a join number and type diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs index 085a33bd..82c09e54 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalInputJoinMap.cs @@ -1,10 +1,10 @@ using System; -namespace PepperDash.Essentials.Core.Bridges -{ - public class IDigitalInputJoinMap : JoinMapBaseAdvanced - { - +namespace PepperDash.Essentials.Core.Bridges +{ + public class IDigitalInputJoinMap : JoinMapBaseAdvanced + { + [JoinName("InputState")] public JoinDataComplete InputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "Room Email Url", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); @@ -26,6 +26,6 @@ namespace PepperDash.Essentials.Core.Bridges protected IDigitalInputJoinMap(uint joinStart, Type type) : base(joinStart, type) { - } - } + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs new file mode 100644 index 00000000..cbe62398 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/IDigitalOutputJoinMap.cs @@ -0,0 +1,31 @@ +using System; + +namespace PepperDash.Essentials.Core.Bridges +{ + public class IDigitalOutputJoinMap : JoinMapBaseAdvanced + { + + [JoinName("OutputState")] + public JoinDataComplete OutputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Get / Set state of Digital Input", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IDigitalOutputJoinMap(uint joinStart) + : this(joinStart, typeof(IDigitalOutputJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IDigitalOutputJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs new file mode 100644 index 00000000..794fe609 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinIo8/DinIo8Controller.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.GeneralIO; +using PepperDash.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + public class DinIo8Controller:CrestronGenericBaseDevice, IIOPorts + { + private DinIo8 _device; + + public DinIo8Controller(string key, Func preActivationFunc, DeviceConfig config):base(key, config.Name) + { + AddPreActivationAction(() => + { + _device = preActivationFunc(config); + + RegisterCrestronGenericBase(_device); + }); + } + + #region Implementation of IIOPorts + + public CrestronCollection VersiPorts + { + get { return _device.VersiPorts; } + } + + public int NumberOfVersiPorts + { + get { return _device.NumberOfVersiPorts; } + } + + #endregion + + + } + + public class DinIo8ControllerFactory : EssentialsDeviceFactory + { + public DinIo8ControllerFactory() + { + TypeNames = new List() { "DinIo8" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new DinIo8 Device"); + + return new DinIo8Controller(dc.Key, GetDinIo8Device, dc); + } + + static DinIo8 GetDinIo8Device(DeviceConfig dc) + { + var control = CommFactory.GetControlPropertiesConfig(dc); + var cresnetId = control.CresnetIdInt; + var branchId = control.ControlPortNumber; + var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey; + + if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase)) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new DinIo8", parentKey); + return new DinIo8(cresnetId, Global.ControlSystem); + } + var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches; + + if (cresnetBridge != null) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new DinIo8", parentKey); + return new DinIo8(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs new file mode 100644 index 00000000..197a5b19 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/GenericVersiportOutputDevice.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Bridges; + + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + /// + /// Represents a generic digital input deviced tied to a versiport + /// + public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput + { + public Versiport OutputPort { get; private set; } + + public BoolFeedback OutputStateFeedback { get; private set; } + + Func OutputStateFeedbackFunc + { + get + { + return () => OutputPort.DigitalOut; + } + } + + public GenericVersiportDigitalOutputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : + base(key, name) + { + OutputStateFeedback = new BoolFeedback(OutputStateFeedbackFunc); + + AddPostActivationAction(() => + { + OutputPort = postActivationFunc(config); + + OutputPort.Register(); + + OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput); + if (config.DisablePullUpResistor) + OutputPort.DisablePullUpResistor = true; + + OutputPort.VersiportChange += OutputPort_VersiportChange; + + + + Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, OutputPort.DisablePullUpResistor); + + }); + + } + + void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args) + { + Debug.Console(1, this, "Versiport change: {0}", args.Event); + + if(args.Event == eVersiportEvent.DigitalOutChange) + OutputStateFeedback.FireUpdate(); + } + + /// + /// Set value of the versiport digital output + /// + /// value to set the output to + public void SetOutput(bool state) + { + OutputPort.DigitalOut = state; + } + + #region Bridge Linking + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IDigitalOutputJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } + + try + { + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + // Link feedback for input state + OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]); + trilist.SetBoolSigAction(joinMap.OutputState.JoinNumber, SetOutput); + } + catch (Exception e) + { + Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); + Debug.Console(1, this, "Error: {0}", e); + } + } + + #endregion + + + public static Versiport GetVersiportDigitalOutput(IOPortConfig dc) + { + + IIOPorts ioPortDevice; + + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsVersiport) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Processor does not support Versiports"); + return null; + } + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey); + return null; + } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + return null; + } + + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.Console(0, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + } + + return ioPortDevice.VersiPorts[dc.PortNumber]; + + } + } + + + public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory + { + public GenericVersiportDigitalOutputDeviceFactory() + { + TypeNames = new List() { "versiportoutput" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new Generic Versiport Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + if (props == null) return null; + + var portDevice = new GenericVersiportDigitalOutputDevice(dc.Key, dc.Name, GenericVersiportDigitalOutputDevice.GetVersiportDigitalOutput, props); + + return portDevice; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs new file mode 100644 index 00000000..b4151941 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Outputs/IDigitalOutput.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Essentials.Core.CrestronIO +{ + /// + /// Represents a device that provides digital input + /// + public interface IDigitalOutput + { + BoolFeedback OutputStateFeedback { get; } + void SetOutput(bool state); + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs index 708ed930..39501387 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs @@ -16,5 +16,9 @@ namespace PepperDash.Essentials.Core { return string.IsNullOrEmpty(s.Trim()) ? null : s; } + public static string ReplaceIfNullOrEmpty(this string s, string newString) + { + return string.IsNullOrEmpty(s) ? newString : s; + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs index 04abc7f8..6ffb16cc 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -1,8 +1,13 @@ using System; using System.Collections.Generic; +using System.Data; +using System.Globalization; using System.Linq; using System.Runtime.InteropServices; +using System.Text; using Crestron.SimplSharp.Reflection; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Essentials.Core.Config; @@ -193,19 +198,6 @@ namespace PepperDash.Essentials.Core protected void AddJoins(Type type) { - // Add all the JoinDataComplete properties to the Joins Dictionary and pass in the offset - //Joins = this.GetType() - // .GetCType() - // .GetFields(BindingFlags.Public | BindingFlags.Instance) - // .Where(field => field.IsDefined(typeof(JoinNameAttribute), true)) - // .Select(field => (JoinDataComplete)field.GetValue(this)) - // .ToDictionary(join => join.GetNameAttribute(), join => - // { - // join.SetJoinOffset(_joinOffset); - // return join; - // }); - - //type = this.GetType(); <- this wasn't working because 'this' was always the base class, never the derived class var fields = type.GetCType() .GetFields(BindingFlags.Public | BindingFlags.Instance) @@ -219,7 +211,7 @@ namespace PepperDash.Essentials.Core if (value == null) { - Debug.Console(0, "Unable to caset base class to {0}", type.Name); + Debug.Console(0, "Unable to cast base class to {0}", type.Name); continue; } @@ -256,12 +248,64 @@ namespace PepperDash.Essentials.Core var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value); Debug.Console(2, "Found {0} Analog Joins", analogs.Count); PrintJoinList(GetSortedJoins(analogs)); - + Debug.Console(0, "Serials:"); var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); Debug.Console(2, "Found {0} Serial Joins", serials.Count); PrintJoinList(GetSortedJoins(serials)); + } + /// + /// Prints the join information to console + /// + public void MarkdownJoinMapInfo(string deviceKey, string bridgeKey) + { + var pluginType = GetType().Name; + + Debug.Console(0, "{0}:\n", pluginType); + + var sb = new StringBuilder(); + + sb.AppendLine(String.Format("# {0}", GetType().Name)); + sb.AppendLine(String.Format("Generated from '{0}' on bridge '{1}'", deviceKey, bridgeKey)); + sb.AppendLine(); + sb.AppendLine("## Digitals"); + // Get the joins of each type and print them + var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Digital Joins", digitals.Count); + var digitalSb = AppendJoinList(GetSortedJoins(digitals)); + digitalSb.AppendLine("## Analogs"); + digitalSb.AppendLine(); + + Debug.Console(0, "Analogs:"); + var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Analog Joins", analogs.Count); + var analogSb = AppendJoinList(GetSortedJoins(analogs)); + analogSb.AppendLine("## Serials"); + analogSb.AppendLine(); + + Debug.Console(0, "Serials:"); + var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Serial Joins", serials.Count); + var serialSb = AppendJoinList(GetSortedJoins(serials)); + + sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length); + sb.Append(digitalSb).Append(analogSb).Append(serialSb); + + WriteJoinmapMarkdown(sb, pluginType, bridgeKey, deviceKey); + + } + + private static void WriteJoinmapMarkdown(StringBuilder stringBuilder, string pluginType, string bridgeKey, string deviceKey) + { + var fileName = String.Format("{0}{1}{2}__{3}__{4}.md", Global.FilePathPrefix, "joinMaps/", pluginType, bridgeKey, deviceKey); + + using (var sw = new StreamWriter(fileName)) + { + sw.WriteLine(stringBuilder.ToString()); + Debug.Console(0, "Joinmap Readme generated and written to {0}", fileName); + } + } /// @@ -293,6 +337,39 @@ namespace PepperDash.Essentials.Core } } + static StringBuilder AppendJoinList(List> joins) + { + var sb = new StringBuilder(); + const string stringFormatter = "| {0} | {1} | {2} | {3} | {4} |"; + const int joinNumberLen = 11; + const int joinSpanLen = 9; + const int typeLen = 19; + const int capabilitiesLen = 12; + var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max(); + + //build header + sb.AppendLine(String.Format(stringFormatter, + String.Format("Join Number").PadRight(joinNumberLen, ' '), + String.Format("Join Span").PadRight(joinSpanLen, ' '), + String.Format("Description").PadRight(descriptionLen, ' '), + String.Format("Type").PadRight(typeLen, ' '), + String.Format("Capabilities").PadRight(capabilitiesLen, ' '))); + //build table seperator + sb.AppendLine(String.Format(stringFormatter, + new String('-', joinNumberLen), + new String('-', joinSpanLen), + new String('-', descriptionLen), + new String('-', typeLen), + new String('-', capabilitiesLen))); + + foreach (var join in joins) + { + sb.AppendLine(join.Value.GetMarkdownFormattedData(stringFormatter, descriptionLen)); + } + sb.AppendLine(); + return sb; + } + /// /// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom /// @@ -459,6 +536,64 @@ namespace PepperDash.Essentials.Core Metadata = metadata; } + public string GetMarkdownFormattedData(string stringFormatter, int descriptionLen) + { + + //Fixed Width Headers + var joinNumberLen = String.Format("Join Number").Length; + var joinSpanLen = String.Format("Join Span").Length; + var typeLen = String.Format("AnalogDigitalSerial").Length; + var capabilitiesLen = String.Format("ToFromFusion").Length; + + //Track which one failed, if it did + const string placeholder = "unknown"; + var dataArray = new Dictionary + { + {"joinNumber", placeholder.PadRight(joinNumberLen, ' ')}, + {"joinSpan", placeholder.PadRight(joinSpanLen, ' ')}, + {"description", placeholder.PadRight(descriptionLen, ' ')}, + {"joinType", placeholder.PadRight(typeLen, ' ')}, + {"capabilities", placeholder.PadRight(capabilitiesLen, ' ')} + }; + + + try + { + dataArray["joinNumber"] = String.Format("{0}", JoinNumber.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinNumberLen, ' '); + dataArray["joinSpan"] = String.Format("{0}", JoinSpan.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinSpanLen, ' '); + dataArray["description"] = String.Format("{0}", Metadata.Description.ReplaceIfNullOrEmpty(placeholder)).PadRight(descriptionLen, ' '); + dataArray["joinType"] = String.Format("{0}", Metadata.JoinType.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(typeLen, ' '); + dataArray["capabilities"] = String.Format("{0}", Metadata.JoinCapabilities.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(capabilitiesLen, ' '); + + return String.Format(stringFormatter, + dataArray["joinNumber"], + dataArray["joinSpan"], + dataArray["description"], + dataArray["joinType"], + dataArray["capabilities"]); + + } + catch (Exception e) + { + //Don't Throw - we don't want to kill the system if this falls over - it's not mission critical. Print the error, use placeholder data + var errorKey = string.Empty; + foreach (var item in dataArray) + { + if (item.Value.TrimEnd() == placeholder) ; + errorKey = item.Key; + break; + } + Debug.Console(0, "Unable to decode join metadata {1}- {0}", e.Message, !String.IsNullOrEmpty(errorKey) ? (' ' + errorKey) : String.Empty); + return String.Format(stringFormatter, + dataArray["joinNumber"], + dataArray["joinSpan"], + dataArray["description"], + dataArray["joinType"], + dataArray["capabilities"]); + } + } + + /// /// Sets the join offset value /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index dfa59b88..2cf2928c 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -123,6 +123,7 @@ + @@ -179,12 +180,15 @@ + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs index 95a94a24..8e0cbc55 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Secrets/SecretsManager.cs @@ -148,6 +148,7 @@ namespace PepperDash.Essentials.Core { Secrets.Add(key, provider); Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key); + return; } Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key ); } @@ -164,13 +165,13 @@ namespace PepperDash.Essentials.Core { Secrets.Add(key, provider); Debug.Console(1, "Secrets provider '{0}' added to SecretsManager", key); - + return; } if (overwrite) { Secrets.Add(key, provider); Debug.Console(1, Debug.ErrorLogLevel.Notice, "Provider with the key '{0}' already exists in secrets. Overwriting with new secrets provider.", key); - + return; } Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key); }