diff --git a/.github/scripts/GenerateVersionNumber.ps1 b/.github/scripts/GenerateVersionNumber.ps1 index 75a18d37..9cccbf43 100644 --- a/.github/scripts/GenerateVersionNumber.ps1 +++ b/.github/scripts/GenerateVersionNumber.ps1 @@ -1,5 +1,8 @@ $latestVersions = $(git tag --merged origin/main) $latestVersion = [version]"0.0.0" +Write-Host "GITHUB_REF: $($Env:GITHUB_REF)" +Write-Host "GITHUB_HEAD_REF: $($Env:GITHUB_HEAD_REF)" +Write-Host "GITHUB_BASE_REF: $($Env:GITHUB_BASE_REF)" Foreach ($version in $latestVersions) { Write-Host $version try { @@ -17,7 +20,13 @@ Foreach ($version in $latestVersions) { $newVersion = [version]$latestVersion $phase = "" $newVersionString = "" + switch -regex ($Env:GITHUB_REF) { + '^refs\/pull\/*.' { + $splitRef = $Env:GITHUB_REF -split "/" + $phase = "pr$($splitRef[2])" + $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER + } '^refs\/heads\/main*.' { $newVersionString = "{0}.{1}.{2}" -f $newVersion.Major, $newVersion.Minor, $newVersion.Build } @@ -43,6 +52,7 @@ switch -regex ($Env:GITHUB_REF) { $phase = 'hotfix' $newVersionString = "{0}.{1}.{2}-{3}-{4}" -f $newVersion.Major, $newVersion.Minor, ($newVersion.Build + 1), $phase, $Env:GITHUB_RUN_NUMBER } + } diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3eb3e42e..315fbd67 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -8,6 +8,9 @@ on: - bugfix/* - release/* - development + pull_request: + branches: + - development env: # solution path doesn't need slashes unless there it is multiple folders deep @@ -29,14 +32,7 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 - # And any submodules - - name: Checkout submodules - shell: bash - run: | - git config --global url."https://github.com/".insteadOf "git@github.com:" - auth_header="$(git config --local --get http.https://github.com/.extraheader)" - git submodule sync --recursive - git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + submodules: true # Fetch all tags - name: Fetch tags run: git fetch --tags diff --git a/.github/workflows/master.yml b/.github/workflows/main.yml similarity index 100% rename from .github/workflows/master.yml rename to .github/workflows/main.yml diff --git a/PepperDashEssentials/Bridges/EiscBridge.cs b/PepperDashEssentials/Bridges/EiscBridge.cs index 9af277a9..21a220ef 100644 --- a/PepperDashEssentials/Bridges/EiscBridge.cs +++ b/PepperDashEssentials/Bridges/EiscBridge.cs @@ -158,12 +158,12 @@ namespace PepperDash.Essentials.Bridges try { if (Debug.Level >= 1) - Debug.Console(1, this, "EiscApi change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); + Debug.Console(2, this, "EiscApi change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); var uo = args.Sig.UserObject; if (uo == null) return; - Debug.Console(1, this, "Executing Action: {0}", uo.ToString()); + Debug.Console(2, this, "Executing Action: {0}", uo.ToString()); if (uo is Action) (uo as Action)(args.Sig.BoolValue); else if (uo is Action) diff --git a/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json b/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json index 3fb02ce8..f66add0c 100644 --- a/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json +++ b/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json @@ -175,6 +175,10 @@ { "deviceKey": "gls-odt-1", "joinStart": 2751 + }, + { + "deviceKey": "gls-part-1", + "joinStart": 2781 } ] } @@ -427,6 +431,19 @@ "method": "cresnet" } } + }, + { + "key": "gls-part-1", + "uid": 19, + "name": "GLS-PART-CN 1", + "type": "glspartcn", + "group": "partition", + "properties": { + "control": { + "cresnetId": "90", + "method": "cresnet" + } + } } ], "rooms": [], diff --git a/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs b/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs index c6c85d1a..4b0ef2b2 100644 --- a/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs +++ b/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs @@ -1,23 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; +using System; +using System.Linq; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.Fusion; -using PepperDash.Core; -using PepperDash.Essentials; +using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.Fusion; -using PepperDash.Essentials.Devices.Common; -using PepperDash.Essentials.Devices.Common.Occupancy; - +using PepperDash.Essentials.Core.Fusion; + namespace PepperDash.Essentials.Fusion { public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs index 60f4d970..ec6c2ebe 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/BridgeBase.cs @@ -198,11 +198,11 @@ namespace PepperDash.Essentials.Core.Bridges var uo = Eisc.BooleanOutput[join].UserObject as Action; if (uo != null) { - Debug.Console(1, this, "Executing Action: {0}", uo.ToString()); + Debug.Console(2, this, "Executing Action: {0}", uo.ToString()); uo(Convert.ToBoolean(state)); } else - Debug.Console(1, this, "User Action is null. Nothing to Execute"); + Debug.Console(2, this, "User Action is null. Nothing to Execute"); break; } case "analog": @@ -210,27 +210,27 @@ namespace PepperDash.Essentials.Core.Bridges var uo = Eisc.BooleanOutput[join].UserObject as Action; if (uo != null) { - Debug.Console(1, this, "Executing Action: {0}", uo.ToString()); + Debug.Console(2, this, "Executing Action: {0}", uo.ToString()); uo(Convert.ToUInt16(state)); } else - Debug.Console(1, this, "User Action is null. Nothing to Execute"); break; + Debug.Console(2, this, "User Action is null. Nothing to Execute"); break; } case "serial": { var uo = Eisc.BooleanOutput[join].UserObject as Action; if (uo != null) { - Debug.Console(1, this, "Executing Action: {0}", uo.ToString()); + Debug.Console(2, this, "Executing Action: {0}", uo.ToString()); uo(Convert.ToString(state)); } else - Debug.Console(1, this, "User Action is null. Nothing to Execute"); + Debug.Console(2, this, "User Action is null. Nothing to Execute"); break; } default: { - Debug.Console(1, "Unknown join type. Use digital/serial/analog"); + Debug.Console(2, "Unknown join type. Use digital/serial/analog"); break; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs new file mode 100644 index 00000000..cc554790 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Bridges.JoinMaps +{ + public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced + { + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData() + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Is Online", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete( + new JoinData() + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("Enable")] + public JoinDataComplete Enable = new JoinDataComplete( + new JoinData() + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Enable", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PartitionSensed")] + public JoinDataComplete PartitionSensed = new JoinDataComplete( + new JoinData() + { + JoinNumber = 3, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Partition Sensed", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PartitionNotSensed")] + public JoinDataComplete PartitionNotSensed = new JoinDataComplete( + new JoinData() + { + JoinNumber = 4, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Partition Not Sensed", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncreaseSensitivity")] + public JoinDataComplete IncreaseSensitivity = new JoinDataComplete( + new JoinData() + { + JoinNumber = 6, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Increase Sensitivity", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DecreaseSensitivity")] + public JoinDataComplete DecreaseSensitivity = new JoinDataComplete( + new JoinData() + { + JoinNumber = 7, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Decrease Sensitivity", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Sensitivity")] + public JoinDataComplete Sensitivity = new JoinDataComplete( + new JoinData() + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata() + { + Description = "Sensor Sensitivity", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + public GlsPartitionSensorJoinMap(uint joinStart) + : base(joinStart, typeof (GlsPartitionSensorJoinMap)) + { + + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nRts/C2nRthsController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nRts/C2nRthsController.cs index 73279368..e1aa545e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nRts/C2nRthsController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/C2nRts/C2nRthsController.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.GeneralIO; @@ -13,21 +14,30 @@ namespace PepperDash.Essentials.Core.CrestronIO [Description("Wrapper class for the C2N-RTHS sensor")] public class C2nRthsController : CrestronGenericBridgeableBaseDevice { - private readonly C2nRths _device; + private C2nRths _device; public IntFeedback TemperatureFeedback { get; private set; } public IntFeedback HumidityFeedback { get; private set; } - public C2nRthsController(string key, string name, GenericBase hardware) : base(key, name, hardware) + public C2nRthsController(string key, Func preActivationFunc, + DeviceConfig config) + : base(key, config.Name) { - _device = hardware as C2nRths; - TemperatureFeedback = new IntFeedback(() => _device.TemperatureFeedback.UShortValue); - HumidityFeedback = new IntFeedback(() => _device.HumidityFeedback.UShortValue); + AddPreActivationAction(() => + { + _device = preActivationFunc(config); - if (_device != null) _device.BaseEvent += DeviceOnBaseEvent; + RegisterCrestronGenericBase(_device); + + TemperatureFeedback = new IntFeedback(() => _device.TemperatureFeedback.UShortValue); + HumidityFeedback = new IntFeedback(() => _device.HumidityFeedback.UShortValue); + + if (_device != null) _device.BaseEvent += DeviceOnBaseEvent; + }); } + private void DeviceOnBaseEvent(GenericBase device, BaseEventArgs args) { switch (args.EventId) @@ -76,24 +86,63 @@ namespace PepperDash.Essentials.Core.CrestronIO HumidityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Humidity.JoinNumber]); trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name; - } - } - public class C2nRthsControllerFactory : EssentialsDeviceFactory - { - public C2nRthsControllerFactory() - { - TypeNames = new List() { "c2nrths" }; + trilist.OnlineStatusChange += (d, args) => + { + if (!args.DeviceOnLine) return; + + UpdateFeedbacksWhenOnline(); + + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name; + }; } - public override EssentialsDevice BuildDevice(DeviceConfig dc) + private void UpdateFeedbacksWhenOnline() { - Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); + IsOnline.FireUpdate(); + TemperatureFeedback.FireUpdate(); + HumidityFeedback.FireUpdate(); + } + #region PreActivation + + private static C2nRths GetC2nRthsDevice(DeviceConfig dc) + { var control = CommFactory.GetControlPropertiesConfig(dc); var cresnetId = control.CresnetIdInt; + var branchId = control.ControlPortNumber; + var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey; - return new C2nRthsController(dc.Key, dc.Name, new C2nRths(cresnetId, Global.ControlSystem)); + if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase)) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nRths", parentKey); + return new C2nRths(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 C2nRths", parentKey); + return new C2nRths(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + #endregion + + public class C2nRthsControllerFactory : EssentialsDeviceFactory + { + public C2nRthsControllerFactory() + { + TypeNames = new List() { "c2nrths" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); + + return new C2nRthsController(dc.Key, GetC2nRthsDevice, dc); + } } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs new file mode 100644 index 00000000..68fedc82 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/DinCenCnController.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.GeneralIO; +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + + +namespace PepperDash.Essentials.Core +{ + public class DinCenCn2Controller : CrestronGenericBaseDevice, IHasCresnetBranches + { + private readonly DinCenCn2 _device; + + public CrestronCollection CresnetBranches + { + get { + return _device != null ? _device.Branches : null; + } + } + + public DinCenCn2Controller(string key, string name, DinCenCn2 device, DeviceConfig config) + : base(key, name, device) + { + _device = device; + } + + public class DinCenCn2ControllerFactory : EssentialsDeviceFactory + { + public DinCenCn2ControllerFactory() + { + TypeNames = new List() { "dincencn2", "dincencn2poe", "din-cencn2", "din-cencn2-poe" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); + + var control = CommFactory.GetControlPropertiesConfig(dc); + var ipid = control.IpIdInt; + + if (dc.Type.ToLower().Contains("poe")) + { + return new DinCenCn2Controller(dc.Key, dc.Name, new DinCenCn2Poe(ipid, Global.ControlSystem), dc); + } + + return new DinCenCn2Controller(dc.Key, dc.Name, new DinCenCn2(ipid, Global.ControlSystem), dc); + } + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/IHasCresnetBranches.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/IHasCresnetBranches.cs new file mode 100644 index 00000000..11e1b707 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/DinCenCn/IHasCresnetBranches.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; + +namespace PepperDash.Essentials.Core +{ + public interface IHasCresnetBranches + { + CrestronCollection CresnetBranches { get; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/StatusSign/StatusSignController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/StatusSign/StatusSignController.cs index 1bd22ebe..6f0cf80e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/StatusSign/StatusSignController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/StatusSign/StatusSignController.cs @@ -13,7 +13,7 @@ namespace PepperDash.Essentials.Core.CrestronIO [Description("Wrapper class for the Crestron StatusSign device")] public class StatusSignController : CrestronGenericBridgeableBaseDevice { - private readonly StatusSign _device; + private StatusSign _device; public BoolFeedback RedLedEnabledFeedback { get; private set; } public BoolFeedback GreenLedEnabledFeedback { get; private set; } @@ -23,34 +23,40 @@ namespace PepperDash.Essentials.Core.CrestronIO public IntFeedback GreenLedBrightnessFeedback { get; private set; } public IntFeedback BlueLedBrightnessFeedback { get; private set; } - public StatusSignController(string key, string name, GenericBase hardware) : base(key, name, hardware) + public StatusSignController(string key, Func preActivationFunc, DeviceConfig config) : base(key, config.Name) { - _device = hardware as StatusSign; + AddPreActivationAction(() => + { + _device = preActivationFunc(config); - RedLedEnabledFeedback = + RegisterCrestronGenericBase(_device); + + RedLedEnabledFeedback = new BoolFeedback( () => - _device.Leds[(uint) StatusSign.Led.eLedColor.Red] - .ControlFeedback.BoolValue); - GreenLedEnabledFeedback = - new BoolFeedback( - () => - _device.Leds[(uint) StatusSign.Led.eLedColor.Green] - .ControlFeedback.BoolValue); - BlueLedEnabledFeedback = - new BoolFeedback( - () => - _device.Leds[(uint) StatusSign.Led.eLedColor.Blue] + _device.Leds[(uint)StatusSign.Led.eLedColor.Red] .ControlFeedback.BoolValue); + GreenLedEnabledFeedback = + new BoolFeedback( + () => + _device.Leds[(uint)StatusSign.Led.eLedColor.Green] + .ControlFeedback.BoolValue); + BlueLedEnabledFeedback = + new BoolFeedback( + () => + _device.Leds[(uint)StatusSign.Led.eLedColor.Blue] + .ControlFeedback.BoolValue); - RedLedBrightnessFeedback = - new IntFeedback(() => (int) _device.Leds[(uint) StatusSign.Led.eLedColor.Red].BrightnessFeedback); - GreenLedBrightnessFeedback = - new IntFeedback(() => (int) _device.Leds[(uint) StatusSign.Led.eLedColor.Green].BrightnessFeedback); - BlueLedBrightnessFeedback = - new IntFeedback(() => (int) _device.Leds[(uint) StatusSign.Led.eLedColor.Blue].BrightnessFeedback); + RedLedBrightnessFeedback = + new IntFeedback(() => (int)_device.Leds[(uint)StatusSign.Led.eLedColor.Red].BrightnessFeedback); + GreenLedBrightnessFeedback = + new IntFeedback(() => (int)_device.Leds[(uint)StatusSign.Led.eLedColor.Green].BrightnessFeedback); + BlueLedBrightnessFeedback = + new IntFeedback(() => (int)_device.Leds[(uint)StatusSign.Led.eLedColor.Blue].BrightnessFeedback); - if (_device != null) _device.BaseEvent += _device_BaseEvent; + if (_device != null) _device.BaseEvent += _device_BaseEvent; + + }); } void _device_BaseEvent(GenericBase device, BaseEventArgs args) @@ -167,23 +173,51 @@ namespace PepperDash.Essentials.Core.CrestronIO device.SetColor(redBrightness, greenBrightness, blueBrightness); } - } - public class StatusSignControllerFactory : EssentialsDeviceFactory - { - public StatusSignControllerFactory() + #region PreActivation + + private static StatusSign GetStatusSignDevice(DeviceConfig dc) { - TypeNames = new List() { "statussign" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new StatusSign Device"); - var control = CommFactory.GetControlPropertiesConfig(dc); var cresnetId = control.CresnetIdInt; + var branchId = control.ControlPortNumber; + var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey; - return new StatusSignController(dc.Key, dc.Name, new StatusSign(cresnetId, Global.ControlSystem)); + if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase)) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new StatusSign", parentKey); + return new StatusSign(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 StatusSign", parentKey); + return new StatusSign(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + #endregion + + public class StatusSignControllerFactory : EssentialsDeviceFactory + { + public StatusSignControllerFactory() + { + TypeNames = new List() { "statussign" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new StatusSign Device"); + + var control = CommFactory.GetControlPropertiesConfig(dc); + var cresnetId = control.CresnetIdInt; + + return new StatusSignController(dc.Key, GetStatusSignDevice, dc); + } } } + + } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs index 7866075f..9db81122 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs @@ -1,7 +1,9 @@ -using System.Linq; +using System; +using System.Linq; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; +using PepperDash.Core.JsonStandardObjects; using PepperDash.Essentials.Core.Bridges; namespace PepperDash.Essentials.Core @@ -11,7 +13,7 @@ namespace PepperDash.Essentials.Core /// public abstract class CrestronGenericBaseDevice : EssentialsDevice, IOnline, IHasFeedback, ICommunicationMonitor, IUsageTracking { - public virtual GenericBase Hardware { get; protected set; } + protected GenericBase Hardware; /// /// Returns a list containing the Outputs that we want to expose. @@ -42,6 +44,24 @@ namespace PepperDash.Essentials.Core CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); } + protected CrestronGenericBaseDevice(string key, string name) + : base(key, name) + { + Feedbacks = new FeedbackCollection(); + + } + + protected void RegisterCrestronGenericBase(GenericBase hardware) + { + Hardware = hardware; + IsOnline = new BoolFeedback("IsOnlineFeedback", () => Hardware.IsOnline); + IsRegistered = new BoolFeedback("IsRegistered", () => Hardware.Registered); + IpConnectionsText = new StringFeedback("IpConnectionsText", () => Hardware.ConnectedIpList != null ? string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()) : string.Empty); + AddToFeedbackList(IsOnline, IpConnectionsText); + + CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); + } + /// /// Make sure that overriding classes call this! /// Registers the Crestron device, connects up to the base events, starts communication monitor @@ -135,6 +155,11 @@ namespace PepperDash.Essentials.Core { } + protected CrestronGenericBridgeableBaseDevice(string key, string name) + : base(key, name) + { + } + public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs index 8cc0e95c..dfc63911 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs @@ -238,6 +238,42 @@ namespace PepperDash.Essentials.Core } } + public static void AddDevice(IEnumerable devicesToAdd) + { + try + { + if (!DeviceCriticalSection.TryEnter()) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "Currently unable to add devices to Device Manager. Please try again"); + return; + } + if (!AddDeviceEnabled) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "All devices have been activated. Adding new devices is not allowed."); + return; + } + + foreach (var dev in devicesToAdd) + { + try + { + Devices.Add(dev.Key, dev); + } + catch (ArgumentException ex) + { + Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}", + dev.Key, ex.Message, ex.StackTrace); + } + } + } + finally + { + DeviceCriticalSection.Leave(); + } + } + public static void RemoveDevice(IKeyed newDev) { try diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/ReadyEventArgs.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/ReadyEventArgs.cs new file mode 100644 index 00000000..89c0b7b3 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/ReadyEventArgs.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash_Essentials_Core +{ + public class IsReadyEventArgs : EventArgs + { + public bool IsReady { get; set; } + + public IsReadyEventArgs(bool data) + { + IsReady = data; + } + } + + public interface IHasReady + { + event EventHandler IsReadyEvent; + bool IsReady { get; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Gateways/CenRfgwController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Gateways/CenRfgwController.cs index 1fd7da6d..fb7968d9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Gateways/CenRfgwController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Gateways/CenRfgwController.cs @@ -6,134 +6,192 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.Gateways; using Newtonsoft.Json; +using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; +using PepperDash_Essentials_Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core { - [Description("Wrapper class for Crestron Infinet-EX Gateways")] - public class CenRfgwController : CrestronGenericBaseDevice - { - private GatewayBase _Gateway; - public GatewayBase GateWay { get { return _Gateway; } } - - /// - /// Constructor for the on-board gateway - /// - /// - /// - public CenRfgwController(string key, string name, GatewayBase gateway) : - base(key, name, gateway) - { - _Gateway = gateway; - } - - public static CenRfgwController GetNewExGatewayController(string key, string name, ushort ipId, ushort cresnetId, string gatewayType) - { - eExGatewayType type = (eExGatewayType)Enum.Parse(typeof(eExGatewayType), gatewayType, true); - try - { - var cs = Global.ControlSystem; - - GatewayBase gw = null; - switch (type) - { - case eExGatewayType.Ethernet: - gw = new CenRfgwEx(ipId, cs); - break; - case eExGatewayType.EthernetShared: - gw = new CenRfgwExEthernetSharable(ipId, cs); - break; - case eExGatewayType.Cresnet: - gw = new CenRfgwExCresnet(cresnetId, cs); - break; - } - return new CenRfgwController(key, name, gw); - } - catch (Exception) - { - Debug.Console(0, "ERROR: Cannot create EX Gateway, id {0}, type {1}", type == eExGatewayType.Cresnet ? cresnetId : ipId, gatewayType); - return null; - } - } - public static CenRfgwController GetNewErGatewayController(string key, string name, ushort ipId, ushort cresnetId, string gatewayType) - { - eExGatewayType type = (eExGatewayType)Enum.Parse(typeof(eExGatewayType), gatewayType, true); - try - { - var cs = Global.ControlSystem; - - GatewayBase gw = null; - switch (type) - { - case eExGatewayType.Ethernet: - gw = new CenErfgwPoe(ipId, cs); - break; - case eExGatewayType.EthernetShared: - gw = new CenErfgwPoeEthernetSharable(ipId, cs); - break; - case eExGatewayType.Cresnet: - gw = new CenErfgwPoeCresnet(cresnetId, cs); - break; - } - return new CenRfgwController(key, name, gw); - } - catch (Exception) - { - Debug.Console(0, "ERROR: Cannot create ER Gateway, id {0}, type {1}", type== eExGatewayType.Cresnet ? cresnetId : ipId, gatewayType); - return null; - } - } - - } - - - - public enum eExGatewayType - { - Ethernet, EthernetShared, Cresnet - } + [Description("Wrapper class for Crestron Infinet-EX Gateways")] + public class CenRfgwController : CrestronGenericBaseDevice, IHasReady + { + public event EventHandler IsReadyEvent; + public bool IsReady { get; private set; } - #region Factory - public class CenRfgwControllerFactory : EssentialsDeviceFactory - { - public CenRfgwControllerFactory() - { - TypeNames = new List() { "cenrfgwex", "cenerfgwpoe" }; - } + private GatewayBase _gateway; - public override EssentialsDevice BuildDevice(DeviceConfig dc) + public GatewayBase GateWay { - - Debug.Console(1, "Factory Attempting to create new CEN-GWEXER Device"); - - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - - var type = dc.Type.ToLower(); - var control = props.Control; - var ipid = control.IpIdInt; - var cresnetId = control.CresnetIdInt; - var gatewayType = props.GatewayType; - - switch (type) - { - case ("cenrfgwex"): - return CenRfgwController.GetNewExGatewayController(dc.Key, dc.Name, - (ushort)ipid, (ushort)cresnetId, gatewayType); - case ("cenerfgwpoe"): - return CenRfgwController.GetNewErGatewayController(dc.Key, dc.Name, - (ushort)ipid, (ushort)cresnetId, gatewayType); - default: - return null; - } + get { return _gateway; } } + + /// + /// Constructor for the on-board gateway + /// + /// + /// + /// + public CenRfgwController(string key, string name, GatewayBase gateway) : + base(key, name, gateway) + { + _gateway = gateway; + IsReady = true; + FireIsReadyEvent(IsReady); + } + + public CenRfgwController(string key, Func preActivationFunc, DeviceConfig config) : + base(key, config.Name) + { + IsReady = false; + FireIsReadyEvent(IsReady); + AddPreActivationAction(() => + { + _gateway = preActivationFunc(config); + + IsReady = true; + RegisterCrestronGenericBase(_gateway); + FireIsReadyEvent(IsReady); + + }); + } + + public static GatewayBase GetNewIpRfGateway(DeviceConfig dc) + { + var control = CommFactory.GetControlPropertiesConfig(dc); + var type = dc.Type; + var ipId = control.IpIdInt; + + if (type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenRfgwEx(ipId, Global.ControlSystem); + } + if (type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenErfgwPoe(ipId, Global.ControlSystem); + } + return null; + } + + private void FireIsReadyEvent(bool data) + { + var handler = IsReadyEvent; + if (handler == null) return; + + handler(this, new IsReadyEventArgs(data)); + + } + + public static GatewayBase GetNewSharedIpRfGateway(DeviceConfig dc) + { + var control = CommFactory.GetControlPropertiesConfig(dc); + var ipId = control.IpIdInt; + + if (dc.Type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenRfgwExEthernetSharable(ipId, Global.ControlSystem); + } + if (dc.Type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenErfgwPoeEthernetSharable(ipId, Global.ControlSystem); + } + return null; + } + + public static GatewayBase GetCenRfgwCresnetController(DeviceConfig dc) + { + var control = CommFactory.GetControlPropertiesConfig(dc); + var type = dc.Type; + 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 CenRfgw", parentKey); + if (type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenErfgwPoeCresnet(cresnetId, Global.ControlSystem); + } + if (type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenRfgwExCresnet(cresnetId, Global.ControlSystem); + } + } + var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as ICresnetBridge; + + if (cresnetBridge != null) + { + Debug.Console(0, "Device {0} is a valid cresnet master - creating new CenRfgw", parentKey); + + if (type.Equals("cenerfgwpoe", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenErfgwPoeCresnet(cresnetId, cresnetBridge.Branches[branchId]); + } + if (type.Equals("cenrfgwex", StringComparison.InvariantCultureIgnoreCase)) + { + return new CenRfgwExCresnet(cresnetId, cresnetBridge.Branches[branchId]); + } + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + + + + + + + + public enum EExGatewayType + { + Ethernet, + EthernetShared, + Cresnet + } + + + #region Factory + + public class CenRfgwControllerFactory : EssentialsDeviceFactory + { + public CenRfgwControllerFactory() + { + TypeNames = new List {"cenrfgwex", "cenerfgwpoe"}; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + + Debug.Console(1, "Factory Attempting to create new CEN-GWEXER Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + EExGatewayType gatewayType = + (EExGatewayType) Enum.Parse(typeof (EExGatewayType), props.GatewayType, true); + + switch (gatewayType) + { + case (EExGatewayType.Ethernet): + return new CenRfgwController(dc.Key, dc.Name, GetNewIpRfGateway(dc)); + case (EExGatewayType.EthernetShared): + return new CenRfgwController(dc.Key, dc.Name, GetNewSharedIpRfGateway(dc)); + case (EExGatewayType.Cresnet): + return new CenRfgwController(dc.Key, GetCenRfgwCresnetController, dc); + } + return null; + } + } + + #endregion } - #endregion + + +} -} \ 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 676299e5..ba6b3482 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -1,488 +1,488 @@ -using System; -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; -using Crestron.SimplSharp.Reflection; - -using PepperDash.Core; -using PepperDash.Essentials.Core.Config; - -using Newtonsoft.Json; - -namespace PepperDash.Essentials.Core -{ - public static class JoinMapHelper - { - /// - /// Attempts to get the serialized join map from config - /// - /// - /// - public static string GetSerializedJoinMapForDevice(string joinMapKey) - { - if (string.IsNullOrEmpty(joinMapKey)) - return null; - - var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; - - return joinMap; - } - - /// - /// Attempts to get the serialized join map from config - /// - /// - /// - public static string GetJoinMapForDevice(string joinMapKey) - { - return GetSerializedJoinMapForDevice(joinMapKey); - } - - /// - /// Attempts to find a custom join map by key and returns it deserialized if found - /// - /// - /// - public static Dictionary TryGetJoinMapAdvancedForDevice(string joinMapKey) - { - if (string.IsNullOrEmpty(joinMapKey)) - return null; - - var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; - - if (joinMapSerialzed == null) return null; - - var joinMapData = JsonConvert.DeserializeObject>(joinMapSerialzed); - - return joinMapData; - } - - } - - /// - /// Base class for join maps - /// - [Obsolete("This is being deprecated in favor of JoinMapBaseAdvanced")] - public abstract class JoinMapBase - { - /// - /// Modifies all the join numbers by adding the offset. This should never be called twice - /// - /// - public abstract void OffsetJoinNumbers(uint joinStart); - - /// - /// The collection of joins and associated metadata - /// - public Dictionary Joins = new Dictionary(); - - /// - /// Prints the join information to console - /// - public void PrintJoinMapInfo() - { - Debug.Console(0, "{0}:\n", GetType().Name); - - // Get the joins of each type and print them - Debug.Console(0, "Digitals:"); - var digitals = Joins.Where(j => (j.Value.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Digital Joins", digitals.Count); - PrintJoinList(GetSortedJoins(digitals)); - - Debug.Console(0, "Analogs:"); - var analogs = Joins.Where(j => (j.Value.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.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Serial Joins", serials.Count); - PrintJoinList(GetSortedJoins(serials)); - - } - - /// - /// Returns a sorted list by JoinNumber - /// - /// - /// - List> GetSortedJoins(Dictionary joins) - { - var sortedJoins = joins.ToList(); - - sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber)); - - return sortedJoins; - } - - void PrintJoinList(List> joins) - { - foreach (var join in joins) - { - Debug.Console(0, - @"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'", - join.Value.JoinNumber, - join.Value.Label, - join.Value.JoinSpan, - join.Value.JoinType.ToString(), - join.Value.JoinCapabilities.ToString()); - } - } - - /// - /// Returns the join number for the join with the specified key - /// - /// - /// - public uint GetJoinForKey(string key) - { - return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0; - } - - /// - /// Returns the join span for the join with the specified key - /// - /// - /// - public uint GetJoinSpanForKey(string key) - { - return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0; - } - } - - /// - /// Base class for join maps - /// - public abstract class JoinMapBaseAdvanced - { - protected uint JoinOffset; - - /// - /// The collection of joins and associated metadata - /// - public Dictionary Joins { get; private set; } - - protected JoinMapBaseAdvanced(uint joinStart) - { - Joins = new Dictionary(); - - JoinOffset = joinStart - 1; - } - - protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart) - { - AddJoins(type); - } - - 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) - .Where(f => f.IsDefined(typeof (JoinNameAttribute), true)); - - foreach (var field in fields) - { - var childClass = Convert.ChangeType(this, type, null); - - var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields. - - if (value == null) - { - Debug.Console(0, "Unable to caset base class to {0}", type.Name); - continue; - } - - value.SetJoinOffset(JoinOffset); - - var joinName = value.GetNameAttribute(field); - - if (String.IsNullOrEmpty(joinName)) continue; - - Joins.Add(joinName, value); - } - - - PrintJoinMapInfo(); - } - - /// - /// Prints the join information to console - /// - public void PrintJoinMapInfo() - { - Debug.Console(0, "{0}:\n", GetType().Name); - - // Get the joins of each type and print them - Debug.Console(0, "Digitals:"); - 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); - PrintJoinList(GetSortedJoins(digitals)); - - 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); - 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)); - - } - - /// - /// Returns a sorted list by JoinNumber - /// - /// - /// - List> GetSortedJoins(Dictionary joins) - { - var sortedJoins = joins.ToList(); - - sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber)); - - return sortedJoins; - } - - void PrintJoinList(List> joins) - { - foreach (var join in joins) - { - Debug.Console(0, - @"Join Number: {0} | JoinSpan: '{1}' | Label: '{2}' | Type: '{3}' | Capabilities: '{4}'", - join.Value.JoinNumber, - join.Value.JoinSpan, - join.Value.Metadata.Label, - join.Value.Metadata.JoinType.ToString(), - join.Value.Metadata.JoinCapabilities.ToString()); - } - } - - /// - /// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom - /// - /// - public void SetCustomJoinData(Dictionary joinData) - { - foreach (var customJoinData in joinData) - { - var join = Joins[customJoinData.Key]; - - if (join != null) - { - join.SetCustomJoinData(customJoinData.Value); - } - else - { - Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key); - } - } - - PrintJoinMapInfo(); - } - - ///// - ///// Returns the join number for the join with the specified key - ///// - ///// - ///// - //public uint GetJoinForKey(string key) - //{ - // return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0; - //} - - - ///// - ///// Returns the join span for the join with the specified key - ///// - ///// - ///// - //public uint GetJoinSpanForKey(string key) - //{ - // return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0; - //} - } - - /// - /// Read = Provides feedback to SIMPL - /// Write = Responds to sig values from SIMPL - /// - [Flags] - public enum eJoinCapabilities - { - None = 0, - ToSIMPL = 1, - FromSIMPL = 2, - ToFromSIMPL = ToSIMPL | FromSIMPL - } - - [Flags] - public enum eJoinType - { - None = 0, - Digital = 1, - Analog = 2, - Serial = 4, - DigitalAnalog = Digital | Analog, - DigitalSerial = Digital | Serial, - AnalogSerial = Analog | Serial, - DigitalAnalogSerial = Digital | Analog | Serial - } - - /// - /// Metadata describing the join - /// - public class JoinMetadata +using Crestron.SimplSharp.Reflection; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + +using Newtonsoft.Json; + +namespace PepperDash.Essentials.Core +{ + public static class JoinMapHelper { - private string _description; - - /// - /// Join number (based on join offset value) - /// - [JsonProperty("joinNumber")] - [Obsolete] - public uint JoinNumber { get; set; } - /// - /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range - /// - [Obsolete] - [JsonProperty("joinSpan")] - public uint JoinSpan { get; set; } - - /// - /// A label for the join to better describe its usage - /// - [Obsolete("Use Description instead")] - [JsonProperty("label")] - public string Label { get { return _description; } set { _description = value; } } - /// - /// A description for the join to better describe its usage - /// - [JsonProperty("description")] - public string Description { get { return _description; } set { _description = value; } } - /// - /// Signal type(s) - /// - [JsonProperty("joinType")] - public eJoinType JoinType { get; set; } - /// - /// Indicates whether the join is read and/or write - /// - [JsonProperty("joinCapabilities")] - public eJoinCapabilities JoinCapabilities { get; set; } - /// - /// Indicates a set of valid values (particularly if this translates to an enum - /// - [JsonProperty("validValues")] - public string[] ValidValues { get; set; } - - } - - /// - /// Data describing the join. Can be - /// - public class JoinData - { - /// - /// Join number (based on join offset value) - /// - [JsonProperty("joinNumber")] - public uint JoinNumber { get; set; } - /// - /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range - /// - [JsonProperty("joinSpan")] - public uint JoinSpan { get; set; } - } - - /// - /// A class to aggregate the JoinData and JoinMetadata for a join - /// - public class JoinDataComplete - { - private uint _joinOffset; - - private JoinData _data; - public JoinMetadata Metadata { get; set; } - - public JoinDataComplete(JoinData data, JoinMetadata metadata) - { - _data = data; - Metadata = metadata; - } - - /// - /// Sets the join offset value - /// - /// - public void SetJoinOffset(uint joinOffset) - { - _joinOffset = joinOffset; - } - - /// - /// The join number (including the offset) - /// - public uint JoinNumber - { - get { return _data.JoinNumber+ _joinOffset; } - set { _data.JoinNumber = value; } - } - - public uint JoinSpan - { - get { return _data.JoinSpan; } - } - - public void SetCustomJoinData(JoinData customJoinData) - { - _data = customJoinData; - } - - public string GetNameAttribute(MemberInfo memberInfo) - { - var name = string.Empty; - var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute)); - - if (attribute == null) return name; - - name = attribute.Name; - Debug.Console(2, "JoinName Attribute value: {0}", name); - return name; + /// Attempts to get the serialized join map from config + /// + /// + /// + public static string GetSerializedJoinMapForDevice(string joinMapKey) + { + if (string.IsNullOrEmpty(joinMapKey)) + return null; + + var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; + + return joinMap; + } + + /// + /// Attempts to get the serialized join map from config + /// + /// + /// + public static string GetJoinMapForDevice(string joinMapKey) + { + return GetSerializedJoinMapForDevice(joinMapKey); + } + + /// + /// Attempts to find a custom join map by key and returns it deserialized if found + /// + /// + /// + public static Dictionary TryGetJoinMapAdvancedForDevice(string joinMapKey) + { + if (string.IsNullOrEmpty(joinMapKey)) + return null; + + var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; + + if (joinMapSerialzed == null) return null; + + var joinMapData = JsonConvert.DeserializeObject>(joinMapSerialzed); + + return joinMapData; + } + + } + + /// + /// Base class for join maps + /// + [Obsolete("This is being deprecated in favor of JoinMapBaseAdvanced")] + public abstract class JoinMapBase + { + /// + /// Modifies all the join numbers by adding the offset. This should never be called twice + /// + /// + public abstract void OffsetJoinNumbers(uint joinStart); + + /// + /// The collection of joins and associated metadata + /// + public Dictionary Joins = new Dictionary(); + + /// + /// Prints the join information to console + /// + public void PrintJoinMapInfo() + { + Debug.Console(0, "{0}:\n", GetType().Name); + + // Get the joins of each type and print them + Debug.Console(0, "Digitals:"); + var digitals = Joins.Where(j => (j.Value.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Digital Joins", digitals.Count); + PrintJoinList(GetSortedJoins(digitals)); + + Debug.Console(0, "Analogs:"); + var analogs = Joins.Where(j => (j.Value.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.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); + Debug.Console(2, "Found {0} Serial Joins", serials.Count); + PrintJoinList(GetSortedJoins(serials)); + + } + + /// + /// Returns a sorted list by JoinNumber + /// + /// + /// + List> GetSortedJoins(Dictionary joins) + { + var sortedJoins = joins.ToList(); + + sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber)); + + return sortedJoins; + } + + void PrintJoinList(List> joins) + { + foreach (var join in joins) + { + Debug.Console(0, + @"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'", + join.Value.JoinNumber, + join.Value.Label, + join.Value.JoinSpan, + join.Value.JoinType.ToString(), + join.Value.JoinCapabilities.ToString()); + } + } + + /// + /// Returns the join number for the join with the specified key + /// + /// + /// + public uint GetJoinForKey(string key) + { + return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0; + } + + /// + /// Returns the join span for the join with the specified key + /// + /// + /// + public uint GetJoinSpanForKey(string key) + { + return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0; } } - - - [AttributeUsage(AttributeTargets.All)] - public class JoinNameAttribute : CAttribute - { - private string _Name; - - public JoinNameAttribute(string name) - { - Debug.Console(2, "Setting Attribute Name: {0}", name); - _Name = name; - } - - public string Name - { - get { return _Name; } - } + /// + /// Base class for join maps + /// + public abstract class JoinMapBaseAdvanced + { + protected uint JoinOffset; + + /// + /// The collection of joins and associated metadata + /// + public Dictionary Joins { get; private set; } + + protected JoinMapBaseAdvanced(uint joinStart) + { + Joins = new Dictionary(); + + JoinOffset = joinStart - 1; + } + + protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart) + { + AddJoins(type); + } + + 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) + .Where(f => f.IsDefined(typeof (JoinNameAttribute), true)); + + foreach (var field in fields) + { + var childClass = Convert.ChangeType(this, type, null); + + var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields. + + if (value == null) + { + Debug.Console(0, "Unable to caset base class to {0}", type.Name); + continue; + } + + value.SetJoinOffset(JoinOffset); + + var joinName = value.GetNameAttribute(field); + + if (String.IsNullOrEmpty(joinName)) continue; + + Joins.Add(joinName, value); + } + + + PrintJoinMapInfo(); + } + + /// + /// Prints the join information to console + /// + public void PrintJoinMapInfo() + { + Debug.Console(0, "{0}:\n", GetType().Name); + + // Get the joins of each type and print them + Debug.Console(0, "Digitals:"); + 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); + PrintJoinList(GetSortedJoins(digitals)); + + 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); + 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)); + + } + + /// + /// Returns a sorted list by JoinNumber + /// + /// + /// + List> GetSortedJoins(Dictionary joins) + { + var sortedJoins = joins.ToList(); + + sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber)); + + return sortedJoins; + } + + void PrintJoinList(List> joins) + { + foreach (var join in joins) + { + Debug.Console(0, + @"Join Number: {0} | JoinSpan: '{1}' | Label: '{2}' | Type: '{3}' | Capabilities: '{4}'", + join.Value.JoinNumber, + join.Value.JoinSpan, + join.Value.Metadata.Label, + join.Value.Metadata.JoinType.ToString(), + join.Value.Metadata.JoinCapabilities.ToString()); + } + } + + /// + /// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom + /// + /// + public void SetCustomJoinData(Dictionary joinData) + { + foreach (var customJoinData in joinData) + { + var join = Joins[customJoinData.Key]; + + if (join != null) + { + join.SetCustomJoinData(customJoinData.Value); + } + else + { + Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key); + } + } + + PrintJoinMapInfo(); + } + + ///// + ///// Returns the join number for the join with the specified key + ///// + ///// + ///// + //public uint GetJoinForKey(string key) + //{ + // return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0; + //} + + + ///// + ///// Returns the join span for the join with the specified key + ///// + ///// + ///// + //public uint GetJoinSpanForKey(string key) + //{ + // return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0; + //} + } + + /// + /// Read = Provides feedback to SIMPL + /// Write = Responds to sig values from SIMPL + /// + [Flags] + public enum eJoinCapabilities + { + None = 0, + ToSIMPL = 1, + FromSIMPL = 2, + ToFromSIMPL = ToSIMPL | FromSIMPL + } + + [Flags] + public enum eJoinType + { + None = 0, + Digital = 1, + Analog = 2, + Serial = 4, + DigitalAnalog = Digital | Analog, + DigitalSerial = Digital | Serial, + AnalogSerial = Analog | Serial, + DigitalAnalogSerial = Digital | Analog | Serial + } + + /// + /// Metadata describing the join + /// + public class JoinMetadata + { + private string _description; + + /// + /// Join number (based on join offset value) + /// + [JsonProperty("joinNumber")] + [Obsolete] + public uint JoinNumber { get; set; } + /// + /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range + /// + [Obsolete] + [JsonProperty("joinSpan")] + public uint JoinSpan { get; set; } + + /// + /// A label for the join to better describe its usage + /// + [Obsolete("Use Description instead")] + [JsonProperty("label")] + public string Label { get { return _description; } set { _description = value; } } + + /// + /// A description for the join to better describe its usage + /// + [JsonProperty("description")] + public string Description { get { return _description; } set { _description = value; } } + /// + /// Signal type(s) + /// + [JsonProperty("joinType")] + public eJoinType JoinType { get; set; } + /// + /// Indicates whether the join is read and/or write + /// + [JsonProperty("joinCapabilities")] + public eJoinCapabilities JoinCapabilities { get; set; } + /// + /// Indicates a set of valid values (particularly if this translates to an enum + /// + [JsonProperty("validValues")] + public string[] ValidValues { get; set; } + + } + + /// + /// Data describing the join. Can be + /// + public class JoinData + { + /// + /// Join number (based on join offset value) + /// + [JsonProperty("joinNumber")] + public uint JoinNumber { get; set; } + /// + /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range + /// + [JsonProperty("joinSpan")] + public uint JoinSpan { get; set; } + } + + /// + /// A class to aggregate the JoinData and JoinMetadata for a join + /// + public class JoinDataComplete + { + private uint _joinOffset; + + private JoinData _data; + public JoinMetadata Metadata { get; set; } + + public JoinDataComplete(JoinData data, JoinMetadata metadata) + { + _data = data; + Metadata = metadata; + } + + /// + /// Sets the join offset value + /// + /// + public void SetJoinOffset(uint joinOffset) + { + _joinOffset = joinOffset; + } + + /// + /// The join number (including the offset) + /// + public uint JoinNumber + { + get { return _data.JoinNumber+ _joinOffset; } + set { _data.JoinNumber = value; } + } + + public uint JoinSpan + { + get { return _data.JoinSpan; } + } + + public void SetCustomJoinData(JoinData customJoinData) + { + _data = customJoinData; + } + + public string GetNameAttribute(MemberInfo memberInfo) + { + var name = string.Empty; + var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute)); + + if (attribute == null) return name; + + name = attribute.Name; + Debug.Console(2, "JoinName Attribute value: {0}", name); + return name; + } + } + + + + [AttributeUsage(AttributeTargets.All)] + public class JoinNameAttribute : CAttribute + { + private string _Name; + + public JoinNameAttribute(string name) + { + Debug.Console(2, "Setting Attribute Name: {0}", name); + _Name = name; + } + + public string Name + { + get { return _Name; } + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/CenOdtOccupancySensorBaseController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/CenOdtOccupancySensorBaseController.cs similarity index 97% rename from essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/CenOdtOccupancySensorBaseController.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/CenOdtOccupancySensorBaseController.cs index c64b62be..603abeef 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/CenOdtOccupancySensorBaseController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/CenOdtOccupancySensorBaseController.cs @@ -11,7 +11,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Devices.Common.Occupancy +namespace PepperDash.Essentials.Core { [Description("Wrapper class for CEN-ODT-C-POE")] public class CenOdtOccupancySensorBaseController : CrestronGenericBridgeableBaseDevice, IOccupancyStatusProvider diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig similarity index 100% rename from essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/GlsOccupancySensorBaseController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/GlsOccupancySensorBaseController.cs similarity index 72% rename from essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/GlsOccupancySensorBaseController.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/GlsOccupancySensorBaseController.cs index b6508920..077be4f5 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/GlsOccupancySensorBaseController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/GlsOccupancySensorBaseController.cs @@ -11,7 +11,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Devices.Common.Occupancy +namespace PepperDash.Essentials.Core { [Description("Wrapper class for Single Technology GLS Occupancy Sensors")] public class GlsOccupancySensorBaseController : CrestronGenericBridgeableBaseDevice, IOccupancyStatusProvider @@ -55,11 +55,29 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy } } - public GlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor) - : base(key, name, sensor) + public GlsOccupancySensorBaseController(string key, Func preActivationFunc, + DeviceConfig config) + : base(key, config.Name) { - OccSensor = sensor; - + + + AddPreActivationAction(() => + { + OccSensor = preActivationFunc(config); + + RegisterCrestronGenericBase(OccSensor); + + RegisterGlsOdtSensorBaseController(OccSensor); + + }); + } + + public GlsOccupancySensorBaseController(string key, string name) : base(key, name) {} + + protected void RegisterGlsOdtSensorBaseController(GlsOccupancySensorBase occSensor) + { + OccSensor = occSensor; + RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc); PirSensorEnabledFeedback = new BoolFeedback(() => OccSensor.PirEnabledFeedback.BoolValue); @@ -68,15 +86,18 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy ShortTimeoutEnabledFeedback = new BoolFeedback(() => OccSensor.ShortTimeoutEnabledFeedback.BoolValue); - PirSensitivityInVacantStateFeedback = new IntFeedback(() => OccSensor.PirSensitivityInVacantStateFeedback.UShortValue); + PirSensitivityInVacantStateFeedback = + new IntFeedback(() => OccSensor.PirSensitivityInVacantStateFeedback.UShortValue); - PirSensitivityInOccupiedStateFeedback = new IntFeedback(() => OccSensor.PirSensitivityInOccupiedStateFeedback.UShortValue); + PirSensitivityInOccupiedStateFeedback = + new IntFeedback(() => OccSensor.PirSensitivityInOccupiedStateFeedback.UShortValue); CurrentTimeoutFeedback = new IntFeedback(() => OccSensor.CurrentTimeoutFeedback.UShortValue); LocalTimoutFeedback = new IntFeedback(() => OccSensor.LocalTimeoutFeedback.UShortValue); - GraceOccupancyDetectedFeedback = new BoolFeedback(() => OccSensor.GraceOccupancyDetectedFeedback.BoolValue); + GraceOccupancyDetectedFeedback = + new BoolFeedback(() => OccSensor.GraceOccupancyDetectedFeedback.BoolValue); RawOccupancyFeedback = new BoolFeedback(() => OccSensor.RawOccupancyFeedback.BoolValue); @@ -84,9 +105,9 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy ExternalPhotoSensorValue = new IntFeedback(() => OccSensor.ExternalPhotoSensorValueFeedback.UShortValue); - OccSensor.BaseEvent += new Crestron.SimplSharpPro.BaseEventHandler(OccSensor_BaseEvent); + OccSensor.BaseEvent += OccSensor_BaseEvent; - OccSensor.GlsOccupancySensorChange += new GlsOccupancySensorChangeEventHandler(OccSensor_GlsOccupancySensorChange); + OccSensor.GlsOccupancySensorChange += OccSensor_GlsOccupancySensorChange; } @@ -97,40 +118,56 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy /// protected virtual void OccSensor_GlsOccupancySensorChange(GlsOccupancySensorBase device, GlsOccupancySensorChangeEventArgs args) { - if (args.EventId == GlsOccupancySensorBase.PirEnabledFeedbackEventId) - PirSensorEnabledFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.LedFlashEnabledFeedbackEventId) - LedFlashEnabledFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.ShortTimeoutEnabledFeedbackEventId) - ShortTimeoutEnabledFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.PirSensitivityInOccupiedStateFeedbackEventId) - PirSensitivityInOccupiedStateFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.PirSensitivityInVacantStateFeedbackEventId) - PirSensitivityInVacantStateFeedback.FireUpdate(); + switch (args.EventId) + { + case GlsOccupancySensorBase.PirEnabledFeedbackEventId: + PirSensorEnabledFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.LedFlashEnabledFeedbackEventId: + LedFlashEnabledFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.ShortTimeoutEnabledFeedbackEventId: + ShortTimeoutEnabledFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.PirSensitivityInOccupiedStateFeedbackEventId: + PirSensitivityInOccupiedStateFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.PirSensitivityInVacantStateFeedbackEventId: + PirSensitivityInVacantStateFeedback.FireUpdate(); + break; + } } protected virtual void OccSensor_BaseEvent(Crestron.SimplSharpPro.GenericBase device, Crestron.SimplSharpPro.BaseEventArgs args) { Debug.Console(2, this, "GlsOccupancySensorChange EventId: {0}", args.EventId); - if (args.EventId == Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomOccupiedFeedbackEventId - || args.EventId == Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomVacantFeedbackEventId) + switch (args.EventId) { - Debug.Console(1, this, "Occupancy State: {0}", OccSensor.OccupancyDetectedFeedback.BoolValue); - RoomIsOccupiedFeedback.FireUpdate(); + case Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomVacantFeedbackEventId: + case Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomOccupiedFeedbackEventId: + Debug.Console(1, this, "Occupancy State: {0}", OccSensor.OccupancyDetectedFeedback.BoolValue); + RoomIsOccupiedFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.TimeoutFeedbackEventId: + CurrentTimeoutFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.TimeoutLocalFeedbackEventId: + LocalTimoutFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.GraceOccupancyDetectedFeedbackEventId: + GraceOccupancyDetectedFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.RawOccupancyFeedbackEventId: + RawOccupancyFeedback.FireUpdate(); + break; + case GlsOccupancySensorBase.InternalPhotoSensorValueFeedbackEventId: + InternalPhotoSensorValue.FireUpdate(); + break; + case GlsOccupancySensorBase.ExternalPhotoSensorValueFeedbackEventId: + ExternalPhotoSensorValue.FireUpdate(); + break; } - else if (args.EventId == GlsOccupancySensorBase.TimeoutFeedbackEventId) - CurrentTimeoutFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.TimeoutLocalFeedbackEventId) - LocalTimoutFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.GraceOccupancyDetectedFeedbackEventId) - GraceOccupancyDetectedFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.RawOccupancyFeedbackEventId) - RawOccupancyFeedback.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.InternalPhotoSensorValueFeedbackEventId) - InternalPhotoSensorValue.FireUpdate(); - else if (args.EventId == GlsOccupancySensorBase.ExternalPhotoSensorValueFeedbackEventId) - ExternalPhotoSensorValue.FireUpdate(); } public void SetTestMode(bool mode) @@ -373,27 +410,51 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy { LinkOccSensorToApi(this, trilist, joinStart, joinMapKey, bridge); } - } - public class GlsOccupancySensorBaseControllerFactory : EssentialsDeviceFactory - { - public GlsOccupancySensorBaseControllerFactory() + #region PreActivation + + private static GlsOirCCn GetGlsOirCCn(DeviceConfig dc) { - TypeNames = new List() { "glsoirccn" }; + 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 GlsOirCCn", parentKey); + return new GlsOirCCn(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 GlsOirCCn", parentKey); + return new GlsOirCCn(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; } + #endregion - public override EssentialsDevice BuildDevice(DeviceConfig dc) + public class GlsOccupancySensorBaseControllerFactory : EssentialsDeviceFactory { - Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device"); + public GlsOccupancySensorBaseControllerFactory() + { + TypeNames = new List() { "glsoirccn" }; + } - var key = dc.Key; - var name = dc.Name; - var comm = CommFactory.GetControlPropertiesConfig(dc); - GlsOccupancySensorBase occSensor = new GlsOirCCn(comm.CresnetIdInt, Global.ControlSystem); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device"); + + return new GlsOccupancySensorBaseController(dc.Key, GetGlsOirCCn, dc); + } - return new GlsOccupancySensorBaseController(key, name, occSensor); } } + + } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/GlsOdtOccupancySensorController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/GlsOdtOccupancySensorController.cs similarity index 63% rename from essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/GlsOdtOccupancySensorController.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/GlsOdtOccupancySensorController.cs index 26fec016..4900ca93 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/GlsOdtOccupancySensorController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/GlsOdtOccupancySensorController.cs @@ -11,7 +11,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Devices.Common.Occupancy +namespace PepperDash.Essentials.Core { [Description("Wrapper class for Dual Technology GLS Occupancy Sensors")] public class GlsOdtOccupancySensorController : GlsOccupancySensorBaseController @@ -35,26 +35,35 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy public BoolFeedback RawOccupancyUsFeedback { get; private set; } - public GlsOdtOccupancySensorController(string key, string name, GlsOdtCCn sensor) - : base(key, name, sensor) + public GlsOdtOccupancySensorController(string key, Func preActivationFunc, + DeviceConfig config) + : base(key, config.Name) { - OccSensor = sensor; + AddPreActivationAction(() => + { + OccSensor = preActivationFunc(config); - AndWhenVacatedFeedback = new BoolFeedback(() => OccSensor.AndWhenVacatedFeedback.BoolValue); + RegisterCrestronGenericBase(OccSensor); - OrWhenVacatedFeedback = new BoolFeedback(() => OccSensor.OrWhenVacatedFeedback.BoolValue); + RegisterGlsOdtSensorBaseController(OccSensor); - UltrasonicAEnabledFeedback = new BoolFeedback(() => OccSensor.UsAEnabledFeedback.BoolValue); + AndWhenVacatedFeedback = new BoolFeedback(() => OccSensor.AndWhenVacatedFeedback.BoolValue); - UltrasonicBEnabledFeedback = new BoolFeedback(() => OccSensor.UsBEnabledFeedback.BoolValue); + OrWhenVacatedFeedback = new BoolFeedback(() => OccSensor.OrWhenVacatedFeedback.BoolValue); - RawOccupancyPirFeedback = new BoolFeedback(() => OccSensor.RawOccupancyPirFeedback.BoolValue); + UltrasonicAEnabledFeedback = new BoolFeedback(() => OccSensor.UsAEnabledFeedback.BoolValue); - RawOccupancyUsFeedback = new BoolFeedback(() => OccSensor.RawOccupancyUsFeedback.BoolValue); + UltrasonicBEnabledFeedback = new BoolFeedback(() => OccSensor.UsBEnabledFeedback.BoolValue); - UltrasonicSensitivityInVacantStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInVacantStateFeedback.UShortValue); + RawOccupancyPirFeedback = new BoolFeedback(() => OccSensor.RawOccupancyPirFeedback.BoolValue); - UltrasonicSensitivityInOccupiedStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInOccupiedStateFeedback.UShortValue); + RawOccupancyUsFeedback = new BoolFeedback(() => OccSensor.RawOccupancyUsFeedback.BoolValue); + + UltrasonicSensitivityInVacantStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInVacantStateFeedback.UShortValue); + + UltrasonicSensitivityInOccupiedStateFeedback = new IntFeedback(() => OccSensor.UsSensitivityInOccupiedStateFeedback.UShortValue); + + }); } /// @@ -160,38 +169,51 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy { LinkOccSensorToApi(this, trilist, joinStart, joinMapKey, bridge); } - } - public class GlsOdtOccupancySensorControllerFactory : EssentialsDeviceFactory - { - public GlsOdtOccupancySensorControllerFactory() + #region PreActivation + + private static GlsOdtCCn GetGlsOdtCCn(DeviceConfig dc) { - TypeNames = new List() { "glsodtccn" }; - } + var control = CommFactory.GetControlPropertiesConfig(dc); + var cresnetId = control.CresnetIdInt; + var branchId = control.ControlPortNumber; + var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey; - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device"); - - var typeName = dc.Type.ToLower(); - var key = dc.Key; - var name = dc.Name; - var comm = CommFactory.GetControlPropertiesConfig(dc); - - var occSensor = new GlsOdtCCn(comm.CresnetIdInt, Global.ControlSystem); - - if (occSensor != null) + if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase)) { - return new GlsOdtOccupancySensorController(key, name, occSensor); + Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsOdtCCn", parentKey); + return new GlsOdtCCn(cresnetId, Global.ControlSystem); } - else + var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches; + + if (cresnetBridge != null) { - Debug.Console(0, "ERROR: Unable to create Occupancy Sensor Device. Key: '{0}'", key); - return null; + Debug.Console(0, "Device {0} is a valid cresnet master - creating new GlsOdtCCn", parentKey); + return new GlsOdtCCn(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + #endregion + + public class GlsOdtOccupancySensorControllerFactory : EssentialsDeviceFactory + { + public GlsOdtOccupancySensorControllerFactory() + { + TypeNames = new List() { "glsodtccn" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device"); + + return new GlsOdtOccupancySensorController(dc.Key, GetGlsOdtCCn, dc); + } + } } + + } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/IOccupancyStatusProviderAggregator.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs similarity index 95% rename from essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/IOccupancyStatusProviderAggregator.cs rename to essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs index 72f67f7d..c321dcad 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Occupancy/IOccupancyStatusProviderAggregator.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Occupancy/IOccupancyStatusProviderAggregator.cs @@ -5,9 +5,9 @@ using System.Text; using Crestron.SimplSharp; using PepperDash.Core; -using PepperDash.Essentials.Core; - -namespace PepperDash.Essentials.Devices.Common.Occupancy +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core { /// /// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs new file mode 100644 index 00000000..8dd30eff --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs @@ -0,0 +1,280 @@ +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.GeneralIO; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash_Essentials_Core.Bridges.JoinMaps; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.Gateways; +using Newtonsoft.Json; +using Crestron.SimplSharpPro.DeviceSupport; + + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; +using PepperDash_Essentials_Core; + +namespace PepperDash.Essentials.Core +{ + [Description("Wrapper class for GLS Cresnet Partition Sensor")] + public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice + { + private GlsPartCn _partitionSensor; + + public StringFeedback NameFeedback { get; private set; } + public BoolFeedback EnableFeedback { get; private set; } + public BoolFeedback PartitionSensedFeedback { get; private set; } + public BoolFeedback PartitionNotSensedFeedback { get; private set; } + public IntFeedback SensitivityFeedback { get; private set; } + + public bool InTestMode { get; private set; } + public bool TestEnableFeedback { get; private set; } + public bool TestPartitionSensedFeedback { get; private set; } + public int TestSensitivityFeedback { get; private set; } + + + public GlsPartitionSensorController(string key, Func preActivationFunc, DeviceConfig config) + : base(key, config.Name) + { + AddPreActivationAction(() => + { + _partitionSensor = preActivationFunc(config); + + RegisterCrestronGenericBase(_partitionSensor); + + NameFeedback = new StringFeedback(() => Name); + EnableFeedback = new BoolFeedback(() => _partitionSensor.EnableFeedback.BoolValue); + PartitionSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue); + PartitionNotSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionNotSensedFeedback.BoolValue); + SensitivityFeedback = new IntFeedback(() => _partitionSensor.SensitivityFeedback.UShortValue); + + if (_partitionSensor != null) _partitionSensor.BaseEvent += PartitionSensor_BaseEvent; + }); + } + + private void PartitionSensor_BaseEvent(GenericBase device, BaseEventArgs args) + { + Debug.Console(2, this, "EventId: {0}, Index: {1}", args.EventId, args.Index); + + switch (args.EventId) + { + case (GlsPartCn.EnableFeedbackEventId): + { + EnableFeedback.FireUpdate(); + break; + } + case (GlsPartCn.PartitionSensedFeedbackEventId): + { + PartitionSensedFeedback.FireUpdate(); + break; + } + case (GlsPartCn.PartitionNotSensedFeedbackEventId): + { + PartitionNotSensedFeedback.FireUpdate(); + break; + } + case (GlsPartCn.SensitivityFeedbackEventId): + { + SensitivityFeedback.FireUpdate(); + break; + } + default: + { + Debug.Console(2, this, "Unhandled args.EventId: {0}", args.EventId); + break; + } + } + } + + public void SetTestMode(bool mode) + { + InTestMode = mode; + Debug.Console(1, this, "InTestMode: {0}", InTestMode.ToString()); + } + + public void SetTestEnableState(bool state) + { + if (InTestMode) + { + TestEnableFeedback = state; + Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString()); + return; + } + + Debug.Console(1, this, "InTestMode: {0}, unable to set enable state: {1}", InTestMode.ToString(), state.ToString()); + } + + public void SetTestPartitionSensedState(bool state) + { + if (InTestMode) + { + TestPartitionSensedFeedback = state; + Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString()); + return; + } + + Debug.Console(1, this, "InTestMode: {0}, unable to set partition state: {1}", InTestMode.ToString(), state.ToString()); + } + + public void SetTestSensitivityValue(int value) + { + if (InTestMode) + { + TestSensitivityFeedback = value; + Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback); + return; + } + + Debug.Console(1, this, "InTestMode: {0}, unable to set sensitivity value: {1}", InTestMode.ToString(), value); + } + + public void SetEnableState(bool state) + { + if (_partitionSensor == null) + return; + + _partitionSensor.Enable.BoolValue = state; + } + + public void IncreaseSensitivity() + { + if (_partitionSensor == null) + return; + + _partitionSensor.IncreaseSensitivity(); + } + + public void DecreaseSensitivity() + { + if (_partitionSensor == null) + return; + + _partitionSensor.DecreaseSensitivity(); + } + + public void SetSensitivity(ushort value) + { + if (_partitionSensor == null) + return; + + _partitionSensor.Sensitivity.UShortValue = value; + } + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new GlsPartitionSensorJoinMap(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 'type': 'EiscApiAdvanced' to get all join map features for this device"); + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name); + + // link input from simpl + trilist.SetSigTrueAction(joinMap.Enable.JoinNumber, () => SetEnableState(true)); + trilist.SetSigFalseAction(joinMap.Enable.JoinNumber, () => SetEnableState(false)); + trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity); + trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity); + trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity); + + // link output to simpl + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]); + PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]); + PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]); + SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]); + + FeedbacksFireUpdates(); + + // update when device is online + _partitionSensor.OnlineStatusChange += (o, a) => + { + if (a.DeviceOnLine) + { + FeedbacksFireUpdates(); + } + }; + + // update when trilist is online + trilist.OnlineStatusChange += (o, a) => + { + if (a.DeviceOnLine) + { + FeedbacksFireUpdates(); + } + }; + } + + private void FeedbacksFireUpdates() + { + IsOnline.FireUpdate(); + NameFeedback.FireUpdate(); + EnableFeedback.FireUpdate(); + PartitionSensedFeedback.FireUpdate(); + PartitionNotSensedFeedback.FireUpdate(); + SensitivityFeedback.FireUpdate(); + } + + #region PreActivation + + private static GlsPartCn GetGlsPartCnDevice(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 GlsPartCn", parentKey); + return new GlsPartCn(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 GlsPartCn", parentKey); + return new GlsPartCn(cresnetId, cresnetBridge.CresnetBranches[branchId]); + } + Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey); + return null; + } + #endregion + + + public class GlsPartitionSensorControllerFactory : EssentialsDeviceFactory + { + public GlsPartitionSensorControllerFactory() + { + TypeNames = new List() { "glspartcn" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); + + return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc); + } + } + + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 1177db17..f80d77b6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -137,6 +137,7 @@ + @@ -171,6 +172,8 @@ + + @@ -192,6 +195,7 @@ + @@ -213,6 +217,11 @@ + + + + + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs index ff1ef06b..311df7f1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs @@ -21,30 +21,70 @@ namespace PepperDash.Essentials.Core [Description("Wrapper class for all HR-Series remotes")] public class Hrxx0WirelessRemoteController : EssentialsBridgeableDevice, IHasFeedback { + private CenRfgwController _gateway; + private Hr1x0WirelessRemoteBase _remote; public FeedbackCollection Feedbacks { get; set; } public CrestronCollection - void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) - { - var output = args.Number; - - switch (args.EventId) - { - case DMOutputEventIds.VolumeEventId: - { - if (VolumeControls.ContainsKey(output)) - { - VolumeControls[args.Number].VolumeEventFromChassis(); - } - - break; - } - case DMOutputEventIds.EndpointOnlineEventId: - { - Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. State: {1}", args.Number, - Chassis.Outputs[output].EndpointOnlineFeedback); - OutputEndpointOnlineFeedbacks[output].FireUpdate(); - break; - } - case DMOutputEventIds.OnlineFeedbackEventId: - { - Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", args.Number, - Chassis.Outputs[output].EndpointOnlineFeedback); - OutputEndpointOnlineFeedbacks[output].FireUpdate(); - break; - } - case DMOutputEventIds.VideoOutEventId: - { - if (Chassis.Outputs[output].VideoOutFeedback != null) - Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output); - - if (VideoOutputFeedbacks.ContainsKey(output)) - VideoOutputFeedbacks[output].FireUpdate(); - - if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) - OutputVideoRouteNameFeedbacks[output].FireUpdate(); - - break; - } - case DMOutputEventIds.AudioOutEventId: - { - if (Chassis.Outputs[output].AudioOutFeedback != null) - Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].AudioOutFeedback.Number, output); - - if (AudioOutputFeedbacks.ContainsKey(output)) - AudioOutputFeedbacks[output].FireUpdate(); - - if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) - OutputAudioRouteNameFeedbacks[output].FireUpdate(); - - break; - } - case DMOutputEventIds.OutputNameEventId: - { - Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); - OutputNameFeedbacks[output].FireUpdate(); - break; - } - case DMOutputEventIds.UsbRoutedToEventId: - { - Debug.Console(2, this, "DM Output {0} UsbRoutedToEventId", args.Number); - UsbOutputRoutedToFeebacks[args.Number].FireUpdate(); - break; - } - case DMOutputEventIds.DisabledByHdcpEventId: - { - Debug.Console(2, this, "DM Output {0} DisabledByHdcpEventId", args.Number); - OutputDisabledByHdcpFeedbacks[args.Number].FireUpdate(); - break; - } - default: - { - Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", args.Number, args.EventId); - break; - } - } - } - - /// - /// - /// - /// - void StartOffTimer(PortNumberType pnt) - { - if (RouteOffTimers.ContainsKey(pnt)) - return; - RouteOffTimers[pnt] = new CTimer(o => { ExecuteSwitch(0, pnt.Number, pnt.Type); }, RouteOffTime); - } - - // Send out sigs when coming online - void IsOnline_OutputChange(object sender, EventArgs e) - { - if (IsOnline.BoolValue) - { - (Chassis as DmMDMnxn).EnableAudioBreakaway.BoolValue = true; - (Chassis as DmMDMnxn).EnableUSBBreakaway.BoolValue = true; - - - EnableAudioBreakawayFeedback.FireUpdate(); - EnableUsbBreakawayFeedback.FireUpdate(); - - if (InputNames != null) - foreach (var kvp in InputNames) - Chassis.Inputs[kvp.Key].Name.StringValue = kvp.Value; - if (OutputNames != null) - foreach (var kvp in OutputNames) - Chassis.Outputs[kvp.Key].Name.StringValue = kvp.Value; - } - } - - #region IRouting Members - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) - { - Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType); - - var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail - var output = Convert.ToUInt32(outputSelector); - - var chassisSize = (uint) Chassis.NumberOfInputs; //need this to determine USB routing values 8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 - //16x16 1-16 is inputs 1-16, 17-32 is outputs 1-16 - //32x32 1-32 is inputs 1-32, 33-64 is outputs 1-32 - - // Check to see if there's an off timer waiting on this and if so, cancel - var key = new PortNumberType(output, sigType); - if (input == 0) - { - StartOffTimer(key); - } - else - { - if (RouteOffTimers.ContainsKey(key)) - { - Debug.Console(2, this, "{0} cancelling route off due to new source", output); - RouteOffTimers[key].Stop(); - RouteOffTimers.Remove(key); - } - } - - var inCard = input == 0 ? null : Chassis.Inputs[input]; - var outCard = input == 0 ? null : Chassis.Outputs[output]; - - // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES - if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) - { - Chassis.VideoEnter.BoolValue = true; - Chassis.Outputs[output].VideoOut = inCard; - } - - if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) - { - (Chassis as DmMDMnxn).AudioEnter.BoolValue = true; - Chassis.Outputs[output].AudioOut = inCard; - } - - if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput) - { - //using base here because USB can be routed between 2 output cards or 2 input cards - DMInputOutputBase dmCard; - - Debug.Console(2, this, "Executing USB Output switch.\r\n in:{0} output: {1}", input, output); - - if (input > chassisSize) - { - //wanting to route an output to an output. Subtract chassis size and get output, unless it's 8x8 - //need this to determine USB routing values - //8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 - //16x16 1-16 is inputs 1-16, 17-32 is outputs 1-16 - //32x32 1-32 is inputs 1-32, 33-64 is outputs 1-32 - uint outputIndex; - - if (chassisSize == 8) - { - outputIndex = input - 16; - } - else - { - outputIndex = input - chassisSize; - } - dmCard = Chassis.Outputs[outputIndex]; - } - else - { - dmCard = inCard; - } - Chassis.USBEnter.BoolValue = true; - if (Chassis.Outputs[output] != null) - { - Debug.Console(2, this, "Routing USB for input {0} to {1}", Chassis.Outputs[input], dmCard); - Chassis.Outputs[output].USBRoutedTo = dmCard; - } - } - - if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) - { - //using base here because USB can be routed between 2 output cards or 2 input cards - DMInputOutputBase dmCard; - - Debug.Console(2, this, "Executing USB Input switch.\r\n in:{0} output: {1}", input, output); - - if (output > chassisSize) - { - //wanting to route an input to an output. Subtract chassis size and get output, unless it's 8x8 - //need this to determine USB routing values - //8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 - //16x16 1-16 is inputs 1-16, 17-32 is outputs 1-16 - //32x32 1-32 is inputs 1-32, 33-64 is outputs 1-32 - uint outputIndex; - - if (chassisSize == 8) - { - outputIndex = input - 16; - } - else - { - outputIndex = input - chassisSize; - } - dmCard = Chassis.Outputs[outputIndex]; - } - else - { - dmCard = Chassis.Inputs[input]; - } - - - - Chassis.USBEnter.BoolValue = true; - - if (Chassis.Inputs[output] == null) - { - return; - } - Debug.Console(2, this, "Routing USB for input {0} to {1}", Chassis.Inputs[output], dmCard); - Chassis.Inputs[output].USBRoutedTo = dmCard; - } - } - #endregion - - #region IRoutingNumeric Members - - public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) - { - ExecuteSwitch(inputSelector, outputSelector, sigType); - } - - #endregion - - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = GetJoinMap(joinStart, joinMapKey, bridge); - - Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - - LinkChassisToApi(trilist, joinMap); - - // Link up inputs & outputs - for (uint i = 1; i <= Chassis.NumberOfOutputs; i++) - { - var ioSlot = i; - var ioSlotJoin = ioSlot - 1; - - LinkRoutingJoinsToApi(trilist, joinMap, ioSlotJoin, ioSlot); - - if (TxDictionary.ContainsKey(ioSlot)) - { - LinkTxToApi(trilist, ioSlot, joinMap, ioSlotJoin); - } - else - { - LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin); - } - - if (RxDictionary.ContainsKey(ioSlot)) - { - LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin); - } - } - } - - private void LinkHdmiInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) - { - VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - - var inputPort = InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)]; - if (inputPort == null) - { - return; - } - - Debug.Console(1, "Port value for input card {0} is set", ioSlot); - var port = inputPort.Port; - - if (port == null) - { - return; - } - if (!(port is HdmiInputWithCEC)) - { - Debug.Console(0, this, "HDMI Input port on card {0} does not support HDCP settings.", ioSlot); - return; - } - - Debug.Console(1, "Port is HdmiInputWithCec"); - - var hdmiInPortWCec = port as HdmiInputWithCEC; - - - SetHdcpStateAction(true, hdmiInPortWCec, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); - - - InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - - if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = - (ushort)InputCardHdcpCapabilityTypes[ioSlot]; - } - else - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; - } - } - - private void LinkRxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) - { - Debug.Console(2, "Creating Rx Feedbacks {0}", ioSlot); - var rxKey = RxDictionary[ioSlot]; - var rxDevice = DeviceManager.GetDeviceForKey(rxKey) as DmRmcControllerBase; - var hdBaseTDevice = DeviceManager.GetDeviceForKey(rxKey) as DmHdBaseTControllerBase; - if (Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps - || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps - || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps || hdBaseTDevice != null) - { - OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); - } - else if (rxDevice != null) - { - rxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); - } - } - - private void LinkTxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) - { - Debug.Console(1, "Setting up actions and feedbacks on input card {0}", ioSlot); - VideoInputSyncFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - - Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot); - var txKey = TxDictionary[ioSlot]; - var txDevice = DeviceManager.GetDeviceForKey(txKey) as BasicDmTxControllerBase; - - if (txDevice == null) - { - return; - } - - LinkTxOnlineFeedbackToApi(trilist, ioSlot, joinMap, ioSlotJoin, txDevice); - - LinkBasicTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); - - LinkAdvancedTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); - } - - private void LinkBasicTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlot, - uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) - { - var advTx = basicTransmitter as DmTxControllerBase; - - if (advTx != null) - { - return; - } - var inputPort = InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)]; - - if (inputPort == null) - { - return; - } - var port = inputPort.Port; - - if (!(port is DMInputPortWithCec)) - { - Debug.Console(0, this, "DM Input port on card {0} does not support HDCP settings.", ioSlot); - return; - } - Debug.Console(1, "Port is DMInputPortWithCec"); - - var dmInPortWCec = port as DMInputPortWithCec; - - bool supportsHdcp2; - - //added in case the InputSlotSupportsHdcp2 section isn't included in the config, or this slot is left out. - //if the key isn't in the dictionary, supportsHdcp2 will be false - - if(!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, - "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", - ioSlot); - } - - SetHdcpStateAction(supportsHdcp2, dmInPortWCec, - joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); - - InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - - if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = - (ushort) InputCardHdcpCapabilityTypes[ioSlot]; - } - else - { - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; - } - } - - private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, - uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) - { - var transmitter = basicTransmitter as DmTxControllerBase; - if (transmitter == null) return; - - trilist.BooleanInput[joinMap.TxAdvancedIsPresent.JoinNumber + ioSlotJoin].BoolValue = true; - - transmitter.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); - - var txRoutingInputs = transmitter as IRoutingInputs; - - if (txRoutingInputs == null) return; - - var inputPorts = txRoutingInputs.InputPorts.Where((p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); - - if (inputPorts.Count == 0) - { - Debug.Console(1, this, "No HDCP-capable input ports found on transmitter for slot {0}", ioSlot); - return; - } - - bool supportsHdcp2; - - if (!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, - "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", - ioSlot); - } - - SetHdcpStateAction(supportsHdcp2, inputPorts, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); - - if (transmitter.HdcpStateFeedback != null) - { - transmitter.HdcpStateFeedback.LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - } - else - { - Debug.Console(2, this, "Transmitter Hdcp Feedback null. Linking to card's feedback"); - InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( - trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); - } - - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = - (ushort) transmitter.HdcpSupportCapability; - } - - private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, - uint ioSlotJoin, BasicDmTxControllerBase txDevice) - { - var advancedTxDevice = txDevice as DmTxControllerBase; - - if ((Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps - || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps - || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps) || - advancedTxDevice == null) - { - Debug.Console(2, "Linking Tx Online Feedback from Input Card {0}", ioSlot); - InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); - return; - } - - Debug.Console(2, "Linking Tx Online Feedback from Advanced Transmitter at input {0}", ioSlot); - - advancedTxDevice.IsOnline.LinkInputSig( - trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); - } - - private void LinkRoutingJoinsToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlotJoin, - uint ioSlot) - { - // Routing Control - trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, - o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)); - trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, - o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)); - trilist.SetUShortSigAction(joinMap.OutputUsb.JoinNumber + ioSlotJoin, - o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.UsbOutput)); - trilist.SetUShortSigAction(joinMap.InputUsb.JoinNumber + ioSlotJoin, - o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.UsbInput)); - - //Routing Feedbacks - VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]); - AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]); - UsbOutputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputUsb.JoinNumber + ioSlotJoin]); - UsbInputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.InputUsb.JoinNumber + ioSlotJoin]); - - OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); - InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); - OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig( - trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]); - OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig( - trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]); - - OutputDisabledByHdcpFeedbacks[ioSlot].LinkInputSig( - trilist.BooleanInput[joinMap.OutputDisabledByHdcp.JoinNumber + ioSlotJoin]); - } - - private void LinkChassisToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap) - { - var chassis = Chassis as DmMDMnxn; - - IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - - trilist.SetUShortSigAction(joinMap.SystemId.JoinNumber, o => - { - if (chassis != null) - { - chassis.SystemId.UShortValue = o; - } - }); - - trilist.SetSigTrueAction(joinMap.SystemId.JoinNumber, () => - { - if (chassis != null) - { - chassis.ApplySystemId(); - } - }); - - SystemIdFeebdack.LinkInputSig(trilist.UShortInput[joinMap.SystemId.JoinNumber]); - SystemIdBusyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemId.JoinNumber]); - - EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]); - EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]); - - trilist.OnlineStatusChange += (o, a) => - { - if (!a.DeviceOnLine) - { - return; - } - - EnableAudioBreakawayFeedback.FireUpdate(); - EnableUsbBreakawayFeedback.FireUpdate(); - SystemIdBusyFeedback.FireUpdate(); - SystemIdFeebdack.FireUpdate(); - }; - } - - private DmChassisControllerJoinMap GetJoinMap(uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new DmChassisControllerJoinMap(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."); - } - return joinMap; - } - - private void SetHdcpStateAction(bool supportsHdcp2, HdmiInputWithCEC port, uint join, BasicTriList trilist) - { - if (!supportsHdcp2) - { - trilist.SetUShortSigAction(join, - s => - { - if (s == 0) - { - port.HdcpSupportOff(); - } - else if (s > 0) - { - port.HdcpSupportOn(); - } - }); - } - else - { - trilist.SetUShortSigAction(join, - u => - { - port.HdcpReceiveCapability = (eHdcpCapabilityType)u; - }); - } - } - - private void SetHdcpStateAction(bool supportsHdcp2, EndpointHdmiInput port, uint join, BasicTriList trilist) - { - if (!supportsHdcp2) - { - trilist.SetUShortSigAction(join, - s => - { - if (s == 0) - { - port.HdcpSupportOff(); - } - else if (s > 0) - { - port.HdcpSupportOn(); - } - }); - } - else - { - trilist.SetUShortSigAction(join, - u => - { - port.HdcpCapability = (eHdcpCapabilityType)u; - }); - } - } - - private void SetHdcpStateAction(bool supportsHdcp2, List ports, uint join, - BasicTriList triList) - { - if (!supportsHdcp2) - { - triList.SetUShortSigAction(join, a => - { - foreach (var tempPort in ports.Select(port => port.Port).OfType()) - { - if (a == 0) - { - tempPort.HdcpSupportOff(); - } - else if (a > 0) - { - tempPort.HdcpSupportOn(); - } - } - }); - } - else - { - triList.SetUShortSigAction(join, a => - { - foreach (var tempPort in ports.Select(port => port.Port).OfType()) - { - tempPort.HdcpCapability = (eHdcpCapabilityType) a; - } - }); - } - } - - private void SetHdcpStateAction(bool supportsHdcp2, DMInputPortWithCec port, uint join, BasicTriList trilist) - { - if (!supportsHdcp2) - { - trilist.SetUShortSigAction(join, - s => - { - if (s == 0) - { - port.HdcpSupportOff(); - } - else if (s > 0) - { - port.HdcpSupportOn(); - } - }); - } - else - { - trilist.SetUShortSigAction(join, - u => - { - port.HdcpReceiveCapability = (eHdcpCapabilityType)u; - }); - } - } - } - - public struct PortNumberType - { - public uint Number { get; private set; } - public eRoutingSignalType Type { get; private set; } - - public PortNumberType(uint number, eRoutingSignalType type) - : this() - { - Number = number; - Type = type; - } - } - - public class DmChassisControllerFactory : EssentialsDeviceFactory - { - public DmChassisControllerFactory() - { - TypeNames = new List() { "dmmd8x8", "dmmd8x8rps", "dmmd8x8cpu3", "dmmd8x8cpu3rps", - "dmmd16x16", "dmmd16x16rps", "dmmd16x16cpu3", "dmmd16x16cpu3rps", - "dmmd32x32", "dmmd32x32rps", "dmmd32x32cpu3", "dmmd32x32cpu3rps", - "dmmd64x64", "dmmd128x128" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - var type = dc.Type.ToLower(); - - Debug.Console(1, "Factory Attempting to create new DmChassisController Device"); - - if (type.StartsWith("dmmd8x") || type.StartsWith("dmmd16x") || type.StartsWith("dmmd32x")) - { - - var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmChassisController. - GetDmChassisController(dc.Key, dc.Name, type, props); - } - else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x")) - { - var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmBladeChassisController. - GetDmChassisController(dc.Key, dc.Name, type, props); - } - - return null; - } - } - -} - +using System; +using System.Collections.Generic; +using System.Linq; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Cards; +using Crestron.SimplSharpPro.DM.Endpoints; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.DM.Config; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.DM +{ + /// + /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions + /// + /// + [Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")] + public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumeric + { + public DMChassisPropertiesConfig PropertiesConfig { get; set; } + + public Switch Chassis { get; private set; } + + // Feedbacks for EssentialDM + public Dictionary VideoOutputFeedbacks { get; private set; } + public Dictionary AudioOutputFeedbacks { get; private set; } + public Dictionary VideoInputSyncFeedbacks { get; private set; } + public Dictionary InputEndpointOnlineFeedbacks { get; private set; } + public Dictionary OutputEndpointOnlineFeedbacks { get; private set; } + public Dictionary InputNameFeedbacks { get; private set; } + public Dictionary OutputNameFeedbacks { get; private set; } + public Dictionary OutputVideoRouteNameFeedbacks { get; private set; } + public Dictionary OutputAudioRouteNameFeedbacks { get; private set; } + public Dictionary UsbOutputRoutedToFeebacks { get; private set; } + public Dictionary UsbInputRoutedToFeebacks { get; private set; } + public Dictionary OutputDisabledByHdcpFeedbacks { get; private set; } + + public IntFeedback SystemIdFeebdack { get; private set; } + public BoolFeedback SystemIdBusyFeedback { get; private set; } + public BoolFeedback EnableAudioBreakawayFeedback { get; private set; } + public BoolFeedback EnableUsbBreakawayFeedback { get; private set; } + + public Dictionary InputCardHdcpStateFeedbacks { get; private set; } + + public Dictionary InputCardHdcpCapabilityTypes { get; private set; } + + // Need a couple Lists of generic Backplane ports + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public Dictionary TxDictionary { get; set; } + public Dictionary RxDictionary { get; set; } + + //public Dictionary InputCards { get; private set; } + //public Dictionary OutputCards { get; private set; } + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + public Dictionary VolumeControls { get; private set; } + + public const int RouteOffTime = 500; + Dictionary RouteOffTimers = new Dictionary(); + + /// + /// Text that represents when an output has no source routed to it + /// + public string NoRouteText = ""; + + /// + /// Factory method to create a new chassis controller from config data. Limited to 8x8 right now + /// + public static DmChassisController GetDmChassisController(string key, string name, + string type, DMChassisPropertiesConfig properties) + { + try + { + type = type.ToLower(); + uint ipid = properties.Control.IpIdInt; + + DmMDMnxn chassis = null; + switch (type) { + case "dmmd8x8": + chassis = new DmMd8x8(ipid, Global.ControlSystem); + break; + case "dmmd8x8rps": + chassis = new DmMd8x8rps(ipid, Global.ControlSystem); + break; + case "dmmd8x8cpu3": + chassis = new DmMd8x8Cpu3(ipid, Global.ControlSystem); + break; + case "dmmd8x8cpu3rps": + chassis = new DmMd8x8Cpu3rps(ipid, Global.ControlSystem); + break; + case "dmmd16x16": + chassis = new DmMd16x16(ipid, Global.ControlSystem); + break; + case "dmmd16x16rps": + chassis = new DmMd16x16rps(ipid, Global.ControlSystem); + break; + case "dmmd16x16cpu3": + chassis = new DmMd16x16Cpu3(ipid, Global.ControlSystem); + break; + case "dmmd16x16cpu3rps": + chassis = new DmMd16x16Cpu3rps(ipid, Global.ControlSystem); + break; + case "dmmd32x32": + chassis = new DmMd32x32(ipid, Global.ControlSystem); + break; + case "dmmd32x32rps": + chassis = new DmMd32x32rps(ipid, Global.ControlSystem); + break; + case "dmmd32x32cpu3": + chassis = new DmMd32x32Cpu3(ipid, Global.ControlSystem); + break; + case "dmmd32x32cpu3rps": + chassis = new DmMd32x32Cpu3rps(ipid, Global.ControlSystem); + break; + } + + if (chassis == null) + return null; + + var controller = new DmChassisController(key, name, chassis); + + // add the cards and port names + foreach (var kvp in properties.InputSlots) + controller.AddInputCard(kvp.Value, kvp.Key); + + foreach (var kvp in properties.OutputSlots) + controller.AddOutputCard(kvp.Value, kvp.Key); + + foreach (var kvp in properties.VolumeControls) + { + // get the card + // check it for an audio-compatible type + // make a something-something that will make it work + // retire to mountain village + var outNum = kvp.Key; + var card = controller.Chassis.Outputs[outNum].Card; + Audio.Output audio = null; + if (card is DmcHdo) + audio = (card as DmcHdo).Audio; + else if (card is Dmc4kHdo) + audio = (card as Dmc4kHdo).Audio; + if (audio == null) + continue; + + // wire up the audio to something here... + controller.AddVolumeControl(outNum, audio); + } + + controller.InputNames = properties.InputNames; + controller.OutputNames = properties.OutputNames; + + if (!string.IsNullOrEmpty(properties.NoRouteText)) + { + controller.NoRouteText = properties.NoRouteText; + Debug.Console(1, controller, "Setting No Route Text value to: {0}", controller.NoRouteText); + } + else + { + Debug.Console(1, controller, "NoRouteText not specified. Defaulting to blank string.", controller.NoRouteText); + } + + controller.PropertiesConfig = properties; + return controller; + } + catch (Exception e) + { + Debug.Console(0, "Error creating DM chassis:\r{0}", e); + } + + return null; + } + + /// + /// + /// + /// + /// + /// + public DmChassisController(string key, string name, DmMDMnxn chassis) + : base(key, name, chassis) + { + Chassis = chassis; + InputPorts = new RoutingPortCollection(); + OutputPorts = new RoutingPortCollection(); + VolumeControls = new Dictionary(); + TxDictionary = new Dictionary(); + RxDictionary = new Dictionary(); + IsOnline.OutputChange += new EventHandler(IsOnline_OutputChange); + Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange); + Chassis.DMSystemChange += new DMSystemEventHandler(Chassis_DMSystemChange); + Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange); + VideoOutputFeedbacks = new Dictionary(); + AudioOutputFeedbacks = new Dictionary(); + UsbOutputRoutedToFeebacks = new Dictionary(); + UsbInputRoutedToFeebacks = new Dictionary(); + OutputDisabledByHdcpFeedbacks = new Dictionary(); + VideoInputSyncFeedbacks = new Dictionary(); + InputNameFeedbacks = new Dictionary(); + OutputNameFeedbacks = new Dictionary(); + OutputVideoRouteNameFeedbacks = new Dictionary(); + OutputAudioRouteNameFeedbacks = new Dictionary(); + InputEndpointOnlineFeedbacks = new Dictionary(); + OutputEndpointOnlineFeedbacks = new Dictionary(); + + SystemIdFeebdack = new IntFeedback(() => { return (Chassis as DmMDMnxn).SystemIdFeedback.UShortValue; }); + SystemIdBusyFeedback = new BoolFeedback(() => { return (Chassis as DmMDMnxn).SystemIdBusy.BoolValue; }); + EnableAudioBreakawayFeedback = + new BoolFeedback(() => (Chassis as DmMDMnxn).EnableAudioBreakawayFeedback.BoolValue); + EnableUsbBreakawayFeedback = + new BoolFeedback(() => (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue); + + InputCardHdcpStateFeedbacks = new Dictionary(); + InputCardHdcpCapabilityTypes = new Dictionary(); + + for (uint x = 1; x <= Chassis.NumberOfOutputs; x++) + { + var tempX = x; + + if (Chassis.Outputs[tempX] != null) + { + VideoOutputFeedbacks[tempX] = new IntFeedback(() => { + if (Chassis.Outputs[tempX].VideoOutFeedback != null) + return (ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number; + + return 0; + }); + AudioOutputFeedbacks[tempX] = new IntFeedback(() => { + if (Chassis.Outputs[tempX].AudioOutFeedback != null) + return (ushort)Chassis.Outputs[tempX].AudioOutFeedback.Number; + + return 0; + }); + UsbOutputRoutedToFeebacks[tempX] = new IntFeedback(() => { + if (Chassis.Outputs[tempX].USBRoutedToFeedback != null) + return (ushort)Chassis.Outputs[tempX].USBRoutedToFeedback.Number; + + return 0; + }); + + OutputNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Outputs[tempX].NameFeedback != null) + return Chassis.Outputs[tempX].NameFeedback.StringValue; + + return ""; + }); + OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Outputs[tempX].VideoOutFeedback != null) + return Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue; + + return NoRouteText; + }); + OutputAudioRouteNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Outputs[tempX].AudioOutFeedback != null) + return Chassis.Outputs[tempX].AudioOutFeedback.NameFeedback.StringValue; + + return NoRouteText; + }); + OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => Chassis.Outputs[tempX].EndpointOnlineFeedback); + + OutputDisabledByHdcpFeedbacks[tempX] = new BoolFeedback(() => { + var output = Chassis.Outputs[tempX]; + + var hdmiTxOutput = output as Card.HdmiTx; + if (hdmiTxOutput != null) + return hdmiTxOutput.HdmiOutput.DisabledByHdcp.BoolValue; + + var dmHdmiOutput = output as Card.DmHdmiOutput; + if (dmHdmiOutput != null) + return dmHdmiOutput.DisabledByHdcpFeedback.BoolValue; + + var dmsDmOutAdvanced = output as Card.DmsDmOutAdvanced; + if (dmsDmOutAdvanced != null) + return dmsDmOutAdvanced.DisabledByHdcpFeedback.BoolValue; + + var dmps3HdmiAudioOutput = output as Card.Dmps3HdmiAudioOutput; + if (dmps3HdmiAudioOutput != null) + return dmps3HdmiAudioOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + var dmps3HdmiOutput = output as Card.Dmps3HdmiOutput; + if (dmps3HdmiOutput != null) + return dmps3HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + var dmps3HdmiOutputBackend = output as Card.Dmps3HdmiOutputBackend; + if (dmps3HdmiOutputBackend != null) + return dmps3HdmiOutputBackend.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + // var hdRx4kX10HdmiOutput = output as HdRx4kX10HdmiOutput; + // if (hdRx4kX10HdmiOutput != null) + // return hdRx4kX10HdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + // var hdMdNxMHdmiOutput = output as HdMdNxMHdmiOutput; + // if (hdMdNxMHdmiOutput != null) + // return hdMdNxMHdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue; + + return false; + }); + } + + if (Chassis.Inputs[tempX] != null) + { + UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() => { + if (Chassis.Inputs[tempX].USBRoutedToFeedback != null) + return (ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number; + + return 0; + }); + VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => { + if (Chassis.Inputs[tempX].VideoDetectedFeedback != null) + return Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue; + + return false; + }); + InputNameFeedbacks[tempX] = new StringFeedback(() => { + if (Chassis.Inputs[tempX].NameFeedback != null) + return Chassis.Inputs[tempX].NameFeedback.StringValue; + + return ""; + }); + + InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { return Chassis.Inputs[tempX].EndpointOnlineFeedback; }); + + InputCardHdcpStateFeedbacks[tempX] = new IntFeedback(() => { + var inputCard = Chassis.Inputs[tempX]; + + if (inputCard.Card is DmcHd) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + + if ((inputCard.Card as DmcHd).HdmiInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + + if (inputCard.Card is DmcHdDsp) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + + if ((inputCard.Card as DmcHdDsp).HdmiInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + if (inputCard.Card is Dmc4kHdBase) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; + return (int)(inputCard.Card as Dmc4kHdBase).HdmiInput.HdcpReceiveCapability; + } + if (inputCard.Card is Dmc4kCBase) + { + if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + return (int)(inputCard.Card as Dmc4kCBase).DmInput.HdcpReceiveCapability; + } + + if ((inputCard.Card as Dmc4kCBase).DmInput.HdcpSupportOnFeedback.BoolValue) + return 1; + return 0; + } + if (inputCard.Card is Dmc4kCDspBase) + { + if (PropertiesConfig.InputSlotSupportsHdcp2[tempX]) + { + InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.HdcpAutoSupport; + return (int)(inputCard.Card as Dmc4kCDspBase).DmInput.HdcpReceiveCapability; + } + + if ((inputCard.Card as Dmc4kCDspBase).DmInput.HdcpSupportOnFeedback.BoolValue) + return 1; + + return 0; + } + return 0; + }); + } + } + } + + private void ChassisOnBaseEvent(GenericBase device, BaseEventArgs args) + { + + } + + /// + /// + /// + /// + /// + public void AddInputCard(string type, uint number) + { + Debug.Console(2, this, "Adding input card '{0}', slot {1}", type, number); + + type = type.ToLower(); + + if (type == "dmchd") + { + var inputCard = new DmcHd(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); + } + else if (type == "dmchddsp") + { + var inputCard = new DmcHdDsp(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); + } + else if (type == "dmc4khd") + { + var inputCard = new Dmc4kHd(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); + } + else if (type == "dmc4khddsp") + { + var inputCard = new Dmc4kHdDsp(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); + } + else if (type == "dmc4kzhd") + { + var inputCard = new Dmc4kzHd(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); + } + else if (type == "dmc4kzhddsp") + { + var inputCard = new Dmc4kzHdDsp(number, this.Chassis); + var cecPort = inputCard.HdmiInput as ICec; + AddHdmiInCardPorts(number, cecPort); + } + else if (type == "dmcc") + { + var inputCard = new DmcC(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); + } + else if (type == "dmccdsp") + { + var inputCard = new DmcCDsp(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); + } + else if (type == "dmc4kc") + { + var inputCard = new Dmc4kC(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); + } + else if (type == "dmc4kcdsp") + { + var inputCard = new Dmc4kCDsp(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); + } + else if (type == "dmc4kzc") + { + var inputCard = new Dmc4kzC(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); + } + else if (type == "dmc4kzcdsp") + { + var inputCard = new Dmc4kzCDsp(number, this.Chassis); + var cecPort = inputCard.DmInput as ICec; + AddDmInCardPorts(number, cecPort); + } + else if (type == "dmccat") + { + new DmcCat(number, this.Chassis); + AddDmInCardPorts(number); + } + else if (type == "dmccatdsp") + { + new DmcCatDsp(number, this.Chassis); + AddDmInCardPorts(number); + } + else if (type == "dmcs") + { + new DmcS(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); + AddInCardHdmiAndAudioLoopPorts(number); + } + else if (type == "dmcsdsp") + { + new DmcSDsp(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); + AddInCardHdmiAndAudioLoopPorts(number); + } + else if (type == "dmcs2") + { + new DmcS2(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); + AddInCardHdmiAndAudioLoopPorts(number); + } + else if (type == "dmcs2dsp") + { + new DmcS2Dsp(number, Chassis); + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); + AddInCardHdmiAndAudioLoopPorts(number); + } + else if (type == "dmcsdi") + { + new DmcSdi(number, Chassis); + AddInputPortWithDebug(number, "sdiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Sdi); + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "sdiOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Sdi, null); + AddInCardHdmiAndAudioLoopPorts(number); + } + else if (type == "dmcdvi") + { + new DmcDvi(number, Chassis); + AddInputPortWithDebug(number, "dviIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Dvi); + AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); + AddInCardHdmiLoopPort(number); + } + else if (type == "dmcvga") + { + new DmcVga(number, Chassis); + AddInputPortWithDebug(number, "vgaIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Vga); + AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); + AddInCardHdmiLoopPort(number); + } + else if (type == "dmcvidbnc") + { + new DmcVidBnc(number, Chassis); + AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); + AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); + AddInCardHdmiLoopPort(number); + } + else if (type == "dmcvidrcaa") + { + new DmcVidRcaA(number, Chassis); + AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); + AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio); + AddInCardHdmiLoopPort(number); + } + else if (type == "dmcvidrcad") + { + new DmcVidRcaD(number, Chassis); + AddInputPortWithDebug(number, "componentIn", eRoutingSignalType.Video, eRoutingPortConnectionType.Component); + AddInputPortWithDebug(number, "audioIn", eRoutingSignalType.Audio, eRoutingPortConnectionType.DigitalAudio); + AddInCardHdmiLoopPort(number); + } + else if (type == "dmcvid4") + { + new DmcVid4(number, Chassis); + AddInputPortWithDebug(number, "compositeIn1", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); + AddInputPortWithDebug(number, "compositeIn2", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); + AddInputPortWithDebug(number, "compositeIn3", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); + AddInputPortWithDebug(number, "compositeIn4", eRoutingSignalType.Video, eRoutingPortConnectionType.Composite); + AddInCardHdmiLoopPort(number); + } + else if (type == "dmcstr") + { + new DmcStr(number, Chassis); + AddInputPortWithDebug(number, "streamIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Streaming); + AddInCardHdmiAndAudioLoopPorts(number); + } + } + + void AddDmInCardPorts(uint number) + { + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat); + AddInCardHdmiAndAudioLoopPorts(number); + } + + void AddDmInCardPorts(uint number, ICec cecPort) + { + AddInputPortWithDebug(number, "dmIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort); + AddInCardHdmiAndAudioLoopPorts(number); + } + + void AddHdmiInCardPorts(uint number, ICec cecPort) + { + AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, cecPort); + AddInCardHdmiAndAudioLoopPorts(number); + } + + void AddInCardHdmiAndAudioLoopPorts(uint number) + { + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null); + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "audioLoopOut", eRoutingSignalType.Audio, eRoutingPortConnectionType.Hdmi, null); + } + + void AddInCardHdmiLoopPort(uint number) + { + AddOutputPortWithDebug(string.Format("inputCard{0}", number), "hdmiLoopOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null); + } + + /// + /// + /// + /// + /// + public void AddOutputCard(string type, uint number) + { + type = type.ToLower(); + + Debug.Console(2, this, "Adding output card '{0}', slot {1}", type, number); + if (type == "dmc4khdo") + { + var outputCard = new Dmc4kHdoSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + var cecPort2 = outputCard.Card2.HdmiOutput; + AddDmcHdoPorts(number, cecPort1, cecPort2); + } + else if (type == "dmchdo") + { + var outputCard = new DmcHdoSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + var cecPort2 = outputCard.Card2.HdmiOutput; + AddDmcHdoPorts(number, cecPort1, cecPort2); + } + else if (type == "dmc4kcohd") + { + var outputCard = new Dmc4kCoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); + } + else if (type == "dmc4kzcohd") + { + var outputCard = new Dmc4kzCoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); + } + else if (type == "dmccohd") + { + var outputCard = new DmcCoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); + } + else if (type == "dmccatohd") + { + var outputCard = new DmcCatoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddDmcCoPorts(number, cecPort1); + } + else if (type == "dmcsohd") + { + var outputCard = new DmcSoHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmMmFiber, 2 * (number - 1) + 1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, 2 * (number - 1) + 1, cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmMmFiber, 2 * (number - 1) + 2); + } + else if (type == "dmcs2ohd") + { + var outputCard = new DmcS2oHdSingle(number, Chassis); + var cecPort1 = outputCard.Card1.HdmiOutput; + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmSmFiber, 2 * (number - 1) + 1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, 2 * (number - 1) + 1, cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmSmFiber, 2 * (number - 1) + 2); + } + else if (type == "dmcstro") + { + var outputCard = new DmcStroSingle(number, Chassis); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "streamOut", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Streaming, 2 * (number - 1) + 1); + } + + else + Debug.Console(1, this, " WARNING: Output card type '{0}' is not available", type); + } + + void AddDmcHdoPorts(uint number, ICec cecPort1, ICec cecPort2) + { + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, 2 * (number - 1) + 1, cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "audioOut1", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, + 2 * (number - 1) + 1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, 2 * (number - 1) + 2, cecPort2); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "audioOut2", eRoutingSignalType.Audio, eRoutingPortConnectionType.LineAudio, + 2 * (number - 1) + 2); + } + + void AddDmcCoPorts(uint number, ICec cecPort1) + { + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmCat, 2 * (number - 1) + 1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "hdmiOut1", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, 2 * (number - 1) + 1, cecPort1); + AddOutputPortWithDebug(string.Format("outputCard{0}", number), "dmOut2", eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmCat, 2 * (number - 1) + 2); + } + + /// + /// Adds InputPort + /// + void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) + { + var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); + Debug.Console(2, this, "Adding input port '{0}'", portKey); + var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this); + + InputPorts.Add(inputPort); + } + + /// + /// Adds InputPort and sets Port as ICec object + /// + void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) + { + var portKey = string.Format("inputCard{0}--{1}", cardNum, portName); + Debug.Console(2, this, "Adding input port '{0}'", portKey); + var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this); + + if (cecPort != null) + inputPort.Port = cecPort; + + InputPorts.Add(inputPort); + } + + /// + /// Adds OutputPort + /// + void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) + { + var portKey = string.Format("{0}--{1}", cardName, portName); + Debug.Console(2, this, "Adding output port '{0}'", portKey); + OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)); + } + + /// + /// Adds OutputPort and sets Port as ICec object + /// + void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector, ICec cecPort) + { + var portKey = string.Format("{0}--{1}", cardName, portName); + Debug.Console(2, this, "Adding output port '{0}'", portKey); + var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this); + + if (cecPort != null) + outputPort.Port = cecPort; + + OutputPorts.Add(outputPort); + } + + /// + /// + /// + void AddVolumeControl(uint number, Audio.Output audio) + { + VolumeControls.Add(number, new DmCardAudioOutputController(audio)); + } + + //public void SetInputHdcpSupport(uint input, ePdtHdcpSupport hdcpSetting) + //{ + + //} + + void Chassis_DMSystemChange(Switch device, DMSystemEventArgs args) + { + switch (args.EventId) + { + case DMSystemEventIds.SystemIdEventId: + { + Debug.Console(2, this, "SystemIdEvent Value: {0}", (Chassis as DmMDMnxn).SystemIdFeedback.UShortValue); + SystemIdFeebdack.FireUpdate(); + break; + } + case DMSystemEventIds.SystemIdBusyEventId: + { + Debug.Console(2, this, "SystemIdBusyEvent State: {0}", (Chassis as DmMDMnxn).SystemIdBusy.BoolValue); + SystemIdBusyFeedback.FireUpdate(); + break; + } + case DMSystemEventIds.AudioBreakawayEventId: + { + Debug.Console(2, this, "AudioBreakaway Event: value: {0}", + (Chassis as DmMDMnxn).EnableAudioBreakawayFeedback.BoolValue); + EnableAudioBreakawayFeedback.FireUpdate(); + break; + } + case DMSystemEventIds.USBBreakawayEventId: + { + Debug.Console(2, this, "USBBreakaway Event: value: {0}", + (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue); + EnableUsbBreakawayFeedback.FireUpdate(); + break; + } + } + } + + void Chassis_DMInputChange(Switch device, DMInputEventArgs args) + { + switch (args.EventId) + { + case DMInputEventIds.EndpointOnlineEventId: + { + Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); + InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.OnlineFeedbackEventId: + { + Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); + InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); + VideoInputSyncFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.InputNameEventId: + { + Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); + InputNameFeedbacks[args.Number].FireUpdate(); + break; + } + case DMInputEventIds.UsbRoutedToEventId: + { + Debug.Console(2, this, "DM Input {0} UsbRoutedToEventId", args.Number); + if (UsbInputRoutedToFeebacks[args.Number] != null) + UsbInputRoutedToFeebacks[args.Number].FireUpdate(); + else + Debug.Console(1, this, "No index of {0} found in UsbInputRoutedToFeedbacks"); + break; + } + case DMInputEventIds.HdcpCapabilityFeedbackEventId: + { + Debug.Console(2, this, "DM Input {0} HdcpCapabilityFeedbackEventId", args.Number); + if (InputCardHdcpStateFeedbacks[args.Number] != null) + InputCardHdcpStateFeedbacks[args.Number].FireUpdate(); + else + Debug.Console(1, this, "No index of {0} found in InputCardHdcpStateFeedbacks"); + break; + } + default: + { + Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId); + break; + } + } + } + + /// + /// + void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args) + { + var output = args.Number; + + switch (args.EventId) + { + case DMOutputEventIds.VolumeEventId: + { + if (VolumeControls.ContainsKey(output)) + { + VolumeControls[args.Number].VolumeEventFromChassis(); + } + + break; + } + case DMOutputEventIds.EndpointOnlineEventId: + { + Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. State: {1}", args.Number, + Chassis.Outputs[output].EndpointOnlineFeedback); + OutputEndpointOnlineFeedbacks[output].FireUpdate(); + break; + } + case DMOutputEventIds.OnlineFeedbackEventId: + { + Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", args.Number, + Chassis.Outputs[output].EndpointOnlineFeedback); + OutputEndpointOnlineFeedbacks[output].FireUpdate(); + break; + } + case DMOutputEventIds.VideoOutEventId: + { + if (Chassis.Outputs[output].VideoOutFeedback != null) + Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output); + + if (VideoOutputFeedbacks.ContainsKey(output)) + VideoOutputFeedbacks[output].FireUpdate(); + + if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) + OutputVideoRouteNameFeedbacks[output].FireUpdate(); + + break; + } + case DMOutputEventIds.AudioOutEventId: + { + if (Chassis.Outputs[output].AudioOutFeedback != null) + Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].AudioOutFeedback.Number, output); + + if (AudioOutputFeedbacks.ContainsKey(output)) + AudioOutputFeedbacks[output].FireUpdate(); + + if (OutputAudioRouteNameFeedbacks.ContainsKey(output)) + OutputAudioRouteNameFeedbacks[output].FireUpdate(); + + break; + } + case DMOutputEventIds.OutputNameEventId: + { + Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); + OutputNameFeedbacks[output].FireUpdate(); + break; + } + case DMOutputEventIds.UsbRoutedToEventId: + { + Debug.Console(2, this, "DM Output {0} UsbRoutedToEventId", args.Number); + UsbOutputRoutedToFeebacks[args.Number].FireUpdate(); + break; + } + case DMOutputEventIds.DisabledByHdcpEventId: + { + Debug.Console(2, this, "DM Output {0} DisabledByHdcpEventId", args.Number); + OutputDisabledByHdcpFeedbacks[args.Number].FireUpdate(); + break; + } + default: + { + Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", args.Number, args.EventId); + break; + } + } + } + + /// + /// + /// + /// + void StartOffTimer(PortNumberType pnt) + { + if (RouteOffTimers.ContainsKey(pnt)) + return; + RouteOffTimers[pnt] = new CTimer(o => { ExecuteSwitch(0, pnt.Number, pnt.Type); }, RouteOffTime); + } + + // Send out sigs when coming online + void IsOnline_OutputChange(object sender, EventArgs e) + { + if (IsOnline.BoolValue) + { + (Chassis as DmMDMnxn).EnableAudioBreakaway.BoolValue = true; + (Chassis as DmMDMnxn).EnableUSBBreakaway.BoolValue = true; + + + EnableAudioBreakawayFeedback.FireUpdate(); + EnableUsbBreakawayFeedback.FireUpdate(); + + if (InputNames != null) + foreach (var kvp in InputNames) + Chassis.Inputs[kvp.Key].Name.StringValue = kvp.Value; + if (OutputNames != null) + foreach (var kvp in OutputNames) + Chassis.Outputs[kvp.Key].Name.StringValue = kvp.Value; + } + } + + #region IRouting Members + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) + { + Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType); + + var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail + var output = Convert.ToUInt32(outputSelector); + + var chassisSize = (uint) Chassis.NumberOfInputs; //need this to determine USB routing values 8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 + //16x16 1-16 is inputs 1-16, 17-32 is outputs 1-16 + //32x32 1-32 is inputs 1-32, 33-64 is outputs 1-32 + + // Check to see if there's an off timer waiting on this and if so, cancel + var key = new PortNumberType(output, sigType); + if (input == 0) + { + StartOffTimer(key); + } + else + { + if (RouteOffTimers.ContainsKey(key)) + { + Debug.Console(2, this, "{0} cancelling route off due to new source", output); + RouteOffTimers[key].Stop(); + RouteOffTimers.Remove(key); + } + } + + var inCard = input == 0 ? null : Chassis.Inputs[input]; + var outCard = input == 0 ? null : Chassis.Outputs[output]; + + // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES + if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) + { + Chassis.VideoEnter.BoolValue = true; + Chassis.Outputs[output].VideoOut = inCard; + } + + if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio) + { + (Chassis as DmMDMnxn).AudioEnter.BoolValue = true; + Chassis.Outputs[output].AudioOut = inCard; + } + + if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput) + { + //using base here because USB can be routed between 2 output cards or 2 input cards + DMInputOutputBase dmCard; + + Debug.Console(2, this, "Executing USB Output switch.\r\n in:{0} output: {1}", input, output); + + if (input > chassisSize) + { + //wanting to route an output to an output. Subtract chassis size and get output, unless it's 8x8 + //need this to determine USB routing values + //8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 + //16x16 1-16 is inputs 1-16, 17-32 is outputs 1-16 + //32x32 1-32 is inputs 1-32, 33-64 is outputs 1-32 + uint outputIndex; + + if (chassisSize == 8) + { + outputIndex = input - 16; + } + else + { + outputIndex = input - chassisSize; + } + dmCard = Chassis.Outputs[outputIndex]; + } + else + { + dmCard = inCard; + } + Chassis.USBEnter.BoolValue = true; + if (Chassis.Outputs[output] != null) + { + Debug.Console(2, this, "Routing USB for input {0} to {1}", Chassis.Outputs[input], dmCard); + Chassis.Outputs[output].USBRoutedTo = dmCard; + } + } + + if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) + { + //using base here because USB can be routed between 2 output cards or 2 input cards + DMInputOutputBase dmCard; + + Debug.Console(2, this, "Executing USB Input switch.\r\n in:{0} output: {1}", input, output); + + if (output > chassisSize) + { + //wanting to route an input to an output. Subtract chassis size and get output, unless it's 8x8 + //need this to determine USB routing values + //8x8 -> 1-8 is inputs 1-8, 17-24 is outputs 1-8 + //16x16 1-16 is inputs 1-16, 17-32 is outputs 1-16 + //32x32 1-32 is inputs 1-32, 33-64 is outputs 1-32 + uint outputIndex; + + if (chassisSize == 8) + { + outputIndex = input - 16; + } + else + { + outputIndex = input - chassisSize; + } + dmCard = Chassis.Outputs[outputIndex]; + } + else + { + dmCard = Chassis.Inputs[input]; + } + + + + Chassis.USBEnter.BoolValue = true; + + if (Chassis.Inputs[output] == null) + { + return; + } + Debug.Console(2, this, "Routing USB for input {0} to {1}", Chassis.Inputs[output], dmCard); + Chassis.Inputs[output].USBRoutedTo = dmCard; + } + } + #endregion + + #region IRoutingNumeric Members + + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType) + { + ExecuteSwitch(inputSelector, outputSelector, sigType); + } + + #endregion + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = GetJoinMap(joinStart, joinMapKey, bridge); + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + LinkChassisToApi(trilist, joinMap); + + // Link up inputs & outputs + for (uint i = 1; i <= Chassis.NumberOfOutputs; i++) + { + var ioSlot = i; + var ioSlotJoin = ioSlot - 1; + + LinkRoutingJoinsToApi(trilist, joinMap, ioSlotJoin, ioSlot); + + if (TxDictionary.ContainsKey(ioSlot)) + { + LinkTxToApi(trilist, ioSlot, joinMap, ioSlotJoin); + } + else + { + LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin); + } + + if (RxDictionary.ContainsKey(ioSlot)) + { + LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin); + } + } + } + + private void LinkHdmiInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) + { + VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + + var inputPort = InputPorts[string.Format("inputCard{0}--hdmiIn", ioSlot)]; + if (inputPort == null) + { + return; + } + + Debug.Console(1, "Port value for input card {0} is set", ioSlot); + var port = inputPort.Port; + + if (port == null) + { + return; + } + if (!(port is HdmiInputWithCEC)) + { + Debug.Console(0, this, "HDMI Input port on card {0} does not support HDCP settings.", ioSlot); + return; + } + + Debug.Console(1, "Port is HdmiInputWithCec"); + + var hdmiInPortWCec = port as HdmiInputWithCEC; + + + SetHdcpStateAction(true, hdmiInPortWCec, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); + + + InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + + if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = + (ushort)InputCardHdcpCapabilityTypes[ioSlot]; + } + else + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; + } + } + + private void LinkRxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) + { + Debug.Console(2, "Creating Rx Feedbacks {0}", ioSlot); + var rxKey = RxDictionary[ioSlot]; + var rxDevice = DeviceManager.GetDeviceForKey(rxKey) as DmRmcControllerBase; + var hdBaseTDevice = DeviceManager.GetDeviceForKey(rxKey) as DmHdBaseTControllerBase; + if (Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps + || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps + || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps || hdBaseTDevice != null) + { + OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); + } + else if (rxDevice != null) + { + rxDevice.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]); + } + } + + private void LinkTxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin) + { + Debug.Console(1, "Setting up actions and feedbacks on input card {0}", ioSlot); + VideoInputSyncFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + + Debug.Console(2, "Creating Tx Feedbacks {0}", ioSlot); + var txKey = TxDictionary[ioSlot]; + var txDevice = DeviceManager.GetDeviceForKey(txKey) as BasicDmTxControllerBase; + + if (txDevice == null) + { + return; + } + + LinkTxOnlineFeedbackToApi(trilist, ioSlot, joinMap, ioSlotJoin, txDevice); + + LinkBasicTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); + + LinkAdvancedTxToApi(trilist, joinMap, ioSlot, ioSlotJoin, txDevice); + } + + private void LinkBasicTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlot, + uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) + { + var advTx = basicTransmitter as DmTxControllerBase; + + if (advTx != null) + { + return; + } + var inputPort = InputPorts[string.Format("inputCard{0}--dmIn", ioSlot)]; + + if (inputPort == null) + { + return; + } + var port = inputPort.Port; + + if (!(port is DMInputPortWithCec)) + { + Debug.Console(0, this, "DM Input port on card {0} does not support HDCP settings.", ioSlot); + return; + } + Debug.Console(1, "Port is DMInputPortWithCec"); + + var dmInPortWCec = port as DMInputPortWithCec; + + bool supportsHdcp2; + + //added in case the InputSlotSupportsHdcp2 section isn't included in the config, or this slot is left out. + //if the key isn't in the dictionary, supportsHdcp2 will be false + + if(!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, + "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", + ioSlot); + } + + SetHdcpStateAction(supportsHdcp2, dmInPortWCec, + joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); + + InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + + if (InputCardHdcpCapabilityTypes.ContainsKey(ioSlot)) + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = + (ushort) InputCardHdcpCapabilityTypes[ioSlot]; + } + else + { + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1; + } + } + + private void LinkAdvancedTxToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, + uint ioSlot, uint ioSlotJoin, BasicDmTxControllerBase basicTransmitter) + { + var transmitter = basicTransmitter as DmTxControllerBase; + if (transmitter == null) return; + + trilist.BooleanInput[joinMap.TxAdvancedIsPresent.JoinNumber + ioSlotJoin].BoolValue = true; + + transmitter.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); + + var txRoutingInputs = transmitter as IRoutingInputs; + + if (txRoutingInputs == null) return; + + var inputPorts = txRoutingInputs.InputPorts.Where((p) => p.Port is EndpointHdmiInput || p.Port is EndpointDisplayPortInput).ToList(); + + if (inputPorts.Count == 0) + { + Debug.Console(1, this, "No HDCP-capable input ports found on transmitter for slot {0}", ioSlot); + return; + } + + bool supportsHdcp2; + + if (!PropertiesConfig.InputSlotSupportsHdcp2.TryGetValue(ioSlot, out supportsHdcp2)) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, + "Input Slot Supports HDCP2 setting not found for slot {0}. Setting to false. Program may not function as intended.", + ioSlot); + } + + SetHdcpStateAction(supportsHdcp2, inputPorts, joinMap.HdcpSupportState.JoinNumber + ioSlotJoin, trilist); + + if (transmitter.HdcpStateFeedback != null) + { + transmitter.HdcpStateFeedback.LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + } + else + { + Debug.Console(2, this, "Transmitter Hdcp Feedback null. Linking to card's feedback"); + InputCardHdcpStateFeedbacks[ioSlot].LinkInputSig( + trilist.UShortInput[joinMap.HdcpSupportState.JoinNumber + ioSlotJoin]); + } + + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = + (ushort) transmitter.HdcpSupportCapability; + } + + private void LinkTxOnlineFeedbackToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, + uint ioSlotJoin, BasicDmTxControllerBase txDevice) + { + var advancedTxDevice = txDevice as DmTxControllerBase; + + if ((Chassis is DmMd8x8Cpu3 || Chassis is DmMd8x8Cpu3rps + || Chassis is DmMd16x16Cpu3 || Chassis is DmMd16x16Cpu3rps + || Chassis is DmMd32x32Cpu3 || Chassis is DmMd32x32Cpu3rps) || + advancedTxDevice == null) + { + Debug.Console(2, "Linking Tx Online Feedback from Input Card {0}", ioSlot); + InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); + return; + } + + Debug.Console(2, "Linking Tx Online Feedback from Advanced Transmitter at input {0}", ioSlot); + + advancedTxDevice.IsOnline.LinkInputSig( + trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); + } + + private void LinkRoutingJoinsToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap, uint ioSlotJoin, + uint ioSlot) + { + // Routing Control + trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, + o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)); + trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin, + o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)); + trilist.SetUShortSigAction(joinMap.OutputUsb.JoinNumber + ioSlotJoin, + o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.UsbOutput)); + trilist.SetUShortSigAction(joinMap.InputUsb.JoinNumber + ioSlotJoin, + o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.UsbInput)); + + //Routing Feedbacks + VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]); + AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]); + UsbOutputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputUsb.JoinNumber + ioSlotJoin]); + UsbInputRoutedToFeebacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.InputUsb.JoinNumber + ioSlotJoin]); + + OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); + InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); + OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig( + trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]); + OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig( + trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]); + + OutputDisabledByHdcpFeedbacks[ioSlot].LinkInputSig( + trilist.BooleanInput[joinMap.OutputDisabledByHdcp.JoinNumber + ioSlotJoin]); + } + + private void LinkChassisToApi(BasicTriList trilist, DmChassisControllerJoinMap joinMap) + { + var chassis = Chassis as DmMDMnxn; + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + + trilist.SetUShortSigAction(joinMap.SystemId.JoinNumber, o => + { + if (chassis != null) + { + chassis.SystemId.UShortValue = o; + } + }); + + trilist.SetSigTrueAction(joinMap.SystemId.JoinNumber, () => + { + if (chassis != null) + { + chassis.ApplySystemId(); + } + }); + + SystemIdFeebdack.LinkInputSig(trilist.UShortInput[joinMap.SystemId.JoinNumber]); + SystemIdBusyFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemId.JoinNumber]); + + EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]); + EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]); + + trilist.OnlineStatusChange += (o, a) => + { + if (!a.DeviceOnLine) + { + return; + } + + EnableAudioBreakawayFeedback.FireUpdate(); + EnableUsbBreakawayFeedback.FireUpdate(); + SystemIdBusyFeedback.FireUpdate(); + SystemIdFeebdack.FireUpdate(); + }; + } + + private DmChassisControllerJoinMap GetJoinMap(uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DmChassisControllerJoinMap(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."); + } + return joinMap; + } + + private void SetHdcpStateAction(bool supportsHdcp2, HdmiInputWithCEC port, uint join, BasicTriList trilist) + { + if (!supportsHdcp2) + { + trilist.SetUShortSigAction(join, + s => + { + if (s == 0) + { + port.HdcpSupportOff(); + } + else if (s > 0) + { + port.HdcpSupportOn(); + } + }); + } + else + { + trilist.SetUShortSigAction(join, + u => + { + port.HdcpReceiveCapability = (eHdcpCapabilityType)u; + }); + } + } + + private void SetHdcpStateAction(bool supportsHdcp2, EndpointHdmiInput port, uint join, BasicTriList trilist) + { + if (!supportsHdcp2) + { + trilist.SetUShortSigAction(join, + s => + { + if (s == 0) + { + port.HdcpSupportOff(); + } + else if (s > 0) + { + port.HdcpSupportOn(); + } + }); + } + else + { + trilist.SetUShortSigAction(join, + u => + { + port.HdcpCapability = (eHdcpCapabilityType)u; + }); + } + } + + private void SetHdcpStateAction(bool supportsHdcp2, List ports, uint join, + BasicTriList triList) + { + if (!supportsHdcp2) + { + triList.SetUShortSigAction(join, a => + { + foreach (var tempPort in ports.Select(port => port.Port).OfType()) + { + if (a == 0) + { + tempPort.HdcpSupportOff(); + } + else if (a > 0) + { + tempPort.HdcpSupportOn(); + } + } + }); + } + else + { + triList.SetUShortSigAction(join, a => + { + foreach (var tempPort in ports.Select(port => port.Port).OfType()) + { + tempPort.HdcpCapability = (eHdcpCapabilityType) a; + } + }); + } + } + + private void SetHdcpStateAction(bool supportsHdcp2, DMInputPortWithCec port, uint join, BasicTriList trilist) + { + if (!supportsHdcp2) + { + trilist.SetUShortSigAction(join, + s => + { + if (s == 0) + { + port.HdcpSupportOff(); + } + else if (s > 0) + { + port.HdcpSupportOn(); + } + }); + } + else + { + trilist.SetUShortSigAction(join, + u => + { + port.HdcpReceiveCapability = (eHdcpCapabilityType)u; + }); + } + } + } + + public struct PortNumberType + { + public uint Number { get; private set; } + public eRoutingSignalType Type { get; private set; } + + public PortNumberType(uint number, eRoutingSignalType type) + : this() + { + Number = number; + Type = type; + } + } + + public class DmChassisControllerFactory : EssentialsDeviceFactory + { + public DmChassisControllerFactory() + { + TypeNames = new List() { "dmmd8x8", "dmmd8x8rps", "dmmd8x8cpu3", "dmmd8x8cpu3rps", + "dmmd16x16", "dmmd16x16rps", "dmmd16x16cpu3", "dmmd16x16cpu3rps", + "dmmd32x32", "dmmd32x32rps", "dmmd32x32cpu3", "dmmd32x32cpu3rps", + "dmmd64x64", "dmmd128x128" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + var type = dc.Type.ToLower(); + + Debug.Console(1, "Factory Attempting to create new DmChassisController Device"); + + if (type.StartsWith("dmmd8x") || type.StartsWith("dmmd16x") || type.StartsWith("dmmd32x")) + { + + var props = JsonConvert.DeserializeObject + (dc.Properties.ToString()); + return PepperDash.Essentials.DM.DmChassisController. + GetDmChassisController(dc.Key, dc.Name, type, props); + } + else if (type.StartsWith("dmmd128x") || type.StartsWith("dmmd64x")) + { + var props = JsonConvert.DeserializeObject + (dc.Properties.ToString()); + return PepperDash.Essentials.DM.DmBladeChassisController. + GetDmChassisController(dc.Key, dc.Name, type, props); + } + + return null; + } + } + +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs index fff3b112..57c52627 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs @@ -4,14 +4,16 @@ using System.Linq; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DM; +using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM.Chassis { - public class HdMdNxM4kEController : Device, IRoutingInputsOutputs, IRouting + public class HdMdNxM4kEController : CrestronGenericBaseDevice, IRoutingInputsOutputs, IRouting { public HdMdNxM Chassis { get; private set; } @@ -27,7 +29,7 @@ namespace PepperDash.Essentials.DM.Chassis /// public HdMdNxM4kEController(string key, string name, HdMdNxM chassis, HdMdNxM4kEPropertiesConfig props) - : base(key, name) + : base(key, name, chassis) { Chassis = chassis; @@ -99,6 +101,8 @@ namespace PepperDash.Essentials.DM.Chassis /// /// /// + /// /* + /* public static HdMdNxM4kEController GetController(string key, string name, string type, HdMdNxM4kEPropertiesConfig properties) { @@ -123,6 +127,35 @@ namespace PepperDash.Essentials.DM.Chassis Debug.Console(0, "ERROR Creating device key {0}: \r{1}", key, e); return null; } + }*/ + + #region Factory + + public class HdMdNxM4kEFactory : EssentialsDeviceFactory + { + public HdMdNxM4kEFactory() + { + TypeNames = new List() {"hdmd4x14ke"}; + } + + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + var type = dc.Type.ToLower(); + var control = props.Control; + var ipid = control.IpIdInt; + var address = control.TcpSshProperties.Address; + + return new HdMdNxM4kEController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props); + + } } + + #endregion + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index ba12a129..e33e54fd 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -114,8 +114,6 @@ - - @@ -150,8 +148,6 @@ - - diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs index c860d0cb..dd99fe34 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs @@ -17,7 +17,7 @@ using PepperDash.Essentials.Core.CrestronIO; using PepperDash.Essentials.Devices.Common; using PepperDash.Essentials.Devices.Common.DSP; using PepperDash.Essentials.Devices.Common.VideoCodec; -using PepperDash.Essentials.Devices.Common.Occupancy; +using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Environment; namespace PepperDash.Essentials.Devices.Common diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index cad7a18c..bd4fee99 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -13,7 +13,7 @@ using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; -using PepperDash.Essentials.Devices.Common.Occupancy; +using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco @@ -601,9 +601,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco //JsonSerializerSettings settings = new JsonSerializerSettings(); //settings.NullValueHandling = NullValueHandling.Ignore; //settings.MissingMemberHandling = MissingMemberHandling.Ignore; - //settings.ObjectCreationHandling = ObjectCreationHandling.Auto; - - if (response.IndexOf("\"Status\":{") > -1) + //settings.ObjectCreationHandling = ObjectCreationHandling.Auto; + + if (response.IndexOf("\"Status\":{") > -1 || response.IndexOf("\"Status\": {") > -1) { // Status Message @@ -775,8 +775,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco if (!SyncState.InitialConfigurationMessageWasReceived) SendText("xConfiguration"); } - } - else if (response.IndexOf("\"Configuration\":{") > -1) + } + else if (response.IndexOf("\"Configuration\":{") > -1 || response.IndexOf("\"Configuration\": {") > -1) { // Configuration Message @@ -791,39 +791,39 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco } } - } - else if (response.IndexOf("\"Event\":{") > -1) - { - if (response.IndexOf("\"CallDisconnect\":{") > -1) + } + else if (response.IndexOf("\"Event\":{") > -1 || response.IndexOf("\"Event\": {") > -1) + { + if (response.IndexOf("\"CallDisconnect\":{") > -1 || response.IndexOf("\"CallDisconnect\": {") > -1) { CiscoCodecEvents.RootObject eventReceived = new CiscoCodecEvents.RootObject(); JsonConvert.PopulateObject(response, eventReceived); EvalutateDisconnectEvent(eventReceived); - } - else if (response.IndexOf("\"Bookings\":{") > -1) // The list has changed, reload it + } + else if (response.IndexOf("\"Bookings\":{") > -1 || response.IndexOf("\"Bookings\": {") > -1) // The list has changed, reload it { GetBookings(null); } - } - else if (response.IndexOf("\"CommandResponse\":{") > -1) + } + else if (response.IndexOf("\"CommandResponse\":{") > -1 || response.IndexOf("\"CommandResponse\": {") > -1) { - // CommandResponse Message - - if (response.IndexOf("\"CallHistoryRecentsResult\":{") > -1) + // CommandResponse Message + + if (response.IndexOf("\"CallHistoryRecentsResult\":{") > -1 || response.IndexOf("\"CallHistoryRecentsResult\": {") > -1) { var codecCallHistory = new CiscoCallHistory.RootObject(); JsonConvert.PopulateObject(response, codecCallHistory); CallHistory.ConvertCiscoCallHistoryToGeneric(codecCallHistory.CommandResponse.CallHistoryRecentsResult.Entry); - } - else if (response.IndexOf("\"CallHistoryDeleteEntryResult\":{") > -1) + } + else if (response.IndexOf("\"CallHistoryDeleteEntryResult\":{") > -1 || response.IndexOf("\"CallHistoryDeleteEntryResult\": {") > -1) { GetCallHistory(); - } - else if (response.IndexOf("\"PhonebookSearchResult\":{") > -1) + } + else if (response.IndexOf("\"PhonebookSearchResult\":{") > -1 || response.IndexOf("\"PhonebookSearchResult\": {") > -1) { var codecPhonebookResponse = new CiscoCodecPhonebook.RootObject(); @@ -1658,7 +1658,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco { get { - if (CodecStatus.Status.SIP.Registration.Count > 0) + if (CodecStatus.Status.SIP != null && CodecStatus.Status.SIP.Registration.Count > 0) { var match = Regex.Match(CodecStatus.Status.SIP.Registration[0].URI.Value, @"(\d+)"); // extract numbers only if (match.Success) @@ -1678,17 +1678,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco return string.Empty; } } - } - public override string SipUri - { - get - { - if (CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value != null) - return CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value; - else - return string.Empty; - } - } + } + + public override string SipUri + { + get + { + if (CodecStatus.Status.SIP != null && CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value != null) + { + return CodecStatus.Status.SIP.AlternateURI.Primary.URI.Value; + } + else if (CodecStatus.Status.UserInterface != null && + CodecStatus.Status.UserInterface.ContactInfo.ContactMethod[0].Number.Value != null) + { + return CodecStatus.Status.UserInterface.ContactInfo.ContactMethod[0].Number.Value; + } + else + return string.Empty; + } + } + public override bool AutoAnswerEnabled { get diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs index 13fa895d..c64bdf36 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ZoomRoom.cs @@ -13,7 +13,7 @@ using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Codec; -using PepperDash.Essentials.Devices.Common.Occupancy; +using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec; namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom