From 601470adf4b54bf354d27afb257341b0dd1972d7 Mon Sep 17 00:00:00 2001 From: Nick Genovese Date: Tue, 17 Nov 2020 16:44:55 -0500 Subject: [PATCH] intitial plugin creationg with base features - overall online status - individual outlet naming, online, power --- ApcEpi.sln | 2 +- src/Abstractions/IApDevice.cs | 10 ++ src/Abstractions/IApDeviceBuilder.cs | 20 +++ src/Abstractions/IApOutlet.cs | 16 ++ src/Abstractions/IOutletName.cs | 9 + src/Abstractions/IOutletOnline.cs | 9 + src/Abstractions/IOutletPower.cs | 12 ++ src/ApcEpi.csproj | 25 ++- src/Builders/Ap89XxBuilder.cs | 63 +++++++ src/Config/ApDeviceConfig.cs | 24 +++ src/Devices/ApDevice.cs | 165 ++++++++++++++++++ src/Entities/Outlet/ApOutlet.cs | 63 +++++++ src/Entities/Outlet/ApOutletOnline.cs | 76 ++++++++ src/Entities/Outlet/ApOutletPower.cs | 130 ++++++++++++++ src/EssentialsPluginConfigObjectTemplate.cs | 6 - src/EssentialsPluginDeviceTemplate.cs | 57 ------ src/EssentialsPluginFactoryTemplate.cs | 35 ---- src/Factories/Ap89XxFactory.cs | 23 +++ .../ApDeviceJoinMap.cs} | 6 +- src/Services/NameCommands/ApOutletName.cs | 31 ++++ .../PowerCommands/ApOutletPowerCommands.cs | 30 ++++ .../StatusCommands/ApOutletStatusCommands.cs | 33 ++++ testconfig.json | 96 ++++++++++ 23 files changed, 833 insertions(+), 108 deletions(-) create mode 100644 src/Abstractions/IApDevice.cs create mode 100644 src/Abstractions/IApDeviceBuilder.cs create mode 100644 src/Abstractions/IApOutlet.cs create mode 100644 src/Abstractions/IOutletName.cs create mode 100644 src/Abstractions/IOutletOnline.cs create mode 100644 src/Abstractions/IOutletPower.cs create mode 100644 src/Builders/Ap89XxBuilder.cs create mode 100644 src/Config/ApDeviceConfig.cs create mode 100644 src/Devices/ApDevice.cs create mode 100644 src/Entities/Outlet/ApOutlet.cs create mode 100644 src/Entities/Outlet/ApOutletOnline.cs create mode 100644 src/Entities/Outlet/ApOutletPower.cs delete mode 100644 src/EssentialsPluginConfigObjectTemplate.cs delete mode 100644 src/EssentialsPluginDeviceTemplate.cs delete mode 100644 src/EssentialsPluginFactoryTemplate.cs create mode 100644 src/Factories/Ap89XxFactory.cs rename src/{EssentialsPluginBridgeJoinMapTemplate.cs => JoinMaps/ApDeviceJoinMap.cs} (68%) create mode 100644 src/Services/NameCommands/ApOutletName.cs create mode 100644 src/Services/PowerCommands/ApOutletPowerCommands.cs create mode 100644 src/Services/StatusCommands/ApOutletStatusCommands.cs create mode 100644 testconfig.json diff --git a/ApcEpi.sln b/ApcEpi.sln index 2998222..f4c5c7a 100644 --- a/ApcEpi.sln +++ b/ApcEpi.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApcEpi", "src/ApcEpi.csproj", "{9D249E47-8F95-4437-A6BB-563510287AD1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApcEpi", "src\ApcEpi.csproj", "{9D249E47-8F95-4437-A6BB-563510287AD1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Abstractions/IApDevice.cs b/src/Abstractions/IApDevice.cs new file mode 100644 index 0000000..9baf230 --- /dev/null +++ b/src/Abstractions/IApDevice.cs @@ -0,0 +1,10 @@ +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Abstractions +{ + public interface IApDevice : IKeyName, IOnline, ICommunicationMonitor, IHasFeedback + { + + } +} \ No newline at end of file diff --git a/src/Abstractions/IApDeviceBuilder.cs b/src/Abstractions/IApDeviceBuilder.cs new file mode 100644 index 0000000..9180866 --- /dev/null +++ b/src/Abstractions/IApDeviceBuilder.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Abstractions +{ + public interface IApDeviceBuilder : IKeyName + { + ICommunicationMonitor Monitor { get; } + IBasicCommunication Coms { get; } + ReadOnlyDictionary Outlets { get; } + CTimer Poll { get; } + + EssentialsDevice Build(); + } +} \ No newline at end of file diff --git a/src/Abstractions/IApOutlet.cs b/src/Abstractions/IApOutlet.cs new file mode 100644 index 0000000..616ff77 --- /dev/null +++ b/src/Abstractions/IApOutlet.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Abstractions +{ + public interface IApOutlet : IKeyName, IOnline, IPower + { + int OutletIndex { get; } + StringFeedback NameFeedback { get; } + } +} \ No newline at end of file diff --git a/src/Abstractions/IOutletName.cs b/src/Abstractions/IOutletName.cs new file mode 100644 index 0000000..3840dba --- /dev/null +++ b/src/Abstractions/IOutletName.cs @@ -0,0 +1,9 @@ +using PepperDash.Essentials.Core; + +namespace ApcEpi.Abstractions +{ + public interface IOutletName : IApDevice + { + bool TryGetOutletNameFeedback(uint outletIndex, out StringFeedback result); + } +} \ No newline at end of file diff --git a/src/Abstractions/IOutletOnline.cs b/src/Abstractions/IOutletOnline.cs new file mode 100644 index 0000000..75adc1d --- /dev/null +++ b/src/Abstractions/IOutletOnline.cs @@ -0,0 +1,9 @@ +using PepperDash.Essentials.Core; + +namespace ApcEpi.Abstractions +{ + public interface IOutletOnline : IApDevice + { + bool TryGetOutletOnlineFeedback(uint outletIndex, out BoolFeedback result); + } +} \ No newline at end of file diff --git a/src/Abstractions/IOutletPower.cs b/src/Abstractions/IOutletPower.cs new file mode 100644 index 0000000..02aa3cc --- /dev/null +++ b/src/Abstractions/IOutletPower.cs @@ -0,0 +1,12 @@ +using PepperDash.Essentials.Core; + +namespace ApcEpi.Abstractions +{ + public interface IOutletPower : IApDevice + { + bool TryGetOutletPowerFeedback(uint outletIndex, out BoolFeedback result); + void ToggleOutletPower(uint outletIndex); + void TurnOutletOff(uint outletIndex); + void TurnOutletOn(uint outletIndex); + } +} \ No newline at end of file diff --git a/src/ApcEpi.csproj b/src/ApcEpi.csproj index 11603f6..63166ba 100644 --- a/src/ApcEpi.csproj +++ b/src/ApcEpi.csproj @@ -79,7 +79,7 @@ False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll + ..\packages\PepperDashEssentials\lib\net35\SimplSharpNewtonsoft.dll False @@ -88,18 +88,31 @@ False - ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll + ..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll - - - - + + + + + + + + + + + + + + + + + diff --git a/src/Builders/Ap89XxBuilder.cs b/src/Builders/Ap89XxBuilder.cs new file mode 100644 index 0000000..d05e4e8 --- /dev/null +++ b/src/Builders/Ap89XxBuilder.cs @@ -0,0 +1,63 @@ +using System; +using System.Linq; +using ApcEpi.Abstractions; +using ApcEpi.Config; +using ApcEpi.Devices; +using ApcEpi.Entities.Outlet; +using Crestron.SimplSharp; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.Devices; + +namespace ApcEpi.Builders +{ + public class Ap89XxBuilder : IApDeviceBuilder + { + public static IApDeviceBuilder GetFromDeviceConfig(DeviceConfig dc) + { + var config = dc.Properties.ToObject(); + var coms = CommFactory.CreateCommForDevice(dc); + + return new Ap89XxBuilder(dc.Key, dc.Name, coms, config); + } + + private Ap89XxBuilder(string key, string name, IBasicCommunication coms, ApDeviceConfig config) + { + Coms = coms; + Name = name; + Key = key; + Outlets = BuildOutletsFromConfig(config, coms); + Monitor = new GenericCommunicationMonitoredDevice( + Key, + Name, + Coms, + "about\r"); + + Poll = new CTimer(_ => ApDevice.PollDevice(coms), null, Timeout.Infinite, 5000); + } + + public static ReadOnlyDictionary BuildOutletsFromConfig(ApDeviceConfig config, IBasicCommunication coms) + { + var outlets = config + .Outlets + .Select(x => new ApOutlet(x.Key, x.Value.Name, x.Value.OutletIndex, coms)) + .ToDictionary(outlet => (uint) outlet.OutletIndex, outlet => outlet); + + return new ReadOnlyDictionary(outlets); + } + + public string Key { get; private set; } + public string Name { get; private set; } + public ICommunicationMonitor Monitor { get; private set; } + public IBasicCommunication Coms { get; private set; } + public ReadOnlyDictionary Outlets { get; private set; } + public CTimer Poll { get; private set; } + + public EssentialsDevice Build() + { + Debug.Console(1, this, "Building..."); + return new ApDevice(this); + } + } +} \ No newline at end of file diff --git a/src/Config/ApDeviceConfig.cs b/src/Config/ApDeviceConfig.cs new file mode 100644 index 0000000..fd4504f --- /dev/null +++ b/src/Config/ApDeviceConfig.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using PepperDash.Core; + +namespace ApcEpi.Config +{ + public class ApDeviceConfig + { + public ControlPropertiesConfig Control { get; set; } + public Dictionary Outlets { get; set; } + } + + public class ApOutletConfig + { + public string Name { get; set; } + public int OutletIndex { get; set; } + public int DelayOn { get; set; } + public int DelayOff { get; set; } + } +} \ No newline at end of file diff --git a/src/Devices/ApDevice.cs b/src/Devices/ApDevice.cs new file mode 100644 index 0000000..657f14c --- /dev/null +++ b/src/Devices/ApDevice.cs @@ -0,0 +1,165 @@ +using System; +using ApcEpi.Abstractions; +using ApcEpi.JoinMaps; +using ApcEpi.Services.StatusCommands; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DeviceSupport; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using Feedback = PepperDash.Essentials.Core.Feedback; + +namespace ApcEpi.Devices +{ + public class ApDevice: EssentialsDevice, IOutletName, IOutletPower, IOutletOnline + { + private readonly ICommunicationMonitor _monitor; + private readonly CTimer _poll; + private readonly ReadOnlyDictionary _outlets; + + public ApDevice(IApDeviceBuilder builder) + : base(builder.Key, builder.Name) + { + Feedbacks = new FeedbackCollection(); + + _outlets = builder.Outlets; + _monitor = builder.Monitor; + _poll = builder.Poll; + + Feedbacks.Add(IsOnline); + } + + public StatusMonitorBase CommunicationMonitor + { + get { return _monitor.CommunicationMonitor; } + } + + public FeedbackCollection Feedbacks { get; private set; } + + public BoolFeedback IsOnline + { + get { return _monitor.CommunicationMonitor.IsOnlineFeedback; } + } + + public override bool CustomActivate() + { + CommunicationMonitor.Start(); + _poll.Reset(2000, 5000); + + foreach (var apOutlet in _outlets.Values) + { + Feedbacks.AddRange(new Feedback[] + { + apOutlet.IsOnline, + apOutlet.NameFeedback, + apOutlet.PowerIsOnFeedback + }); + } + + return true; + } + + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new ApDeviceJoinMap(joinStart); + + if (bridge != null) + bridge.AddJoinMap(Key, joinMap); + + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + + if (customJoins != null) + joinMap.SetCustomJoinData(customJoins); + + Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.Console(0, "Linking to Bridge Type {0}", GetType().Name); + + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) + return; + + foreach (var feedback in Feedbacks) + feedback.FireUpdate(); + }; + } + + public void ToggleOutletPower(uint outletIndex) + { + IApOutlet outlet; + if (_outlets.TryGetValue(outletIndex, out outlet)) + { + outlet.PowerToggle(); + return; + } + + Debug.Console(1, this, "Outlet at index-{0} does not exist", outletIndex); + } + + public bool TryGetOutletNameFeedback(uint outletIndex, out StringFeedback result) + { + result = new StringFeedback(Key + "-OutletName-" + outletIndex, () => String.Empty); + IApOutlet outlet; + if (!_outlets.TryGetValue(outletIndex, out outlet)) + return false; + + result = outlet.NameFeedback; + return true; + } + + public bool TryGetOutletOnlineFeedback(uint outletIndex, out BoolFeedback result) + { + result = new BoolFeedback(Key + "-OutletName-" + outletIndex, () => false); + IApOutlet outlet; + if (!_outlets.TryGetValue(outletIndex, out outlet)) + return false; + + result = outlet.IsOnline; + return true; + } + + public bool TryGetOutletPowerFeedback(uint outletIndex, out BoolFeedback result) + { + result = new BoolFeedback(Key + "-OutletPower-" + outletIndex, () => false); + IApOutlet outlet; + if (!_outlets.TryGetValue(outletIndex, out outlet)) + return false; + + result = outlet.PowerIsOnFeedback; + return true; + } + + public void TurnOutletOff(uint outletIndex) + { + IApOutlet outlet; + if (_outlets.TryGetValue(outletIndex, out outlet)) + { + outlet.PowerOff(); + return; + } + + Debug.Console(1, this, "Outlet at index-{0} does not exist", outletIndex); + } + + public void TurnOutletOn(uint outletIndex) + { + IApOutlet outlet; + if (_outlets.TryGetValue(outletIndex, out outlet)) + { + outlet.PowerOn(); + return; + } + + Debug.Console(1, this, "Outlet at index-{0} does not exist", outletIndex); + } + + public static void PollDevice(IBasicCommunication coms) + { + if (coms == null) + return; + + var command = ApOutletStatusCommands.GetAllOutletStatusCommand(); + coms.SendText(command); + } + } +} \ No newline at end of file diff --git a/src/Entities/Outlet/ApOutlet.cs b/src/Entities/Outlet/ApOutlet.cs new file mode 100644 index 0000000..10b97c7 --- /dev/null +++ b/src/Entities/Outlet/ApOutlet.cs @@ -0,0 +1,63 @@ +using ApcEpi.Abstractions; +using ApcEpi.Services.NameCommands; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Entities.Outlet +{ + public class ApOutlet : IApOutlet + { + private readonly IOnline _online; + private readonly IPower _power; + + public ApOutlet(string key, string name, int outletIndex, IBasicCommunication coms) + { + Key = key; + Name = name; + OutletIndex = outletIndex; + NameFeedback = new StringFeedback(Key + "-OutletName-" + name, () => Name); + + _online = new ApOutletOnline(key, name, outletIndex, coms); + _power = new ApOutletPower(key, name, outletIndex, coms); + + IsOnline.OutputChange += (sender, args) => + { + if (!args.BoolValue) + return; + + var outletNameCommand = ApOutletNameCommands.GetOutletNameCommand(outletIndex, name); + coms.SendText(outletNameCommand); + }; + } + + public BoolFeedback IsOnline + { + get { return _online.IsOnline; } + } + + public string Key { get; private set; } + public string Name { get; private set; } + public int OutletIndex { get; private set; } + public StringFeedback NameFeedback { get; private set; } + + public BoolFeedback PowerIsOnFeedback + { + get { return _power.PowerIsOnFeedback; } + } + + public void PowerOff() + { + _power.PowerOff(); + } + + public void PowerOn() + { + _power.PowerOn(); + } + + public void PowerToggle() + { + _power.PowerToggle(); + } + } +} \ No newline at end of file diff --git a/src/Entities/Outlet/ApOutletOnline.cs b/src/Entities/Outlet/ApOutletOnline.cs new file mode 100644 index 0000000..fa9bf71 --- /dev/null +++ b/src/Entities/Outlet/ApOutletOnline.cs @@ -0,0 +1,76 @@ +using System; +using Crestron.SimplSharp; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Entities.Outlet +{ + public class ApOutletOnline : IOnline, IKeyName + { + private readonly string _matchString; + + private readonly CTimer _offlineTimer; + private bool _isOnline; + + public ApOutletOnline(string key, string name, int outletIndex, IBasicCommunication coms) + { + Key = key; + Name = name; + _matchString = String.Format("{0}: {1}", name, outletIndex); + + IsOnline = new BoolFeedback( + key + "-Power", + () => _isOnline); + + InitializeGather(coms); + + _offlineTimer = new CTimer( + _ => + { + _isOnline = false; + IsOnline.FireUpdate(); + }, + this, + 30000, + 30000); + } + + public BoolFeedback IsOnline { get; private set; } + + public string Key { get; private set; } + public string Name { get; private set; } + + private void GatherOnLineReceived(object sender, GenericCommMethodReceiveTextArgs args) + { + if (!args.Text.Contains(_matchString)) + return; + + _isOnline = true; + IsOnline.FireUpdate(); + _offlineTimer.Reset(30000, 30000); + } + + private void InitializeGather(ICommunicationReceiver coms) + { + var gather = new CommunicationGather(coms, "\n"); + gather.LineReceived += GatherOnLineReceived; + + CrestronEnvironment.ProgramStatusEventHandler += type => + { + switch (type) + { + case eProgramStatusEventType.Stopping: + gather.LineReceived -= GatherOnLineReceived; + gather.Stop(); + break; + case eProgramStatusEventType.Paused: + break; + case eProgramStatusEventType.Resumed: + break; + default: + throw new ArgumentOutOfRangeException("type"); + } + }; + } + } +} \ No newline at end of file diff --git a/src/Entities/Outlet/ApOutletPower.cs b/src/Entities/Outlet/ApOutletPower.cs new file mode 100644 index 0000000..ccda944 --- /dev/null +++ b/src/Entities/Outlet/ApOutletPower.cs @@ -0,0 +1,130 @@ +using System; +using ApcEpi.Services.PowerCommands; +using Crestron.SimplSharp; +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Entities.Outlet +{ + public class ApOutletPower : IPower, IKeyName + { + private readonly IBasicCommunication _coms; + + private readonly string _matchString; + private readonly string _powerOffCommand; + private readonly string _powerOnCommand; + private bool _powerIsOn; + + public ApOutletPower(string key, string name, int outletIndex, IBasicCommunication coms) + { + Key = key; + Name = name; + _coms = coms; + _matchString = String.Format("{0}: {1}", name, outletIndex); + + PowerIsOnFeedback = new BoolFeedback( + key + "-Power", + () => _powerIsOn); + + InitializeGather(coms); + + _powerOnCommand = ApOutletPowerCommands.GetPowerOnCommand(outletIndex); + _powerOffCommand = ApOutletPowerCommands.GetPowerOffCommand(outletIndex); + } + + public enum PowerResponseEnum + { + On, + Off + } + + public string Key { get; private set; } + public string Name { get; private set; } + + public BoolFeedback PowerIsOnFeedback { get; private set; } + + public void PowerOff() + { + if (!_powerIsOn) + return; + + _coms.SendText(_powerOffCommand); + } + + public void PowerOn() + { + if (_powerIsOn) + return; + + _coms.SendText(_powerOnCommand); + } + + public void PowerToggle() + { + if (_powerIsOn) + PowerOff(); + else + PowerOn(); + } + + private static PowerResponseEnum GetOutletStatusFromResponse(string response) + { + response = response.Replace(" ", String.Empty); + var splitResponse = response.Split(new[] {':', ' '}); + + try + { + return (PowerResponseEnum) Enum.Parse(typeof (PowerResponseEnum), splitResponse[3], true); + } + catch (Exception ex) + { + Debug.Console(1, "Error parsing power response:{0} | {1}", response, ex.Message); + throw; + } + } + + private void GatherOnLineReceived(object sender, GenericCommMethodReceiveTextArgs args) + { + if (!args.Text.Contains(_matchString)) + return; + + var status = GetOutletStatusFromResponse(args.Text); + switch (status) + { + case PowerResponseEnum.On: + _powerIsOn = true; + break; + case PowerResponseEnum.Off: + _powerIsOn = false; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + PowerIsOnFeedback.FireUpdate(); + } + + private void InitializeGather(ICommunicationReceiver coms) + { + var gather = new CommunicationGather(coms, "\n"); + gather.LineReceived += GatherOnLineReceived; + + CrestronEnvironment.ProgramStatusEventHandler += type => + { + switch (type) + { + case eProgramStatusEventType.Stopping: + gather.LineReceived -= GatherOnLineReceived; + gather.Stop(); + break; + case eProgramStatusEventType.Paused: + break; + case eProgramStatusEventType.Resumed: + break; + default: + throw new ArgumentOutOfRangeException("type"); + } + }; + } + } +} \ No newline at end of file diff --git a/src/EssentialsPluginConfigObjectTemplate.cs b/src/EssentialsPluginConfigObjectTemplate.cs deleted file mode 100644 index 70c4e01..0000000 --- a/src/EssentialsPluginConfigObjectTemplate.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace EssentialsPluginTemplateEPI -{ - public class EssentialsPluginConfigObjectTemplate - { - } -} \ No newline at end of file diff --git a/src/EssentialsPluginDeviceTemplate.cs b/src/EssentialsPluginDeviceTemplate.cs deleted file mode 100644 index d23c8d1..0000000 --- a/src/EssentialsPluginDeviceTemplate.cs +++ /dev/null @@ -1,57 +0,0 @@ -// For Basic SIMPL# Classes -// For Basic SIMPL#Pro classes -using Crestron.SimplSharpPro.DeviceSupport; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Core; - -namespace EssentialsPluginTemplateEPI -{ - public class EssentialsPluginDeviceTemplate : EssentialsBridgeableDevice - { - private EssentialsPluginConfigObjectTemplate _config; - - public EssentialsPluginDeviceTemplate(string key, string name, EssentialsPluginConfigObjectTemplate config) - : base(key, name) - { - Debug.Console(0, this, "Constructing new EssentialsPluginDeviceTemplate instance"); - _config = config; - } - - #region Overrides of EssentialsBridgeableDevice - - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new EssentialsPluginBridgeJoinMapTemplate(joinStart); - - // This adds the join map to the collection on the bridge - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } - - Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.Console(0, "Linking to Bridge Type {0}", GetType().Name); - - - trilist.OnlineStatusChange += (o, a) => - { - if (a.DeviceOnLine) - { - trilist.SetString(joinMap.DeviceName.JoinNumber, Name); - } - }; - } - - - #endregion - } -} - diff --git a/src/EssentialsPluginFactoryTemplate.cs b/src/EssentialsPluginFactoryTemplate.cs deleted file mode 100644 index d6c305e..0000000 --- a/src/EssentialsPluginFactoryTemplate.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -using PepperDash.Core; -using PepperDash.Essentials.Core; - -using Newtonsoft.Json; - -namespace EssentialsPluginTemplateEPI -{ - public class EssentialsPluginFactoryTemplate : EssentialsPluginDeviceFactory - { - public EssentialsPluginFactoryTemplate() - { - // Set the minimum Essentials Framework Version - MinimumEssentialsFrameworkVersion = "1.5.5"; - - // In the constructor we initialize the list with the typenames that will build an instance of this device - TypeNames = new List() { "examplePluginDevice" }; - } - - // Builds and returns an instance of EssentialsPluginDeviceTemplate - public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new device from type: {0}", dc.Type); - - var propertiesConfig = dc.Properties.ToObject(); - return new EssentialsPluginDeviceTemplate(dc.Key, dc.Name, propertiesConfig); - } - - } -} \ No newline at end of file diff --git a/src/Factories/Ap89XxFactory.cs b/src/Factories/Ap89XxFactory.cs new file mode 100644 index 0000000..98c2483 --- /dev/null +++ b/src/Factories/Ap89XxFactory.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using ApcEpi.Builders; +using ApcEpi.Devices; +using PepperDash.Essentials.Core; + +namespace ApcEpi.Factories +{ + public class Ap89XxFactory : EssentialsPluginDeviceFactory + { + public Ap89XxFactory() + { + MinimumEssentialsFrameworkVersion = "1.6.4"; + TypeNames = new List() { "Ap89xx" }; + } + + public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc) + { + return Ap89XxBuilder + .GetFromDeviceConfig(dc) + .Build(); + } + } +} \ No newline at end of file diff --git a/src/EssentialsPluginBridgeJoinMapTemplate.cs b/src/JoinMaps/ApDeviceJoinMap.cs similarity index 68% rename from src/EssentialsPluginBridgeJoinMapTemplate.cs rename to src/JoinMaps/ApDeviceJoinMap.cs index 4bde9f2..bb1a622 100644 --- a/src/EssentialsPluginBridgeJoinMapTemplate.cs +++ b/src/JoinMaps/ApDeviceJoinMap.cs @@ -1,8 +1,8 @@ using PepperDash.Essentials.Core; -namespace EssentialsPluginTemplateEPI +namespace ApcEpi.JoinMaps { - public class EssentialsPluginBridgeJoinMapTemplate : JoinMapBaseAdvanced + public class ApDeviceJoinMap : JoinMapBaseAdvanced { public JoinDataComplete DeviceName = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 1}, new JoinMetadata @@ -12,7 +12,7 @@ public class EssentialsPluginBridgeJoinMapTemplate : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - public EssentialsPluginBridgeJoinMapTemplate(uint joinStart) + public ApDeviceJoinMap(uint joinStart) :base(joinStart) { } diff --git a/src/Services/NameCommands/ApOutletName.cs b/src/Services/NameCommands/ApOutletName.cs new file mode 100644 index 0000000..691b56f --- /dev/null +++ b/src/Services/NameCommands/ApOutletName.cs @@ -0,0 +1,31 @@ +using System.Text; + +namespace ApcEpi.Services.NameCommands +{ + public class ApOutletNameCommands + { + public const string Command = "olName"; + + public static string GetOutletNameCommand(int outletNumber, string name) + { + var builder = new StringBuilder(Command); + builder.Append(" "); + builder.Append(outletNumber); + builder.Append(" "); + builder.Append(name); + builder.AppendLine(); + + return builder.ToString(); + } + + public static string GetOutletPollCommand(int outletNumber) + { + var builder = new StringBuilder(Command); + builder.Append(" "); + builder.Append(outletNumber); + builder.AppendLine(); + + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/src/Services/PowerCommands/ApOutletPowerCommands.cs b/src/Services/PowerCommands/ApOutletPowerCommands.cs new file mode 100644 index 0000000..2097c93 --- /dev/null +++ b/src/Services/PowerCommands/ApOutletPowerCommands.cs @@ -0,0 +1,30 @@ +using System.Text; + +namespace ApcEpi.Services.PowerCommands +{ + public class ApOutletPowerCommands + { + public const string PowerOnCommand = "olOn"; + public const string PowerOffCommand = "olOff"; + + public static string GetPowerOnCommand(int outletIndex) + { + var builder = new StringBuilder(PowerOnCommand); + builder.Append(" "); + builder.Append(outletIndex); + builder.AppendLine(); + + return builder.ToString(); + } + + public static string GetPowerOffCommand(int outletIndex) + { + var builder = new StringBuilder(PowerOffCommand); + builder.Append(" "); + builder.Append(outletIndex); + builder.AppendLine(); + + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/src/Services/StatusCommands/ApOutletStatusCommands.cs b/src/Services/StatusCommands/ApOutletStatusCommands.cs new file mode 100644 index 0000000..e33b8ae --- /dev/null +++ b/src/Services/StatusCommands/ApOutletStatusCommands.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace ApcEpi.Services.StatusCommands +{ + public class ApOutletStatusCommands + { + public const string Command = "olStatus"; + + public static string GetOutletStatusCommand(int outletIndex) + { + var builder = new StringBuilder(Command); + builder.Append(" "); + builder.Append(outletIndex); + builder.AppendLine(); + + return builder.ToString(); + } + + public static string GetAllOutletStatusCommand() + { + var builder = new StringBuilder(Command); + builder.Append(" "); + builder.Append("all"); + builder.AppendLine(); + + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/testconfig.json b/testconfig.json new file mode 100644 index 0000000..37cf14b --- /dev/null +++ b/testconfig.json @@ -0,0 +1,96 @@ +{ + "system": {}, + "system_url": "http://portal-QA.devcloud.pepperdash.com/templates/0f50640b-bc89-42d5-998f-81d137d3fc98#/template_summary", + "template": { + "devices": [ + { + "type": "pro3", + "name": "PRO3 w/o cards", + "group": "processor", + "supportedConfigModes": [ + "compliance", + "essentials" + ], + "supportedSystemTypes": [ + "hudType", + "presType", + "vtcType", + "custom" + ], + "supportsCompliance": true, + "properties": { + "numberOfComPorts": 6, + "numberOfIrPorts": 8, + "numberOfRelays": 8, + "numberOfDIOPorts": 8 + }, + "key": "processor", + "uid": 0 + }, + { + "key": "PowerSupply01", + "uid": 74, + "name": "PowerSupply01", + "type": "Apc8xx", + "group": "power", + "properties": { + "control": { + "endOfLineString": "\n", + "deviceReadyResponsePattern": "", + "method": "ssh", + "tcpSshProperties": { + "address": "192.168.10.205", + "port": 22, + "autoReconnect": true, + "AutoReconnectIntervalMs": 10000, + "username": "", + "password": "" + } + }, + "outlets": + { + "outlet01" : { + "name": "Outlet 1", + "outletIndex": 1, + "delayOn": 30, + "delayOff": 2 + } + } + } + }, + { + "key": "BridgeEisc-APC", + "uid": 13422, + "name": "APC Bridge", + "group": "api", + "type": "eiscapiadvanced", + "properties": { + "control": { + "tcpSshProperties": { + "address": "127.0.0.2", + "port": 0 + }, + "ipid": "fd", + "method": "ipidTcp" + }, + "devices": [ + { + "deviceKey": "Coms-Dsp", + "joinStart": 1 + } + ] + } + } + ], + "info": { + "comment": "", + "lastModifiedDate": "2017-03-06T23:14:40.290Z", + "lastUid": 8, + "processorType": "Pro3", + "requiredControlSofwareVersion": "", + "systemType": "huddle" + }, + "rooms": [], + "tieLines": [] + } +} \ No newline at end of file