diff --git a/.github/workflows/add-issues-to-project.yml b/.github/workflows/add-issues-to-project.yml deleted file mode 100644 index 8811c0cc..00000000 --- a/.github/workflows/add-issues-to-project.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Add bugs to bugs project - -on: - issues: - types: - - opened - - labeled - -jobs: - check-secret: - runs-on: ubuntu-latest - outputs: - my-key: ${{ steps.my-key.outputs.defined }} - steps: - - id: my-key - if: "${{ env.MY_KEY != '' }}" - run: echo "::set-output name=defined::true" - env: - MY_KEY: ${{ secrets.PROJECT_URL }} - throw-error: - name: Check - runs-on: ubuntu-latest - needs: [check-secret] - if: needs.check-secret.outputs.my-key != 'true' - steps: - - run: echo "The Project URL Repo Secret is empty" - add-to-project: - name: Add issue to project - runs-on: ubuntu-latest - needs: [check-secret] - if: needs.check-secret.outputs.my-key == 'true' - steps: - - uses: actions/add-to-project@main - with: - project-url: ${{ secrets.PROJECT_URL }} - github-token: ${{ secrets.GH_PROJECTS_PASSWORD }} - diff --git a/.gitignore b/.gitignore index 94b7d400..739a60ab 100644 --- a/.gitignore +++ b/.gitignore @@ -389,3 +389,4 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/PepperDash_Essentials_Interfaces.csproj +.DS_Store diff --git a/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs b/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs index 19c0f501..58917199 100644 --- a/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs +++ b/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs @@ -167,7 +167,7 @@ namespace PepperDash.Essentials.Core.Bridges Debug.Console(1, this, "Linking Device: '{0}'", device.Key); - if (!typeof (IBridgeAdvanced).IsAssignableFrom(device.GetType().GetCType())) + if (!typeof(IBridgeAdvanced).IsAssignableFrom(device.GetType().GetCType())) { Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.", @@ -411,7 +411,7 @@ namespace PepperDash.Essentials.Core.Bridges public List Devices { get; set; } [JsonProperty("rooms")] - public List Rooms { get; set; } + public List Rooms { get; set; } public class ApiDevicePropertiesConfig @@ -444,7 +444,7 @@ namespace PepperDash.Essentials.Core.Bridges { public EiscApiAdvancedFactory() { - TypeNames = new List { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" }; + TypeNames = new List { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) @@ -459,34 +459,34 @@ namespace PepperDash.Essentials.Core.Bridges { case "eiscapiadv": case "eiscapiadvanced": - { - eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt, - controlProperties.TcpSshProperties.Address, Global.ControlSystem); - break; - } - case "eiscapiadvancedserver": - { - eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem); - break; - } - case "eiscapiadvancedclient": - { - eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); - break; - } - case "vceiscapiadv": - case "vceiscapiadvanced": - { - if (string.IsNullOrEmpty(controlProperties.RoomId)) { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key); - eisc = null; + eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt, + controlProperties.TcpSshProperties.Address, Global.ControlSystem); + break; + } + case "eiscapiadvancedserver": + { + eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem); + break; + } + case "eiscapiadvancedclient": + { + eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); + break; + } + case "vceiscapiadv": + case "vceiscapiadvanced": + { + if (string.IsNullOrEmpty(controlProperties.RoomId)) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key); + eisc = null; + break; + } + eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId, + Global.ControlSystem); break; } - eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId, - Global.ControlSystem); - break; - } default: eisc = null; break; diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs index 8c2386fd..56f0825c 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs @@ -8,6 +8,18 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "DM RMC Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("VideoMuteOn")] + public JoinDataComplete VideoMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Mute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteOff")] + public JoinDataComplete VideoMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC UnMute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteToggle")] + public JoinDataComplete VideoMuteToggle = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Mute Video Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("CurrentOutputResolution")] public JoinDataComplete CurrentOutputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "DM RMC Current Output Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); @@ -36,6 +48,28 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("HdcpSupportCapability")] + public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port1HdcpState")] + public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Port 1 (DM) HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port2HdcpState")] + public JoinDataComplete Port2HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Port 2 (HDMI) HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdmiInputSync")] + public JoinDataComplete HdmiInputSync = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC HDMI Input Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HdcpInputPortCount")] + public JoinDataComplete HdcpInputPortCount = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of Input Ports that support HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + + /// /// Constructor to use when instantiating this Join Map without inheriting from it /// @@ -50,7 +84,8 @@ namespace PepperDash.Essentials.Core.Bridges /// /// Join this join map will start at /// Type of the child join map - protected DmRmcControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + protected DmRmcControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) { } } diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs index 23d240d5..c6f8f89f 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs @@ -64,6 +64,16 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete VgaContrast = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, new JoinMetadata { Description = "DM TX Online", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("Port3HdcpState")] + public JoinDataComplete Port3HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Port 3 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpInputPortCount")] + public JoinDataComplete HdcpInputPortCount = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of Input Ports that support HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + + /// /// Constructor to use when instantiating this Join Map without inheriting from it /// @@ -78,7 +88,8 @@ namespace PepperDash.Essentials.Core.Bridges /// /// Join this join map will start at /// Type of the child join map - protected DmTxControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + protected DmTxControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) { } } diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs new file mode 100644 index 00000000..288141bb --- /dev/null +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs @@ -0,0 +1,827 @@ +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Bridges.JoinMaps +{ + public sealed class GenericIrControllerJoinMap : JoinMapBaseAdvanced + { + [JoinName("PLAY")] + public JoinDataComplete Play = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "PLAY", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("STOP")] + public JoinDataComplete Stop = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "STOP", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PAUSE")] + public JoinDataComplete Pause = new JoinDataComplete( + new JoinData + { + JoinNumber = 3, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "PAUSE", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("FSCAN")] + public JoinDataComplete ForwardScan = new JoinDataComplete( + new JoinData + { + JoinNumber = 4, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "FSCAN", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RSCAN")] + public JoinDataComplete ReverseScan = new JoinDataComplete( + new JoinData + { + JoinNumber = 5, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "RSCAN", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("F_SKIP")] + public JoinDataComplete ForwardSkip = new JoinDataComplete( + new JoinData + { + JoinNumber = 6, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "F_SKIP", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("R_SKIP")] + public JoinDataComplete ReverseSkip = new JoinDataComplete( + new JoinData + { + JoinNumber = 7, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "R_SKIP", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RECORD")] + public JoinDataComplete Record = new JoinDataComplete( + new JoinData + { + JoinNumber = 8, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "RECORD", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("POWER")] + public JoinDataComplete Power = new JoinDataComplete( + new JoinData + { + JoinNumber = 9, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "POWER", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("0")] + public JoinDataComplete Kp0 = new JoinDataComplete( + new JoinData + { + JoinNumber = 10, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "0", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("1")] + public JoinDataComplete Kp1 = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "1", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] + public JoinDataComplete Kp2 = new JoinDataComplete( + new JoinData + { + JoinNumber = 12, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "2", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] + public JoinDataComplete Kp3 = new JoinDataComplete( + new JoinData + { + JoinNumber = 13, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "3", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] + public JoinDataComplete Kp4 = new JoinDataComplete( + new JoinData + { + JoinNumber = 14, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "4", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] + public JoinDataComplete Kp5 = new JoinDataComplete( + new JoinData + { + JoinNumber = 15, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "5", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] + public JoinDataComplete Kp6 = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "6", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] + public JoinDataComplete Kp7 = new JoinDataComplete( + new JoinData + { + JoinNumber = 17, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "7", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] + public JoinDataComplete Kp8 = new JoinDataComplete( + new JoinData + { + JoinNumber = 18, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] + public JoinDataComplete Kp9 = new JoinDataComplete( + new JoinData + { + JoinNumber = 19, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "9", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + // [JoinName("+10")] + // public JoinDataComplete Kp9 = new JoinDataComplete( + // new JoinData + // { + // JoinNumber = 20, + // JoinSpan = 1 + // }, + // new JoinMetadata + // { + // Description = "+10", + // JoinCapabilities = eJoinCapabilities.FromSIMPL, + // JoinType = eJoinType.Digital + // }); + + [JoinName("ENTER")] + public JoinDataComplete Enter = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "ENTER", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CH+")] + public JoinDataComplete ChannelUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 22, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "CH+", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CH-")] + public JoinDataComplete ChannelDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 23, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "CH-", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] + public JoinDataComplete KpStar = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "*", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] + public JoinDataComplete KpPound = new JoinDataComplete( + new JoinData + { + JoinNumber = 25, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "#", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + // [JoinName(".")] + // public JoinDataComplete KpPound = new JoinDataComplete( + // new JoinData + // { + // JoinNumber = 26, + // JoinSpan = 1 + // }, + // new JoinMetadata + // { + // Description = ".", + // JoinCapabilities = eJoinCapabilities.FromSIMPL, + // JoinType = eJoinType.Digital + // }); + + [JoinName("POWER_ON")] + public JoinDataComplete PowerOn = new JoinDataComplete( + new JoinData + { + JoinNumber = 27, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "POWER_ON", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("POWER_OFF")] + public JoinDataComplete PowerOff = new JoinDataComplete( + new JoinData + { + JoinNumber = 28, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "POWER_OFF", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PLAY_PAUSE")] + public JoinDataComplete PlayPause = new JoinDataComplete( + new JoinData + { + JoinNumber = 29, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "PLAY_PAUSE", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LAST")] + public JoinDataComplete Last = new JoinDataComplete( + new JoinData + { + JoinNumber = 30, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "LAST", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HOME")] + public JoinDataComplete Home = new JoinDataComplete( + new JoinData + { + JoinNumber = 40, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "HOME", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("BACK")] + public JoinDataComplete Back = new JoinDataComplete( + new JoinData + { + JoinNumber = 41, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "BACK", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("GUIDE")] + public JoinDataComplete Guide = new JoinDataComplete( + new JoinData + { + JoinNumber = 42, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "GUIDE", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("INFO")] + public JoinDataComplete Info = new JoinDataComplete( + new JoinData + { + JoinNumber = 43, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "INFO", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MENU")] + public JoinDataComplete Menu = new JoinDataComplete( + new JoinData + { + JoinNumber = 44, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "MENU", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UP_ARROW")] + public JoinDataComplete DpadUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 45, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "UP_ARROW", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DN_ARROW")] + public JoinDataComplete DpadDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 46, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DN_ARROW", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("LEFT_ARROW")] + public JoinDataComplete DpadLeft = new JoinDataComplete( + new JoinData + { + JoinNumber = 47, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "LEFT_ARROW", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RIGHT_ARROW")] + public JoinDataComplete DpadRight = new JoinDataComplete( + new JoinData + { + JoinNumber = 48, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "RIGHT_ARROW", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SELECT")] + public JoinDataComplete DpadSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 49, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SELECT", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("OPTIONS")] + public JoinDataComplete Options = new JoinDataComplete( + new JoinData + { + JoinNumber = 50, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "OPTIONS", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RETURN")] + public JoinDataComplete Return = new JoinDataComplete( + new JoinData + { + JoinNumber = 51, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "RETURN", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DVR")] + public JoinDataComplete Dvr = new JoinDataComplete( + new JoinData + { + JoinNumber = 52, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "DVR", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("ON_DEMAND")] + public JoinDataComplete OnDemand = new JoinDataComplete( + new JoinData + { + JoinNumber = 53, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "ON_DEMAND", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("PAGE_UP")] + public JoinDataComplete PageUp = new JoinDataComplete( + new JoinData + { + JoinNumber = 54, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "PAGE_UP", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("PAGE_DOWN")] + public JoinDataComplete PageDown = new JoinDataComplete( + new JoinData + { + JoinNumber = 55, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "PAGE_DOWN", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("F_SRCH")] + public JoinDataComplete ForwardSearch = new JoinDataComplete( + new JoinData + { + JoinNumber = 56, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "F_SRCH", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("R_SRCH")] + public JoinDataComplete ReverseSearch = new JoinDataComplete( + new JoinData + { + JoinNumber = 57, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "R_SRCH", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("TRACK+")] + public JoinDataComplete TrackPlus = new JoinDataComplete( + new JoinData + { + JoinNumber = 58, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "TRACK+", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("TRACK-")] + public JoinDataComplete TrackMinus = new JoinDataComplete( + new JoinData + { + JoinNumber = 59, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "TRACK-", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("A")] + public JoinDataComplete KpA = new JoinDataComplete( + new JoinData + { + JoinNumber = 61, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "A", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("B")] + public JoinDataComplete KpB = new JoinDataComplete( + new JoinData + { + JoinNumber = 62, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "B", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("C")] + public JoinDataComplete KpC = new JoinDataComplete( + new JoinData + { + JoinNumber = 63, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "C", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("D")] + public JoinDataComplete KpD = new JoinDataComplete( + new JoinData + { + JoinNumber = 64, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "D", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("RED")] + public JoinDataComplete KpRed = new JoinDataComplete( + new JoinData + { + JoinNumber = 65, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "RED", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("GREEN")] + public JoinDataComplete KpGreen = new JoinDataComplete( + new JoinData + { + JoinNumber = 66, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "GREEN", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("YELLOW")] + public JoinDataComplete KpYellow = new JoinDataComplete( + new JoinData + { + JoinNumber = 67, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "YELLOW", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("BLUE")] + public JoinDataComplete KpBlue = new JoinDataComplete( + new JoinData + { + JoinNumber = 68, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "BLUE", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + public GenericIrControllerJoinMap(uint joinStart) + : base(joinStart, typeof(GenericIrControllerJoinMap)) + { + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs new file mode 100644 index 00000000..3f2901c9 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs @@ -0,0 +1,190 @@ +using System; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Bridges +{ + public class HdPsXxxControllerJoinMap : JoinMapBaseAdvanced + { + + #region Digital + + [JoinName("EnableAutoRoute")] + public JoinDataComplete EnableAutoRoute = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Enable Automatic Routing on Xx1 Switchers", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("InputSync")] + public JoinDataComplete InputSync = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Input Sync", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("EnableInputHdcp")] + public JoinDataComplete EnableInputHdcp = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Enable Input Hdcp", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("DisableInputHdcp")] + public JoinDataComplete DisableInputHdcp = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Disnable Input Hdcp", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 30, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device Onlne", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + + #region Analog + + [JoinName("OutputRoute")] + public JoinDataComplete OutputRoute = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 2 + }, + new JoinMetadata + { + Description = "Device Output Route Set/Get", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + #region Serial + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("InputName")] + public JoinDataComplete InputName = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Input Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("OutputName")] + public JoinDataComplete OutputName = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 2 + }, + new JoinMetadata + { + Description = "Device Output Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("OutputRoutedName")] + public JoinDataComplete OutputRoutedName = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 2 + }, + new JoinMetadata + { + Description = "Device Output Route Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + #endregion + + /// + /// Constructor to use when instantiating this join map without inheriting from it + /// + /// Join this join map will start at + public HdPsXxxControllerJoinMap(uint joinStart) + : this(joinStart, typeof(HdPsXxxControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected HdPsXxxControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs index 2ac56ff1..0c2e9ed9 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs @@ -10,7 +10,7 @@ namespace PepperDash.Essentials.Core.Bridges [JoinName("Online")] public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + new JoinMetadata { Description = "Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); [JoinName("OutletCount")] public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs index ffcd5777..9adabfce 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs @@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Core.Bridges [JoinName("ProgramOffsetJoin")] public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 5 }, new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); - + [JoinName("ProgramStart")] public JoinDataComplete ProgramStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, new JoinMetadata { Description = "Processor Program Start / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); @@ -132,6 +132,23 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete DhcpStatus = new JoinDataComplete(new JoinData { JoinNumber = 86, JoinSpan = 1 }, new JoinMetadata { Description = "Processor Ethernet Dhcp Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ProcessorRebot")] + public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Reboot processor", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("IsAppliance")] + public JoinDataComplete IsAppliance = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Is appliance Fb", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("IsServer")] + public JoinDataComplete IsServer = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Is server Fb", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("ProgramReset")] + public JoinDataComplete ProgramReset = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Resets the program", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + /// /// Constructor to use when instantiating this Join Map without inheriting from it /// diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs b/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs index 892caa92..8c132a1b 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs @@ -83,6 +83,15 @@ namespace PepperDash.Essentials.Core } case eControlMethod.Telnet: break; + case eControlMethod.SecureTcpIp: + { + var secureTcp = new GenericSecureTcpIpClient(deviceConfig.Key + "-secureTcp", c.Address, c.Port, c.BufferSize); + secureTcp.AutoReconnect = c.AutoReconnect; + if (secureTcp.AutoReconnect) + secureTcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; + comm = secureTcp; + break; + } default: break; } @@ -117,41 +126,54 @@ namespace PepperDash.Essentials.Core /// public static ICec GetCecPort(ControlPropertiesConfig config) { - var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); + try + { + var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); - if (dev != null) - { - if (!String.IsNullOrEmpty(config.ControlPortName)) - { + Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null + ? "is not valid, failed to get cec port" + : "found in device manager, attempting to get cec port"); - var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; + if (dev == null) + return null; - if (inputPort != null) - { - if (inputPort.Port is ICec) - return inputPort.Port as ICec; - } + if (String.IsNullOrEmpty(config.ControlPortName)) + { + Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); + return null; + } - var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; - if (outputPort != null) - { - if (outputPort.Port is ICec) - return outputPort.Port as ICec; - } + var inputsOutputs = dev as IRoutingInputsOutputs; + if (inputsOutputs == null) + { + Debug.Console(0, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'", + config.ControlPortDevKey, config.ControlPortName); - else - Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", - config.ControlPortDevKey, config.ControlPortName); - } - else - { - Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); - } - } - Debug.Console(0, "GetCecPort: Device '{0}' is not a valid device.", config.ControlPortDevKey); + return null; + } - return null; + var inputPort = inputsOutputs.InputPorts[config.ControlPortName]; + if (inputPort != null && inputPort.Port is ICec) + return inputPort.Port as ICec; + + + var outputPort = inputsOutputs.OutputPorts[config.ControlPortName]; + if (outputPort != null && outputPort.Port is ICec) + return outputPort.Port as ICec; + } + catch (Exception ex) + { + Debug.Console(1, "GetCecPort Exception Message: {0}", ex.Message); + Debug.Console(2, "GetCecPort Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(0, "GetCecPort Exception InnerException: {0}", ex.InnerException); + } + + Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'", + config.ControlPortDevKey, config.ControlPortName); + + return null; } /// diff --git a/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs b/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs index b682af71..4d99edc0 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs @@ -226,12 +226,18 @@ namespace PepperDash.Essentials.Core /// public class IrOutPortConfig { + [JsonProperty("port")] public IROutputPort Port { get; set; } + + [JsonProperty("fileName")] public string FileName { get; set; } + [JsonProperty("useBridgeJoinMap")] + public bool UseBridgeJoinMap { get; set; } + public IrOutPortConfig() { - FileName = ""; + FileName = ""; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs b/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs new file mode 100644 index 00000000..04e697c9 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using PepperDash.Core; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.DeviceInfo +{ + public static class NetworkDeviceHelpers + { + /// + /// Event raised when ArpTable changes + /// + public static event ArpTableEventHandler ArpTableUpdated; + + /// + /// Delegate called by ArpTableUpdated + /// + /// contains the entire ARP table and a bool to note if there was an error in retrieving the data + public delegate void ArpTableEventHandler(ArpTableEventArgs args); + + private static readonly char NewLineSplitter = CrestronEnvironment.NewLine.ToCharArray().First(); + private static readonly string NewLine = CrestronEnvironment.NewLine; + + private static readonly CCriticalSection Lock = new CCriticalSection(); + + /// + /// Last resolved ARP table - it is recommended to refresh the arp before using this. + /// + public static List ArpTable { get; private set; } + + /// + /// Force recheck of ARP table + /// + public static void RefreshArp() + { + var error = false; + try + { + Lock.Enter(); + var consoleResponse = string.Empty; + if (!CrestronConsole.SendControlSystemCommand("showarptable", ref consoleResponse)) return; + if (string.IsNullOrEmpty(consoleResponse)) + { + error = true; + return; + } + ArpTable.Clear(); + + Debug.Console(2, "ConsoleResponse of 'showarptable' : {0}{1}", NewLine, consoleResponse); + + var myLines = + consoleResponse.Split(NewLineSplitter) + .ToList() + .Where(o => (o.Contains(':') && !o.Contains("Type", StringComparison.OrdinalIgnoreCase))) + .ToList(); + foreach (var line in myLines) + { + var item = line; + var seperator = item.Contains('\t') ? '\t' : ' '; + var dataPoints = item.Split(seperator); + if (dataPoints == null || dataPoints.Length < 2) continue; + var ipAddress = SanitizeIpAddress(dataPoints.First().TrimAll()); + var macAddress = dataPoints.Last(); + ArpTable.Add(new ArpEntry(ipAddress, macAddress)); + } + } + catch (Exception ex) + { + Debug.Console(0, "Exception in \"RefreshArp\" : {0}", ex.Message); + error = true; + } + finally + { + Lock.Leave(); + OnArpTableUpdated(new ArpTableEventArgs(ArpTable, error)); + } + } + + + private static void OnArpTableUpdated(ArpTableEventArgs args) + { + if (args == null) return; + var handler = ArpTableUpdated; + if (handler == null) return; + handler.Invoke(args); + } + + static NetworkDeviceHelpers() + { + ArpTable = new List(); + } + + /// + /// Removes leading zeros, leading whitespace, and trailing whitespace from an IPAddress string + /// + /// Ip Address to Santitize + /// Sanitized Ip Address + public static string SanitizeIpAddress(string ipAddressIn) + { + try + { + var ipAddress = IPAddress.Parse(ipAddressIn.TrimStart('0')); + return ipAddress.ToString(); + } + catch (Exception ex) + { + Debug.Console(0, "Unable to Santize Ip : {0}", ex.Message); + return ipAddressIn; + } + } + + /// + /// Resolves a hostname by IP Address using DNS + /// + /// IP Address to resolve from + /// Resolved Hostname - on failure to determine hostname, will return IP Address + public static string ResolveHostnameFromIp(string ipAddress) + { + try + { + var santitizedIp = SanitizeIpAddress(ipAddress); + var hostEntry = Dns.GetHostEntry(santitizedIp); + return hostEntry == null ? ipAddress : hostEntry.HostName; + } + catch (Exception ex) + { + Debug.Console(0, "Exception Resolving Hostname from IP Address : {0}", ex.Message); + return ipAddress; + } + } + + /// + /// Resolves an IP Address by hostname using DNS + /// + /// Hostname to resolve from + /// Resolved IP Address - on a failure to determine IP Address, will return hostname + public static string ResolveIpFromHostname(string hostName) + { + try + { + var hostEntry = Dns.GetHostEntry(hostName); + return hostEntry == null ? hostName : hostEntry.AddressList.First().ToString(); + } + catch (Exception ex) + { + Debug.Console(0, "Exception Resolving IP Address from Hostname : {0}", ex.Message); + return hostName; + } + } + + } + + /// + /// Object to hold data about an arp entry + /// + public class ArpEntry + { + public readonly IPAddress IpAddress; + public readonly string MacAddress; + + /// + /// Constructs new ArpEntry object + /// + /// string formatted as ipv4 address + /// mac address string - format is unimportant + public ArpEntry(string ipAddress, string macAddress) + { + if (string.IsNullOrEmpty(ipAddress)) + { + throw new ArgumentException("\"ipAddress\" cannot be null or empty"); + } + if (string.IsNullOrEmpty(macAddress)) + { + throw new ArgumentException("\"macAddress\" cannot be null or empty"); + } + IpAddress = IPAddress.Parse(ipAddress.TrimStart().TrimStart('0').TrimEnd()); + MacAddress = macAddress; + } + } + + /// + /// Arguments passed by the ArpTableUpdated event + /// + public class ArpTableEventArgs : EventArgs + { + /// + /// The retrieved ARP Table + /// + public readonly List ArpTable; + /// + /// True if there was a problem retrieving the ARP Table + /// + public readonly bool Error; + + /// + /// Constructor for ArpTableEventArgs + /// + /// The entirety of the retrieved ARP table + /// True of an error was encountered updating the ARP table + public ArpTableEventArgs(List arpTable, bool error) + { + ArpTable = arpTable; + Error = error; + } + + /// + /// Constructor for ArpTableEventArgs - assumes no error encountered in retrieving ARP Table + /// + /// The entirety of the retrieved ARP table + public ArpTableEventArgs(List arpTable) + { + ArpTable = arpTable; + Error = false; + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs index 12b3b948..f0101c6c 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs @@ -379,30 +379,28 @@ namespace PepperDash.Essentials.Core /// Prints a list of routing inputs and outputs by device key. /// /// Device key from which to report data - public static void GetRoutingPorts(string s) - { - var device = GetDeviceForKey(s); + public static void GetRoutingPorts(string s) + { + var device = GetDeviceForKey(s); if (device == null) return; var inputPorts = ((device as IRoutingInputs) != null) ? (device as IRoutingInputs).InputPorts : null; var outputPorts = ((device as IRoutingOutputs) != null) ? (device as IRoutingOutputs).OutputPorts : null; - if (inputPorts != null) - { - Debug.Console(0, "Device {0} has {1} Input Ports:", s, inputPorts.Count); - foreach (var routingInputPort in inputPorts) - { - Debug.Console(0, "{0}", routingInputPort.Key); - } - } - if (outputPorts != null) - { - Debug.Console(0, "Device {0} has {1} Output Ports:", s, outputPorts.Count); - foreach (var routingOutputPort in outputPorts) - { - Debug.Console(0, "{0}", routingOutputPort.Key); - } - } - } + if (inputPorts != null) + { + CrestronConsole.ConsoleCommandResponse("Device {0} has {1} Input Ports:{2}", s, inputPorts.Count, CrestronEnvironment.NewLine); + foreach (var routingInputPort in inputPorts) + { + CrestronConsole.ConsoleCommandResponse("{0}{1}", routingInputPort.Key, CrestronEnvironment.NewLine); + } + } + if (outputPorts == null) return; + CrestronConsole.ConsoleCommandResponse("Device {0} has {1} Output Ports:{2}", s, outputPorts.Count, CrestronEnvironment.NewLine); + foreach (var routingOutputPort in outputPorts) + { + CrestronConsole.ConsoleCommandResponse("{0}{1}", routingOutputPort.Key, CrestronEnvironment.NewLine); + } + } /// /// Attempts to set the debug level of a device @@ -435,7 +433,7 @@ namespace PepperDash.Essentials.Core if (device == null) { - Debug.Console(0, "Unable to get device with key: {0}", deviceKey); + CrestronConsole.ConsoleCommandResponse("Unable to get device with key: {0}", deviceKey); return; } @@ -447,7 +445,7 @@ namespace PepperDash.Essentials.Core } catch { - Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both"); + CrestronConsole.ConsoleCommandResponse("Unable to convert setting value. Please use off/rx/tx/both"); return; } @@ -458,18 +456,18 @@ namespace PepperDash.Essentials.Core var min = Convert.ToUInt32(timeout); device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); - Debug.Console(0, "Device: '{0}' debug level set to {1} for {2} minutes", deviceKey, debugSetting, min); + CrestronConsole.ConsoleCommandResponse("Device: '{0}' debug level set to {1} for {2} minutes", deviceKey, debugSetting, min); } catch (Exception e) { - Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e); + CrestronConsole.ConsoleCommandResponse("Unable to convert minutes or settings value. Please use an integer value for minutes. Error: {0}", e); } } else { device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); - Debug.Console(0, "Device: '{0}' debug level set to {1} for default time (30 minutes)", deviceKey, debugSetting); + CrestronConsole.ConsoleCommandResponse("Device: '{0}' debug level set to {1} for default time (30 minutes)", deviceKey, debugSetting); } } diff --git a/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs b/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs index 3c35b686..178e0c30 100644 --- a/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs +++ b/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs @@ -2,12 +2,13 @@ using System; using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharpPro.DeviceSupport; using Full.Newtonsoft.Json; using PepperDash.Core; -using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; +using PepperDash_Essentials_Core.Bridges.JoinMaps; namespace PepperDash.Essentials.Core.Devices { @@ -21,12 +22,11 @@ namespace PepperDash.Essentials.Core.Devices private readonly IrOutputPortController _port; - public string[] IrCommands {get { return _port.IrFileCommands; }} + public string[] IrCommands {get { return _port.IrFileCommands; }} public GenericIrController(string key, string name, IrOutputPortController irPort) : base(key, name) { _port = irPort; - if (_port == null) { Debug.Console(0, this, Debug.ErrorLogLevel.Error, "IR Port is null, device will not function"); @@ -73,23 +73,65 @@ namespace PepperDash.Essentials.Core.Devices if (!string.IsNullOrEmpty(joinMapSerialized)) joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - for (uint i = 0; i < _port.IrFileCommands.Length; i++) - { - var cmd = _port.IrFileCommands[i]; - var joinData = new JoinDataComplete(new JoinData {JoinNumber = i, JoinSpan = 1}, - new JoinMetadata - { - Description = cmd, - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + if (_port.UseBridgeJoinMap) + { + Debug.Console(0, this, "Using new IR bridge join map"); - joinData.SetJoinOffset(joinStart); + var bridgeJoins = joinMap.Joins.Where((kv) => _port.IrFileCommands.Any(cmd => cmd == kv.Key)).ToDictionary(kv => kv.Key); + if (bridgeJoins == null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Failed to link new IR bridge join map"); + return; + } - joinMap.Joins.Add(cmd,joinData); + joinMap.Joins.Clear(); - trilist.SetBoolSigAction(joinData.JoinNumber, (b) => Press(cmd, b)); - } + foreach (var bridgeJoin in bridgeJoins) + { + var key = bridgeJoin.Key; + var joinDataKey = bridgeJoin.Value.Key; + var joinDataValue = bridgeJoin.Value.Value; + var joinNumber = bridgeJoin.Value.Value.JoinNumber; + + Debug.Console(2, this, @"bridgeJoin: Key-'{0}' +Value.Key-'{1}' +Value.JoinNumber-'{2}' +Value.Metadata.Description-'{3}'", + key, + joinDataKey, + joinNumber, + joinDataValue.Metadata.Description); + + + joinMap.Joins.Add(key, joinDataValue); + + trilist.SetBoolSigAction(joinNumber, (b) => Press(key, b)); + } + } + else + { + Debug.Console(0, this, "Using legacy IR join mapping based on available IR commands"); + + joinMap.Joins.Clear(); + + for (uint i = 0; i < _port.IrFileCommands.Length; i++) + { + var cmd = _port.IrFileCommands[i]; + var joinData = new JoinDataComplete(new JoinData { JoinNumber = i, JoinSpan = 1 }, + new JoinMetadata + { + Description = cmd, + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + joinData.SetJoinOffset(joinStart); + + joinMap.Joins.Add(cmd, joinData); + + trilist.SetBoolSigAction(joinData.JoinNumber, (b) => Press(cmd, b)); + } + } joinMap.PrintJoinMapInfo(); @@ -111,13 +153,6 @@ namespace PepperDash.Essentials.Core.Devices } } - public sealed class GenericIrControllerJoinMap : JoinMapBaseAdvanced - { - public GenericIrControllerJoinMap(uint joinStart) : base(joinStart) - { - } - } - public class GenericIrControllerFactory : EssentialsDeviceFactory { public GenericIrControllerFactory() diff --git a/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs index c8a5df39..c8033b92 100644 --- a/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs @@ -72,6 +72,10 @@ namespace PepperDash.Essentials.Core { IBasicVolumeControls CurrentVolumeControls { get; } event EventHandler CurrentVolumeDeviceChange; + + void SetDefaultLevels(); + + bool ZeroVolumeWhenSwtichingVolumeDevices { get; } } diff --git a/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs b/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs index d3d6e19e..6ffee074 100644 --- a/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs +++ b/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs @@ -31,6 +31,8 @@ namespace PepperDash.Essentials.Core public string[] IrFileCommands { get { return IrPort.AvailableStandardIRCmds(IrPortUid); } } + public bool UseBridgeJoinMap { get; private set; } + /// /// Constructor for IrDevice base class. If a null port is provided, this class will /// still function without trying to talk to a port. @@ -55,9 +57,10 @@ namespace PepperDash.Essentials.Core : base(key) { DriverLoaded = new BoolFeedback(() => DriverIsLoaded); + UseBridgeJoinMap = config.Properties["control"].Value("useBridgeJoinMap"); AddPostActivationAction(() => { - IrPort = postActivationFunc(config); + IrPort = postActivationFunc(config); if (IrPort == null) { @@ -69,8 +72,8 @@ namespace PepperDash.Essentials.Core Debug.Console(1, "*************Attempting to load IR file: {0}***************", filePath); LoadDriver(filePath); - - PrintAvailableCommands(); + + PrintAvailableCommands(); }); } diff --git a/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs index 0f3b3fbf..94aa71ac 100644 --- a/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -8,6 +9,7 @@ namespace PepperDash_Essentials_Core.Devices /// /// Interface for any device that is able to control it'spower and has a configurable reboot time /// + [Obsolete("PepperDash_Essentials_Core.Devices is Deprecated - use PepperDash.Essentials.Core")] public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback { /// @@ -24,6 +26,7 @@ namespace PepperDash_Essentials_Core.Devices /// /// Interface for any device that contains a collection of IHasPowerReboot Devices /// + [Obsolete("PepperDash_Essentials_Core.Devices is Deprecated - use PepperDash.Essentials.Core")] public interface IHasControlledPowerOutlets : IKeyName { /// diff --git a/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs new file mode 100644 index 00000000..1fc6672a --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs @@ -0,0 +1,87 @@ +using Crestron.SimplSharp; +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + /// + /// Interface for any device that has a battery that can be monitored + /// + public interface IHasBatteryStats : IKeyName + { + int BatteryPercentage { get; } + int BatteryCautionThresholdPercentage { get; } + int BatteryWarningThresholdPercentage { get; } + BoolFeedback BatteryIsWarningFeedback { get; } + BoolFeedback BatteryIsCautionFeedback { get; } + BoolFeedback BatteryIsOkFeedback { get; } + IntFeedback BatteryPercentageFeedback { get; } + } + + /// + /// Interface for any device that has a battery that can be monitored and the ability to charge and discharge + /// + public interface IHasBatteryCharging : IHasBatteryStats + { + BoolFeedback BatteryIsCharging { get; } + } + + /// + /// Interface for any device that has multiple batteries that can be monitored + /// + public interface IHasBatteries : IKeyName + { + ReadOnlyDictionary Batteries { get; } + } + + public interface IHasBatteryStatsExtended : IHasBatteryStats + { + int InputVoltage { get; } + int OutputVoltage { get; } + int InptuCurrent { get; } + int OutputCurrent { get; } + + IntFeedback InputVoltageFeedback { get; } + IntFeedback OutputVoltageFeedback { get; } + IntFeedback InputCurrentFeedback { get; } + IntFeedback OutputCurrentFeedback { get; } + } + + /// + /// Interface for any device that is able to control its power, has a configurable reboot time, and has batteries that can be monitored + /// + public interface IHasPowerCycleWithBattery : IHasPowerCycle, IHasBatteryStats + { + + } + + /// + /// Interface for any device that is able to control it's power and has a configurable reboot time + /// + public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback + { + /// + /// Delay between power off and power on for reboot + /// + int PowerCycleTimeMs { get; } + + /// + /// Reboot outlet + /// + void PowerCycle(); + } + + /// + /// Interface for any device that contains a collection of IHasPowerReboot Devices + /// + public interface IHasControlledPowerOutlets : IKeyName + { + /// + /// Collection of IPduOutlets + /// + ReadOnlyDictionary PduOutlets { get; } + + } + + + +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs b/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs index 39501387..7bf8d5a5 100644 --- a/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs +++ b/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,17 +9,70 @@ namespace PepperDash.Essentials.Core { public static class StringExtensions { + /// + /// Returns null if a string is empty, otherwise returns the string + /// + /// string input + /// null if the string is emtpy, otherwise returns the string public static string NullIfEmpty(this string s) { return string.IsNullOrEmpty(s) ? null : s; } + + /// + /// Returns null if a string is empty or made of only whitespace characters, otherwise returns the string + /// + /// string input + /// null if the string is wempty or made of only whitespace characters, otherwise returns the string public static string NullIfWhiteSpace(this string s) { return string.IsNullOrEmpty(s.Trim()) ? null : s; } + + /// + /// Returns a replacement string if the input string is empty or made of only whitespace characters, otherwise returns the input string + /// + /// input string + /// string to replace with if input string is empty or whitespace + /// returns newString if s is null, emtpy, or made of whitespace characters, otherwise returns s public static string ReplaceIfNullOrEmpty(this string s, string newString) { return string.IsNullOrEmpty(s) ? newString : s; } + + /// + /// Overload for Contains that allows setting an explicit String Comparison + /// + /// Source String + /// String to check in Source String + /// Comparison parameters + /// true of string contains "toCheck" + public static bool Contains(this string source, string toCheck, StringComparison comp) + { + if (string.IsNullOrEmpty(source)) return false; + return source.IndexOf(toCheck, comp) >= 0; + } + + /// + /// Performs TrimStart() and TrimEnd() on source string + /// + /// String to Trim + /// Trimmed String + public static string TrimAll(this string source) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart().TrimEnd(); + } + + /// + /// Performs TrimStart(chars char[]) and TrimEnd(chars char[]) on source string. + /// + /// String to Trim + /// Char Array to trim from string + /// Trimmed String + public static string TrimAll(this string source, char[] chars) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart(chars).TrimEnd(chars); + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs index f1c77e74..0a7c742d 100644 --- a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs @@ -165,33 +165,26 @@ namespace PepperDash.Essentials.Core /// /// Prints the type names and associated metadata from the FactoryMethods collection. /// - /// + /// public static void GetDeviceFactoryTypes(string filter) { - Dictionary types = new Dictionary(); + var types = !string.IsNullOrEmpty(filter) + ? FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value) + : FactoryMethods; - if (!string.IsNullOrEmpty(filter)) - { - types = FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value); - } - else - { - types = FactoryMethods; - } - - Debug.Console(0, "Device Types:"); + CrestronConsole.ConsoleCommandResponse("Device Types:"); foreach (var type in types.OrderBy(t => t.Key)) { var description = type.Value.Description; var cType = "Not Specified by Plugin"; - if(type.Value.CType != null) + if (type.Value.CType != null) { cType = type.Value.CType.FullName; } - Debug.Console(0, + CrestronConsole.ConsoleCommandResponse( @"Type: '{0}' CType: '{1}' Description: {2}", type.Key, cType, description); diff --git a/src/PepperDash.Essentials.Core/File/FileIO.cs b/src/PepperDash.Essentials.Core/File/FileIO.cs index 51d64230..49b70a0c 100644 --- a/src/PepperDash.Essentials.Core/File/FileIO.cs +++ b/src/PepperDash.Essentials.Core/File/FileIO.cs @@ -21,35 +21,37 @@ namespace PepperDash.Essentials.Core /// /// /// - public static FileInfo[] GetFiles(string fileName) - { - DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fileName)); - var files = dirInfo.GetFiles(Path.GetFileName(fileName)); - Debug.Console(0, "FileIO found: {0}, {1}", files.Count(), fileName); - if (files.Count() > 0) - { - return files; - } - else - { - return null; - } - } + public static FileInfo[] GetFiles(string fileName) + { + string fullFilePath = Global.FilePathPrefix + fileName; + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath)); + var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath)); + Debug.Console(0, "FileIO found: {0}, {1}", files.Count(), fullFilePath); + if (files.Count() > 0) + { + return files; + } + else + { + return null; + } + } - public static FileInfo GetFile(string fileName) - { - DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fileName)); - var files = dirInfo.GetFiles(Path.GetFileName(fileName)); - Debug.Console(0, "FileIO found: {0}, {1}", files.Count(), fileName); - if (files.Count() > 0) - { - return files.FirstOrDefault(); - } - else - { - return null; - } - } + public static FileInfo GetFile(string fileName) + { + string fullFilePath = Global.FilePathPrefix + fileName; + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath)); + var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath)); + Debug.Console(0, "FileIO found: {0}, {1}", files.Count(), fullFilePath); + if (files.Count() > 0) + { + return files.FirstOrDefault(); + } + else + { + return null; + } + } /// @@ -81,7 +83,7 @@ namespace PepperDash.Essentials.Core { if (fileLock.TryEnter()) { - DirectoryInfo dirInfo = new DirectoryInfo(file.Name); + DirectoryInfo dirInfo = new DirectoryInfo(file.DirectoryName); Debug.Console(2, "FileIO Getting Data {0}", file.FullName); if (File.Exists(file.FullName)) @@ -202,7 +204,7 @@ namespace PepperDash.Essentials.Core public static void WriteDataToFile(string data, string filePath) { Thread _WriteFileThread; - _WriteFileThread = new Thread((O) => _WriteFileMethod(data, filePath), null, Thread.eThreadStartOptions.CreateSuspended); + _WriteFileThread = new Thread((O) => _WriteFileMethod(data, Global.FilePathPrefix + "/" + filePath), null, Thread.eThreadStartOptions.CreateSuspended); _WriteFileThread.Priority = Thread.eThreadPriority.LowestPriority; _WriteFileThread.Start(); Debug.Console(0, Debug.ErrorLogLevel.Notice, "New WriteFile Thread"); @@ -217,7 +219,8 @@ namespace PepperDash.Essentials.Core { if (fileLock.TryEnter()) { - using (StreamWriter sw = new StreamWriter(filePath)) + + using (StreamWriter sw = new StreamWriter(filePath)) { sw.Write(data); sw.Flush(); diff --git a/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs index f3827d0a..597a31fd 100644 --- a/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs +++ b/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs @@ -150,15 +150,20 @@ namespace PepperDash.Essentials.Core.Fusion ReadGuidFile(guidFilePath); } - if (Room.RoomOccupancy != null) + var occupancyRoom = Room as IRoomOccupancy; + + if (occupancyRoom != null) { - if (Room.OccupancyStatusProviderIsRemote) + if (occupancyRoom.RoomOccupancy != null) { - SetUpRemoteOccupancy(); - } - else - { - SetUpLocalOccupancy(); + if (occupancyRoom.OccupancyStatusProviderIsRemote) + { + SetUpRemoteOccupancy(); + } + else + { + SetUpLocalOccupancy(); + } } } @@ -1525,10 +1530,15 @@ namespace PepperDash.Essentials.Core.Fusion // Tie to method on occupancy object //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b)); + var occRoom = Room as IRoomOccupancy; + if (occRoom != null) + { + occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig); + occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; + } RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString); - Room.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig); - Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; + RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig); //} diff --git a/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs b/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs index e16640ce..6dff477d 100644 --- a/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs +++ b/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs @@ -2,10 +2,8 @@ using System; using System.Collections.Generic; -using System.Data; using System.Globalization; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using Crestron.SimplSharp.Reflection; using Crestron.SimplSharp.CrestronIO; @@ -105,22 +103,22 @@ namespace PepperDash.Essentials.Core /// public void PrintJoinMapInfo() { - Debug.Console(0, "{0}:\n", GetType().Name); + CrestronConsole.ConsoleCommandResponse("{0}:\n", GetType().Name); // Get the joins of each type and print them - Debug.Console(0, "Digitals:"); + CrestronConsole.ConsoleCommandResponse("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); + CrestronConsole.ConsoleCommandResponse("Found {0} Digital Joins", digitals.Count); PrintJoinList(GetSortedJoins(digitals)); - Debug.Console(0, "Analogs:"); + CrestronConsole.ConsoleCommandResponse("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); + CrestronConsole.ConsoleCommandResponse("Found {0} Analog Joins", analogs.Count); PrintJoinList(GetSortedJoins(analogs)); - Debug.Console(0, "Serials:"); + CrestronConsole.ConsoleCommandResponse("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); + CrestronConsole.ConsoleCommandResponse("Found {0} Serial Joins", serials.Count); PrintJoinList(GetSortedJoins(serials)); } @@ -143,7 +141,7 @@ namespace PepperDash.Essentials.Core { foreach (var join in joins) { - Debug.Console(0, + CrestronConsole.ConsoleCommandResponse( @"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'", join.Value.JoinNumber, join.Value.Label, @@ -238,25 +236,45 @@ namespace PepperDash.Essentials.Core /// public void PrintJoinMapInfo() { - Debug.Console(0, "{0}:\n", GetType().Name); + var sb = JoinmapStringBuilder(); + + CrestronConsole.ConsoleCommandResponse(sb.ToString()); + } + + private StringBuilder JoinmapStringBuilder() + { + var sb = new StringBuilder(); // 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)); + sb.AppendLine(String.Format("# {0}", GetType().Name)); + sb.AppendLine(); + sb.AppendLine("## Digitals"); + sb.AppendLine(); + // Get the joins of each type and print them + var digitals = + Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital) + .ToDictionary(j => j.Key, j => j.Value); + var digitalSb = AppendJoinList(GetSortedJoins(digitals)); + digitalSb.AppendLine("## Analogs"); + digitalSb.AppendLine(); - Debug.Console(0, "Analogs:"); - var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Analog Joins", analogs.Count); - PrintJoinList(GetSortedJoins(analogs)); + var analogs = + Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog) + .ToDictionary(j => j.Key, j => j.Value); + var analogSb = AppendJoinList(GetSortedJoins(analogs)); + analogSb.AppendLine("## Serials"); + analogSb.AppendLine(); - Debug.Console(0, "Serials:"); - var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Serial Joins", serials.Count); - PrintJoinList(GetSortedJoins(serials)); + var serials = + Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial) + .ToDictionary(j => j.Key, j => j.Value); + var serialSb = AppendJoinList(GetSortedJoins(serials)); + sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length); + sb.Append(digitalSb).Append(analogSb).Append(serialSb); + return sb; } + /// /// Prints the join information to console /// @@ -264,37 +282,11 @@ namespace PepperDash.Essentials.Core { var pluginType = GetType().Name; - Debug.Console(0, "{0}:\n", pluginType); + CrestronConsole.ConsoleCommandResponse("{0}:\n", pluginType); - var sb = new StringBuilder(); - sb.AppendLine(String.Format("# {0}", GetType().Name)); - sb.AppendLine(String.Format("Generated from '{0}' on bridge '{1}'", deviceKey, bridgeKey)); - sb.AppendLine(); - sb.AppendLine("## Digitals"); - // Get the joins of each type and print them - var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Digital Joins", digitals.Count); - var digitalSb = AppendJoinList(GetSortedJoins(digitals)); - digitalSb.AppendLine("## Analogs"); - digitalSb.AppendLine(); - Debug.Console(0, "Analogs:"); - var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Analog Joins", analogs.Count); - var analogSb = AppendJoinList(GetSortedJoins(analogs)); - analogSb.AppendLine("## Serials"); - analogSb.AppendLine(); - - Debug.Console(0, "Serials:"); - var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value); - Debug.Console(2, "Found {0} Serial Joins", serials.Count); - var serialSb = AppendJoinList(GetSortedJoins(serials)); - - sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length); - sb.Append(digitalSb).Append(analogSb).Append(serialSb); - - WriteJoinmapMarkdown(sb, pluginType, bridgeKey, deviceKey); + WriteJoinmapMarkdown(JoinmapStringBuilder(), pluginType, bridgeKey, deviceKey); } @@ -305,7 +297,7 @@ namespace PepperDash.Essentials.Core using (var sw = new StreamWriter(fileName)) { sw.WriteLine(stringBuilder.ToString()); - Debug.Console(0, "Joinmap Readme generated and written to {0}", fileName); + CrestronConsole.ConsoleCommandResponse("Joinmap Readme generated and written to {0}", fileName); } } @@ -315,7 +307,7 @@ namespace PepperDash.Essentials.Core /// /// /// - List> GetSortedJoins(Dictionary joins) + static List> GetSortedJoins(Dictionary joins) { var sortedJoins = joins.ToList(); @@ -324,20 +316,6 @@ namespace PepperDash.Essentials.Core return sortedJoins; } - void PrintJoinList(List> joins) - { - foreach (var join in joins) - { - Debug.Console(0, - @"Join Number: {0} | JoinSpan: '{1}' | JoinName: {2} | Description: '{3}' | Type: '{4}' | Capabilities: '{5}'", - join.Value.JoinNumber, - join.Value.JoinSpan, - join.Key, - String.IsNullOrEmpty(join.Value.AttributeName) ? join.Value.Metadata.Label : join.Value.AttributeName, - join.Value.Metadata.JoinType.ToString(), - join.Value.Metadata.JoinCapabilities.ToString()); - } - } static StringBuilder AppendJoinList(List> joins) { @@ -380,16 +358,18 @@ namespace PepperDash.Essentials.Core { foreach (var customJoinData in joinData) { - var join = Joins[customJoinData.Key]; + JoinDataComplete join; + + if (!Joins.TryGetValue(customJoinData.Key, out join)) + { + Debug.Console(2, "No matching key found in join map for: '{0}'", customJoinData.Key); + continue; + } if (join != null) { join.SetCustomJoinData(customJoinData.Value); } - else - { - Debug.Console(2, "No matching key found in join map for: '{0}'", customJoinData.Key); - } } PrintJoinMapInfo(); diff --git a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs index b9d25127..1066637c 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs @@ -45,7 +45,20 @@ namespace PepperDash.Essentials.Core.Monitoring public StringFeedback UptimeFeedback { get; set; } public StringFeedback LastStartFeedback { get; set; } - public SystemMonitorController(string key) + public BoolFeedback IsApplianceFeedback { get; protected set; } + private bool _isApplianceFb + { + get { return CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance; } + } + + public BoolFeedback IsServerFeedback { get; protected set; } + private bool _isServerFb + { + get { return CrestronEnvironment.DevicePlatform == eDevicePlatform.Server; } + } + + + public SystemMonitorController(string key) : base(key) { Debug.Console(2, this, "Adding SystemMonitorController."); @@ -65,6 +78,9 @@ namespace PepperDash.Essentials.Core.Monitoring UptimeFeedback = new StringFeedback(() => _uptime); LastStartFeedback = new StringFeedback(()=> _lastStart); + IsApplianceFeedback = new BoolFeedback(() => _isApplianceFb); + IsServerFeedback = new BoolFeedback(() => _isServerFb); + ProgramStatusFeedbackCollection = new Dictionary(); foreach (var prog in SystemMonitor.ProgramCollection) @@ -125,6 +141,26 @@ namespace PepperDash.Essentials.Core.Monitoring _uptime = uptimeRaw.Substring(forIndex + 4); } + private static void ProcessorReboot() + { + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; + + var response = string.Empty; + CrestronConsole.SendControlSystemCommand("reboot", ref response); + } + + private static void ProgramReset(uint index) + { + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; + + if (index <= 0 || index > 10) return; + + var cmd = string.Format("progreset -p:{0}", index); + + var response = string.Empty; + CrestronConsole.SendControlSystemCommand(cmd, ref response); + } + private void CrestronEnvironmentOnEthernetEventHandler(EthernetEventArgs ethernetEventArgs) { if (ethernetEventArgs.EthernetEventType != eEthernetEventType.LinkUp) return; @@ -187,6 +223,9 @@ namespace PepperDash.Essentials.Core.Monitoring SerialNumberFeedback.FireUpdate(); ModelFeedback.FireUpdate(); + IsApplianceFeedback.FireUpdate(); + IsServerFeedback.FireUpdate(); + OnSystemMonitorPropertiesChanged(); } @@ -239,6 +278,11 @@ namespace PepperDash.Essentials.Core.Monitoring UptimeFeedback.LinkInputSig(trilist.StringInput[joinMap.Uptime.JoinNumber]); LastStartFeedback.LinkInputSig(trilist.StringInput[joinMap.LastBoot.JoinNumber]); + trilist.SetSigHeldAction(joinMap.ProcessorReboot.JoinNumber, 10000, ProcessorReboot); + + IsApplianceFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsAppliance.JoinNumber]); + IsServerFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsServer.JoinNumber]); + // iterate the program status feedback collection and map all the joins LinkProgramInfoJoins(this, trilist, joinMap); @@ -303,11 +347,13 @@ namespace PepperDash.Essentials.Core.Monitoring p.Value.AggregatedProgramInfoFeedback.LinkInputSig( trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]); + trilist.SetSigHeldAction(programSlotJoinStart + joinMap.ProgramReset.JoinNumber, 10000, () => ProgramReset(programNumber)); + programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinSpan; } - } + } - //// Sets the time zone + //// Sets the time zone //public void SetTimeZone(int timeZone) //{ // SystemMonitor.TimeZoneInformation.TimeZoneNumber = timeZone; @@ -519,11 +565,11 @@ namespace PepperDash.Essentials.Core.Monitoring ProgramUnregisteredFeedback = new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Unregister); ProgramUnregisteredFeedback.FireUpdate(); - - ProgramNameFeedback = new StringFeedback(() => ProgramInfo.ProgramFile); + + ProgramNameFeedback = new StringFeedback(() => ProgramInfo.ProgramFile); + CrestronDataBaseVersionFeedback = new StringFeedback(() => ProgramInfo.CrestronDb); + EnvironmentVersionFeedback = new StringFeedback(() => ProgramInfo.Environment); ProgramCompileTimeFeedback = new StringFeedback(() => ProgramInfo.CompileTime); - CrestronDataBaseVersionFeedback = new StringFeedback(() => ProgramInfo.CrestronDb); - EnvironmentVersionFeedback = new StringFeedback(() => ProgramInfo.Environment); AggregatedProgramInfoFeedback = new StringFeedback(() => JsonConvert.SerializeObject(ProgramInfo)); GetProgramInfo(); @@ -576,9 +622,9 @@ namespace PepperDash.Essentials.Core.Monitoring // Assume no valid program info. Constructing a new object will wipe all properties ProgramInfo = new ProgramInfo(Program.Number) { - OperatingState = Program.OperatingState, + OperatingState = Program.OperatingState, RegistrationState = Program.RegistrationState - }; + }; UpdateFeedbacks(); @@ -595,13 +641,20 @@ namespace PepperDash.Essentials.Core.Monitoring if (ProgramInfo.ProgramFile.Contains(".dll")) { - // SSP Program + // SSP Program ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ": ", "\n"); ProgramInfo.ApplicationName = ParseConsoleData(response, "Application Name", ": ", "\n"); ProgramInfo.ProgramTool = ParseConsoleData(response, "Program Tool", ": ", "\n"); ProgramInfo.MinFirmwareVersion = ParseConsoleData(response, "Min Firmware Version", ": ", "\n"); ProgramInfo.PlugInVersion = ParseConsoleData(response, "PlugInVersion", ": ", "\n"); + + ProgramInfo.ProgramFile += string.Format(" {0}.{1}.{2}", + ProgramInfo.CompilerRevisionInfo.Major, + ProgramInfo.CompilerRevisionInfo.Minor, + ProgramInfo.CompilerRevisionInfo.Build); + + ProgramInfo.Environment = ProgramInfo.ProgramTool; } else if (ProgramInfo.ProgramFile.Contains(".smw")) { @@ -692,6 +745,15 @@ namespace PepperDash.Essentials.Core.Monitoring [JsonProperty("compilerRevision")] public string CompilerRevision { get; set; } + [JsonIgnore] + public Version CompilerRevisionInfo + { + get + { + return new Version(CompilerRevision); + } + } + [JsonProperty("compileTime")] public string CompileTime { get; set; } @@ -732,7 +794,7 @@ namespace PepperDash.Essentials.Core.Monitoring ProgramFile = ""; FriendlyName = ""; CompilerRevision = ""; - CompileTime = ""; + CompileTime = ""; Include4Dat = ""; SystemName = ""; diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorController.cs index 7298e303..511eda66 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorController.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorController.cs @@ -87,18 +87,32 @@ namespace PepperDash.Essentials.Core { if (_partitionSensor.IsOnline == false) return; - Debug.Console(1, this, "Attempting to apply settings to sensor from config"); + // Default to enable + _partitionSensor.Enable.BoolValue = true; - if (PropertiesConfig.Sensitivity != null) - { - Debug.Console(1, this, "Sensitivity found, attempting to set value '{0}' from config", - PropertiesConfig.Sensitivity); - _partitionSensor.Sensitivity.UShortValue = (ushort) PropertiesConfig.Sensitivity; - } - else - { - Debug.Console(1, this, "Sensitivity null, no value specified in config"); - } + Debug.Console(1, this, "Attempting to apply settings to sensor from config"); + + if (PropertiesConfig.Sensitivity != null) + { + Debug.Console(1, this, "Sensitivity found, attempting to set value '{0}' from config", + PropertiesConfig.Sensitivity); + _partitionSensor.Sensitivity.UShortValue = (ushort)PropertiesConfig.Sensitivity; + } + else + { + Debug.Console(1, this, "Sensitivity null, no value specified in config"); + } + + if (PropertiesConfig.Enable != null) + { + Debug.Console(1, this, "Enable found, attempting to set value '{0}' from config", + PropertiesConfig.Enable); + _partitionSensor.Enable.BoolValue = (bool)PropertiesConfig.Enable; + } + else + { + Debug.Console(1, this, "Enable null, no value specified in config"); + } } diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs b/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs index 635b8962..03611dd2 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs @@ -18,6 +18,9 @@ namespace PepperDash_Essentials_Core.PartitionSensor /// The sensitivity range shall be between 1(lowest) to 10 (highest). /// [JsonProperty("sensitivity")] - public ushort? Sensitivity { get; set; } + public ushort? Sensitivity { get; set; } + + [JsonProperty("enable")] + public bool? Enable { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/PepperDash_Essentials_Core.csproj b/src/PepperDash.Essentials.Core/PepperDash_Essentials_Core.csproj index 6020fbac..bd727697 100644 --- a/src/PepperDash.Essentials.Core/PepperDash_Essentials_Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash_Essentials_Core.csproj @@ -83,7 +83,7 @@ ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll @@ -94,7 +94,7 @@ False - ..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCWSHelperInterface.dll + ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCWSHelperInterface.dll False @@ -127,6 +127,8 @@ + + @@ -200,6 +202,8 @@ + + @@ -417,12 +421,6 @@ - - - {E51D7C84-4906-486C-B2BA-EEB3B4E9731B} - PepperDash_Essentials_Interfaces - - diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index 9da843b8..dcc492df 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -194,13 +194,13 @@ namespace PepperDash.Essentials /// public static void ReportAssemblyVersions(string command) { - Debug.Console(0, "Loaded Assemblies:"); + + CrestronConsole.ConsoleCommandResponse("Loaded Assemblies:" + CrestronEnvironment.NewLine); foreach (var assembly in LoadedAssemblies) { - Debug.Console(0, "{0} Version: {1}", assembly.Name, assembly.Version); + CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version); } } - /// /// Moves any .dll assemblies not already loaded from the plugins folder to loadedPlugins folder /// diff --git a/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs b/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs index e46e93cb..c3bc0ca2 100644 --- a/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs +++ b/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs @@ -40,7 +40,7 @@ namespace PepperDash.Essentials.Core ScheduledEventGroup FeatureEventGroup; - public IEssentialsRoom Room { get; private set; } + public IRoomOccupancy Room { get; private set; } private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; @@ -86,7 +86,7 @@ namespace PepperDash.Essentials.Core /// void SetUpDevice() { - Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IEssentialsRoom; + Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IRoomOccupancy; if (Room != null) { @@ -237,12 +237,23 @@ namespace PepperDash.Essentials.Core if (FeatureEnabled) { - // Check room power state first - if (!Room.OnFeedback.BoolValue) - { - Debug.Console(1, this, "Powering Room on to default source"); - Room.RunDefaultPresentRoute(); + var essentialsRoom = Room as IEssentialsRoom; + + if (essentialsRoom != null) { + if (!essentialsRoom.OnFeedback.BoolValue) + { + Debug.Console(1, this, "Powering Room on to default source"); + + var defaultRouteRoom = Room as IRunDefaultPresentRoute; + + if (defaultRouteRoom != null) + { + defaultRouteRoom.RunDefaultPresentRoute(); + } + } } + // Check room power state first + } } } diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs index 72bf9060..cf0aa1f1 100644 --- a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs +++ b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs @@ -37,7 +37,7 @@ namespace PepperDash.Essentials.Core public BoolFeedback IsWarmingUpFeedback { get; private set; } public BoolFeedback IsCoolingDownFeedback { get; private set; } - public IOccupancyStatusProvider RoomOccupancy { get; private set; } + public IOccupancyStatusProvider RoomOccupancy { get; protected set; } public bool OccupancyStatusProviderIsRemote { get; private set; } diff --git a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs index 2273690f..9a70f980 100644 --- a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs +++ b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs @@ -17,15 +17,10 @@ namespace PepperDash.Essentials.Core /// public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute, IEnvironmentalControls { - BoolFeedback OnFeedback { get; } - - event EventHandler RoomOccupancyIsSet; + BoolFeedback OnFeedback { get; } BoolFeedback IsWarmingUpFeedback { get; } - BoolFeedback IsCoolingDownFeedback { get; } - - IOccupancyStatusProvider RoomOccupancy { get; } - bool OccupancyStatusProviderIsRemote { get; } + BoolFeedback IsCoolingDownFeedback { get; } bool IsMobileControlEnabled { get; } IMobileControlRoomBridge MobileControlRoomBridge { get; } @@ -35,31 +30,16 @@ namespace PepperDash.Essentials.Core SecondsCountdownTimer ShutdownPromptTimer { get; } int ShutdownPromptSeconds { get; } int ShutdownVacancySeconds { get; } - eShutdownType ShutdownType { get; } - - EssentialsRoomEmergencyBase Emergency { get; } - - Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } + eShutdownType ShutdownType { get; } string LogoUrlLightBkgnd { get; } string LogoUrlDarkBkgnd { get; } - eVacancyMode VacancyMode { get; } + void StartShutdown(eShutdownType type); - bool ZeroVolumeWhenSwtichingVolumeDevices { get; } + void Shutdown(); - void StartShutdown(eShutdownType type); - void StartRoomVacancyTimer(eVacancyMode mode); - - void Shutdown(); - - void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); - - void PowerOnToDefaultOrLastSource(); - - void SetDefaultLevels(); - - void RoomVacatedForTimeoutPeriod(object o); + void PowerOnToDefaultOrLastSource(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs index b5121e9c..e962e604 100644 --- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs @@ -41,7 +41,6 @@ namespace PepperDash.Essentials.Core void RunRouteAction(string routeKey, string sourceListKey); void RunRouteAction(string routeKey, string sourceListKey, Action successCallback); - } /// @@ -78,4 +77,30 @@ namespace PepperDash.Essentials.Core bool HasEnvironmentalControlDevices { get; } } + public interface IRoomOccupancy:IKeyed + { + IOccupancyStatusProvider RoomOccupancy { get; } + bool OccupancyStatusProviderIsRemote { get; } + + void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); + + void RoomVacatedForTimeoutPeriod(object o); + + void StartRoomVacancyTimer(eVacancyMode mode); + + eVacancyMode VacancyMode { get; } + + event EventHandler RoomOccupancyIsSet; + } + + public interface IEmergency + { + EssentialsRoomEmergencyBase Emergency { get; } + } + + public interface IMicrophonePrivacy + { + Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingInterfaces.cs b/src/PepperDash.Essentials.Core/Routing/RoutingInterfaces.cs index 952a48b1..dcec7ae2 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingInterfaces.cs @@ -204,4 +204,9 @@ namespace PepperDash.Essentials.Core SigType = sigType; } } + + public interface IRoutingHasVideoInputSyncFeedbacks + { + FeedbackCollection VideoInputSyncFeedbacks { get; } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs index 79dd4eda..ab64f15e 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs @@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Core public enum eRoutingPortConnectionType { None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi, - Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming + Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC, HdBaseT } /// diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs index 00e85191..7029443b 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs @@ -199,5 +199,45 @@ namespace PepperDash.Essentials.Core.Routing /// MediaPlayer /// public const string MediaPlayer = "mediaPlayer"; - } + /// + /// UsbCIn + /// + public const string UsbCIn = "usbCIn"; + /// + /// UsbCIn1 + /// + public const string UsbCIn1 = "usbCIn1"; + /// + /// UsbCIn2 + /// + public const string UsbCIn2 = "usbCIn2"; + /// + /// UsbCIn3 + /// + public const string UsbCIn3 = "usbCIn3"; + /// + /// UsbCOut + /// + public const string UsbCOut = "usbCOut"; + /// + /// UsbCOut1 + /// + public const string UsbCOut1 = "usbCOut1"; + /// + /// UsbCOut2 + /// + public const string UsbCOut2 = "usbCOut2"; + /// + /// UsbCOut3 + /// + public const string UsbCOut3 = "usbCOut3"; + /// + /// HdBaseTIn + /// + public const string HdBaseTIn = "hdBaseTIn"; + /// + /// HdBaseTOut + /// + public const string HdBaseTOut = "hdBaseTOut"; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs b/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs index c9a5f605..2f6074dd 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs @@ -1,144 +1,352 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Globalization; using Crestron.SimplSharpPro; - +using Newtonsoft.Json; using PepperDash.Core; -using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core.Touchpanels { - /// - /// A wrapper class for the touchpanel portion of an MPC3 class process to allow for configurable - /// behavior of the keybad buttons - /// - public class Mpc3TouchpanelController : Device - { - MPC3Basic _Touchpanel; + /// + /// A wrapper class for the touchpanel portion of an MPC3 class process to allow for configurable + /// behavior of the keybad buttons + /// + public class Mpc3TouchpanelController : Device + { + readonly MPC3Basic _touchpanel; - Dictionary _Buttons; + readonly Dictionary _buttons; - public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) - : base(key, name) - { - _Touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; - _Buttons = buttons; + public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) + : base(key, name) + { + _touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; + if (_touchpanel == null) + { + Debug.Console(1, this, "Failed to construct MPC3 Touchpanel Controller with key {0}, check configuration", key); + return; + } - _Touchpanel.ButtonStateChange += new Crestron.SimplSharpPro.DeviceSupport.ButtonEventHandler(_Touchpanel_ButtonStateChange); + if (_touchpanel.Registerable) + { + var registrationResponse = _touchpanel.Register(); + Debug.Console(0, this, "touchpanel registration response: {0}", registrationResponse); + } - AddPostActivationAction(() => - { - // Link up the button feedbacks to the specified BoolFeedbacks - foreach (var button in _Buttons) - { - var feedbackConfig = button.Value.Feedback; - var device = DeviceManager.GetDeviceForKey(feedbackConfig.DeviceKey) as Device; - if (device != null) - { - var bKey = button.Key.ToLower(); + _touchpanel.BaseEvent += _touchpanel_BaseEvent; + _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _touchpanel.PanelStateChange += _touchpanel_PanelStateChange; - var feedback = device.GetFeedbackProperty(feedbackConfig.FeedbackName); + _buttons = buttons; + if (_buttons == null) + { + Debug.Console(1, this, + "Button properties are null, failed to setup MPC3 Touch Controller, check configuration"); + return; + } - var bFeedback = feedback as BoolFeedback; - var iFeedback = feedback as IntFeedback; - if (bFeedback != null) - { + AddPostActivationAction(() => + { + foreach (var button in _buttons) + { + var buttonKey = button.Key.ToLower(); + var buttonConfig = button.Value; - if (bKey == "power") - { - bFeedback.LinkCrestronFeedback(_Touchpanel.FeedbackPower); - continue; - } - else if (bKey == "mute") - { - bFeedback.LinkCrestronFeedback(_Touchpanel.FeedbackMute); - continue; - } + InitializeButton(buttonKey, buttonConfig); + InitializeButtonFeedback(buttonKey, buttonConfig); + } + }); + } - // Link to the Crestron Feedback corresponding to the button number - bFeedback.LinkCrestronFeedback(_Touchpanel.Feedbacks[UInt16.Parse(button.Key)]); - } - else if (iFeedback != null) - { - if (bKey == "volumefeedback") - { - var volFeedback = feedback as IntFeedback; - // TODO: Figure out how to subsribe to a volume IntFeedback and link it to the voluem - volFeedback.LinkInputSig(_Touchpanel.VolumeBargraph); - } - } - else - { - Debug.Console(1, this, "Unable to get BoolFeedback with name: {0} from device: {1}", feedbackConfig.FeedbackName, device.Key); - } - } - else - { - Debug.Console(1, this, "Unable to get device with key: {0}", feedbackConfig.DeviceKey); - } - } - }); - } + /// + /// Enables/disables buttons based on event type configuration + /// + /// + /// + public void InitializeButton(string key, KeypadButton config) + { + if (config == null) + { + Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); + return; + } - void _Touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) - { - Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); - var type = args.NewButtonState.ToString(); + int buttonNumber; + TryParseInt(key, out buttonNumber); - if (_Buttons.ContainsKey(args.Button.Number.ToString())) - { - Press(args.Button.Number.ToString(), type); - } - else if(_Buttons.ContainsKey(args.Button.Name.ToString())) - { - Press(args.Button.Name.ToString(), type); - } - } + var buttonEventTypes = config.EventTypes; + BoolOutputSig enabledFb = null; + BoolOutputSig disabledFb = null; - /// - /// Runs the function associated with this button/type. One of the following strings: - /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased - /// - /// - /// - public void Press(string number, string type) - { - // TODO: In future, consider modifying this to generate actions at device activation time - // to prevent the need to dynamically call the method via reflection on each button press - if (!_Buttons.ContainsKey(number)) { return; } - var but = _Buttons[number]; - if (but.EventTypes.ContainsKey(type)) - { - foreach (var a in but.EventTypes[type]) { DeviceJsonApi.DoDeviceAction(a); } - } - } + switch (key) + { + case ("power"): + { + if (buttonEventTypes == null || buttonEventTypes.Keys == null) + _touchpanel.DisablePowerButton(); + else + _touchpanel.EnablePowerButton(); - } + enabledFb = _touchpanel.PowerButtonEnabledFeedBack; + disabledFb = _touchpanel.PowerButtonDisabledFeedBack; - /// - /// Represents the configuration of a keybad buggon - /// - public class KeypadButton - { - public Dictionary EventTypes { get; set; } - public KeypadButtonFeedback Feedback { get; set; } + break; + } + //case ("volumeup"): + // { + // break; + // } + //case ("volumedown"): + // { + // break; + // } + //case ("volumefeedback"): + // { + // break; + // } + case ("mute"): + { + if (buttonEventTypes == null || buttonEventTypes.Keys == null) + _touchpanel.DisableMuteButton(); + else + _touchpanel.EnableMuteButton(); - public KeypadButton() - { - EventTypes = new Dictionary(); - Feedback = new KeypadButtonFeedback(); - } - } - /// - /// - /// - public class KeypadButtonFeedback - { - public string DeviceKey { get; set; } - public string FeedbackName { get; set; } - } + enabledFb = _touchpanel.MuteButtonEnabledFeedBack; + disabledFb = _touchpanel.MuteButtonDisabledFeedBack; + + break; + } + default: + { + if (buttonNumber == 0 || buttonNumber > 9) + break; + + if (buttonEventTypes == null || buttonEventTypes.Keys == null) + _touchpanel.DisableNumericalButton((uint)buttonNumber); + else + _touchpanel.EnableNumericalButton((uint)buttonNumber); + + + if (_touchpanel.NumericalButtonEnabledFeedBack != null) + enabledFb = _touchpanel.NumericalButtonEnabledFeedBack[(uint)buttonNumber]; + + if (_touchpanel.NumericalButtonDisabledFeedBack != null) + disabledFb = _touchpanel.NumericalButtonDisabledFeedBack[(uint)buttonNumber]; + + break; + } + } + + Debug.Console(0, this, "InitializeButton: key-'{0}' enabledFb-'{1}', disabledFb-'{2}'", + key, enabledFb ?? (object)"null", disabledFb ?? (object)"null"); + } + + /// + /// Links button feedback if configured + /// + /// + /// + public void InitializeButtonFeedback(string key, KeypadButton config) + { + //Debug.Console(1, this, "Initializing button '{0}' feedback...", key); + + if (config == null) + { + Debug.Console(1, this, "Button '{0}' config is null, skipping.", key); + return; + } + + int buttonNumber; + TryParseInt(key, out buttonNumber); + + // Link up the button feedbacks to the specified device feedback + var buttonFeedback = config.Feedback; + if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey)) + { + Debug.Console(1, this, "Button '{0}' feedback not configured, skipping.", + key); + return; + } + + Feedback deviceFeedback; + + try + { + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Button '{0}' feedback deviceKey '{1}' not found.", + key, buttonFeedback.DeviceKey); + return; + } + + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + if (deviceFeedback == null) + { + Debug.Console(1, this, "Button '{0}' feedbackName property '{1}' not found.", + key, buttonFeedback.FeedbackName); + return; + } + + // TODO [ ] verify if this can replace the current method + //Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { + // break; + // } + // case("intfeedback"): + // { + // break; + // } + // case("stringfeedback"): + // { + // break; + // } + //} + } + catch (Exception ex) + { + Debug.Console(1, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception Message: {0}", + ex.Message, key, buttonFeedback.DeviceKey); + Debug.Console(2, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception StackTrace: {0}", + ex.StackTrace, key, buttonFeedback.DeviceKey); + if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') InnerException: {0}", + ex.InnerException, key, buttonFeedback.DeviceKey); + + return; + } + + var boolFeedback = deviceFeedback as BoolFeedback; + var intFeedback = deviceFeedback as IntFeedback; + + switch (key) + { + case ("power"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); + break; + } + case ("volumeup"): + case ("volumedown"): + case ("volumefeedback"): + { + if (intFeedback != null) + { + var volumeFeedback = intFeedback; + volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); + } + break; + } + case ("mute"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); + break; + } + default: + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + break; + } + } + } + + /// + /// Try parse int helper method + /// + /// + /// + /// + public bool TryParseInt(string str, out int result) + { + try + { + result = int.Parse(str); + return true; + } + catch + { + result = 0; + return false; + } + } + + private void _touchpanel_BaseEvent(GenericBase device, BaseEventArgs args) + { + Debug.Console(1, this, "BaseEvent: eventId-'{0}', index-'{1}'", args.EventId, args.Index); + } + + private void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) + { + Debug.Console(1, this, "ButtonStateChange: buttonNumber-'{0}' buttonName-'{1}', buttonState-'{2}'", args.Button.Number, args.Button.Name, args.NewButtonState); + var type = args.NewButtonState.ToString(); + + if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) + { + Press(args.Button.Number.ToString(CultureInfo.InvariantCulture), type); + } + else if (_buttons.ContainsKey(args.Button.Name.ToString())) + { + Press(args.Button.Name.ToString(), type); + } + } + + private void _touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args) + { + Debug.Console(1, this, "PanelStateChange: eventId-'{0}', index-'{1}'", args.EventId, args.Index); + } + + /// + /// Runs the function associated with this button/type. One of the following strings: + /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased + /// + /// + /// + public void Press(string buttonKey, string type) + { + Debug.Console(2, this, "Press: buttonKey-'{0}', type-'{1}'", buttonKey, type); + + // TODO: In future, consider modifying this to generate actions at device activation time + // to prevent the need to dynamically call the method via reflection on each button press + if (!_buttons.ContainsKey(buttonKey)) return; + + var button = _buttons[buttonKey]; + if (!button.EventTypes.ContainsKey(type)) return; + + foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType); + } + } + + /// + /// Represents the configuration of a keypad button + /// + public class KeypadButton + { + [JsonProperty("eventTypes")] + public Dictionary EventTypes { get; set; } + + [JsonProperty("feedback")] + public KeypadButtonFeedback Feedback { get; set; } + + public KeypadButton() + { + EventTypes = new Dictionary(); + Feedback = new KeypadButtonFeedback(); + } + } + + /// + /// Represents the configuration of a keypad button feedback + /// + public class KeypadButtonFeedback + { + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + [JsonProperty("feedbackName")] + public string FeedbackName { get; set; } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/EssemtialsWebApi.cs b/src/PepperDash.Essentials.Core/Web/EssemtialsWebApi.cs index dc6b2efb..eb012378 100644 --- a/src/PepperDash.Essentials.Core/Web/EssemtialsWebApi.cs +++ b/src/PepperDash.Essentials.Core/Web/EssemtialsWebApi.cs @@ -3,9 +3,6 @@ using System.Collections.Generic; using System.Linq; using Crestron.SimplSharp; using Crestron.SimplSharp.WebScripting; -using Crestron.SimplSharpPro.Diagnostics; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Core.Web; using PepperDash.Essentials.Core.Web.RequestHandlers; @@ -20,13 +17,13 @@ namespace PepperDash.Essentials.Core.Web /// http(s)://{ipaddress}/cws/{basePath} /// http(s)://{ipaddress}/VirtualControl/Rooms/{roomId}/cws/{basePath} /// - private readonly string _defaultBasePath = - CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? string.Format("/app{0:00}/api", InitialParametersClass.ApplicationNumber) : "/api"; + private readonly string _defaultBasePath = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance + ? string.Format("/app{0:00}/api", InitialParametersClass.ApplicationNumber) + : "/api"; - // TODO [ ] Reset debug levels to proper value Trace = 0, Info = 1, Verbose = 2 private const int DebugTrace = 0; - private const int DebugInfo = 0; - private const int DebugVerbose = 0; + private const int DebugInfo = 1; + private const int DebugVerbose = 2; /// /// CWS base path @@ -98,11 +95,6 @@ namespace PepperDash.Essentials.Core.Web Name = "DevProps", RouteHandler = new DevPropsRequestHandler() }, - //new HttpCwsRoute("devprops/{key}") - //{ - // Name = "DevProps", - // RouteHandler = new DevPropsRequestHandler() - //}, new HttpCwsRoute("devjson") { Name = "DevJson", @@ -113,11 +105,6 @@ namespace PepperDash.Essentials.Core.Web Name = "SetDeviceStreamDebug", RouteHandler = new SetDeviceStreamDebugRequestHandler() }, - //new HttpCwsRoute("setdevicestreamdebug/{deviceKey}/{state}") - //{ - // Name = "SetDeviceStreamDebug", - // RouteHandler = new SetDeviceStreamDebugRequestHandler() - //}, new HttpCwsRoute("disableallstreamdebug") { Name = "DisableAllStreamDebug", @@ -173,12 +160,7 @@ namespace PepperDash.Essentials.Core.Web if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) { /* - RMC4> WEBSERVER [ON | OFF | TIMEOUT | MAXSESSIONSPERUSER ] - WEBSERVER [TIMEOUT] will display current session timeout value - WEBSERVER MAXSESSIONSPERUSER will display current max web sessions per user - WEBSERVER ALLOWSHAREDSESSION will display whether 'samesite = none' would be set on cookies - No parameter - displays current setting */ var response = string.Empty; CrestronConsole.SendControlSystemCommand("webserver", ref response); diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/AppDebugRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/AppDebugRequestHandler.cs index 91f45927..46a0f980 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/AppDebugRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/AppDebugRequestHandler.cs @@ -1,6 +1,4 @@ -using System; -using System.Text; -using Crestron.SimplSharp.WebScripting; +using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; @@ -10,25 +8,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class AppDebugRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public AppDebugRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -37,7 +24,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers /// protected override void HandleGet(HttpCwsContext context) { - var appDebug = new AppDebug {Level = Debug.Level}; + var appDebug = new AppDebug { Level = Debug.Level }; var body = JsonConvert.SerializeObject(appDebug, Formatting.Indented); @@ -46,40 +33,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(body, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - + /// /// Handles POST method requests /// @@ -107,7 +61,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers var appDebug = new AppDebug(); var requestBody = JsonConvert.DeserializeAnonymousType(data, appDebug); - + Debug.SetDebugLevel(requestBody.Level); appDebug.Level = Debug.Level; @@ -118,33 +72,11 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(responseBody, false); context.Response.End(); } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } public class AppDebug { [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] - public int Level { get; set; } + public int Level { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs index 1186dc0c..3320de7e 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs @@ -5,6 +5,17 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers { public class DefaultRequestHandler : WebApiBaseRequestHandler { + /// + /// Constructor + /// + /// + /// base(true) enables CORS support by default + /// + public DefaultRequestHandler() + : base(true) + { + } + /// /// Handles CONNECT method requests /// diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs index ff3045b5..5c4f33a2 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -1,6 +1,6 @@ using System; -using System.Text; using Crestron.SimplSharp.WebScripting; +using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers @@ -8,69 +8,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class DevJsonRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public DevJsonRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles GET method requests - /// - /// - protected override void HandleGet(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -108,32 +53,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers } catch (Exception ex) { + Debug.Console(1, "Exception Message: {0}", ex.Message); + Debug.Console(2, "Exception Stack Trace: {0}", ex.StackTrace); + if(ex.InnerException != null) Debug.Console(2, "Exception Inner: {0}", ex.InnerException); + context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; context.Response.End(); } } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs index 1a548f29..e9df4347 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs @@ -8,25 +8,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class DevListRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public DevListRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -58,71 +47,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(js, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs index d7334591..25fadbce 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -1,5 +1,4 @@ -using System; -using System.Text; +using System.Text; using Crestron.SimplSharp.WebScripting; using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; @@ -9,69 +8,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class DevPropsRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public DevPropsRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles GET method requests - /// - /// - protected override void HandleGet(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -128,27 +72,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(deviceProps, false); context.Response.End(); } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index 41dc4974..0e682d6c 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -6,69 +6,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public DisableAllStreamDebugRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles GET method requests - /// - /// - protected override void HandleGet(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -83,27 +28,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.StatusDescription = "OK"; context.Response.End(); } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs index 1055dddd..5dd5495c 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs @@ -8,25 +8,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class GetFeedbacksForDeviceRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public GetFeedbacksForDeviceRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -109,71 +98,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(js, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs index f4ec3975..f2362f4b 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -9,25 +9,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class GetJoinMapForBridgeKeyRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public GetJoinMapForBridgeKeyRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -84,74 +73,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.ContentEncoding = System.Text.Encoding.UTF8; context.Response.Write(js, false); context.Response.End(); - } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - + } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs index fe3fc999..6c669189 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -8,25 +8,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class GetJoinMapForDeviceKeyRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public GetJoinMapForDeviceKeyRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -102,71 +91,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(js, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs index 6636d914..105d2419 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs @@ -1,6 +1,8 @@ -using System.Linq; +extern alias Full + +using System.Linq; using Crestron.SimplSharp.WebScripting; -using Newtonsoft.Json; +using Full.Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers @@ -8,25 +10,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class GetTypesByFilterRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public GetTypesByFilterRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -75,71 +66,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(js, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs index 094d22f4..a72fe7e4 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -1,6 +1,8 @@ -using System.Linq; +extern alias Full + +using System.Linq; using Crestron.SimplSharp.WebScripting; -using Newtonsoft.Json; +using Full.Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers @@ -8,25 +10,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class GetTypesRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public GetTypesRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -65,71 +56,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(js, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs index 321c5bfc..925a95f0 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -1,6 +1,8 @@ -using System.Linq; +extern alias Full + +using System.Linq; using Crestron.SimplSharp.WebScripting; -using Newtonsoft.Json; +using Full.Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers @@ -8,25 +10,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class ReportVersionsRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public ReportVersionsRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -56,71 +47,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(js, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs index 16c05abf..b017627d 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -1,5 +1,7 @@ -using Crestron.SimplSharp.WebScripting; -using Newtonsoft.Json; +extern alias Full + +using Crestron.SimplSharp.WebScripting; +using Full.Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; using PepperDash.Essentials.Core.Config; @@ -8,25 +10,14 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class ShowConfigRequestHandler : WebApiBaseRequestHandler { /// - /// Handles CONNECT method requests + /// Constructor /// - /// - protected override void HandleConnect(HttpCwsContext context) + /// + /// base(true) enables CORS support by default + /// + public ShowConfigRequestHandler() + : base(true) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles DELETE method requests - /// - /// - protected override void HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); } /// @@ -44,71 +35,5 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers context.Response.Write(config, false); context.Response.End(); } - - /// - /// Handles HEAD method requests - /// - /// - protected override void HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles OPTIONS method requests - /// - /// - protected override void HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PATCH method requests - /// - /// - protected override void HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles POST method requests - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles PUT method requests - /// - /// - protected override void HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } - - /// - /// Handles TRACE method requests - /// - /// - protected override void HandleTrace(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/AirMedia/AirMediaController.cs b/src/PepperDash.Essentials.DM/AirMedia/AirMediaController.cs index 80f8e64d..c26e8bc3 100644 --- a/src/PepperDash.Essentials.DM/AirMedia/AirMediaController.cs +++ b/src/PepperDash.Essentials.DM/AirMedia/AirMediaController.cs @@ -22,7 +22,7 @@ namespace PepperDash.Essentials.DM.AirMedia [Description("Wrapper class for an AM-200 or AM-300")] public class AirMediaController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IIROutputPorts, IComPorts { - public AmX00 AirMedia { get; private set; } + public Am3x00 AirMedia { get; private set; } public DeviceConfig DeviceConfig { get; private set; } @@ -47,7 +47,7 @@ namespace PepperDash.Essentials.DM.AirMedia public StringFeedback SerialNumberFeedback { get; private set; } public BoolFeedback AutomaticInputRoutingEnabledFeedback { get; private set; } - public AirMediaController(string key, string name, AmX00 device, DeviceConfig dc, AirMediaPropertiesConfig props) + public AirMediaController(string key, string name, Am3x00 device, DeviceConfig dc, AirMediaPropertiesConfig props) : base(key, name, device) { @@ -98,24 +98,31 @@ namespace PepperDash.Essentials.DM.AirMedia AirMedia.AirMedia.AirMediaChange += new Crestron.SimplSharpPro.DeviceSupport.GenericEventHandler(AirMedia_AirMediaChange); - IsInSessionFeedback = new BoolFeedback(new Func(() => AirMedia.AirMedia.StatusFeedback.UShortValue == 0)); - ErrorFeedback = new IntFeedback(new Func(() => AirMedia.AirMedia.ErrorFeedback.UShortValue)); - NumberOfUsersConnectedFeedback = new IntFeedback(new Func(() => AirMedia.AirMedia.NumberOfUsersConnectedFeedback.UShortValue)); - LoginCodeFeedback = new IntFeedback(new Func(() => AirMedia.AirMedia.LoginCodeFeedback.UShortValue)); - ConnectionAddressFeedback = new StringFeedback(new Func(() => AirMedia.AirMedia.ConnectionAddressFeedback.StringValue)); - HostnameFeedback = new StringFeedback(new Func(() => AirMedia.AirMedia.HostNameFeedback.StringValue)); + IsInSessionFeedback = new BoolFeedback(() => AirMedia.AirMedia.StatusFeedback.UShortValue == 0); + ErrorFeedback = new IntFeedback(() => AirMedia.AirMedia.ErrorFeedback.UShortValue); + NumberOfUsersConnectedFeedback = new IntFeedback(() => AirMedia.AirMedia.NumberOfUsersConnectedFeedback.UShortValue); + LoginCodeFeedback = new IntFeedback(() => AirMedia.AirMedia.LoginCodeFeedback.UShortValue); + ConnectionAddressFeedback = new StringFeedback(() => AirMedia.AirMedia.ConnectionAddressFeedback.StringValue); + HostnameFeedback = new StringFeedback(() => AirMedia.AirMedia.HostNameFeedback.StringValue); // TODO: Figure out if we can actually get the TSID/Serial - SerialNumberFeedback = new StringFeedback(new Func(() => "unknown")); + SerialNumberFeedback = new StringFeedback(() => "unknown"); - AirMedia.DisplayControl.DisplayControlChange += new Crestron.SimplSharpPro.DeviceSupport.GenericEventHandler(DisplayControl_DisplayControlChange); + AirMedia.DisplayControl.DisplayControlChange += DisplayControl_DisplayControlChange; - VideoOutFeedback = new IntFeedback(new Func(() => Convert.ToInt16(AirMedia.DisplayControl.VideoOutFeedback))); - AutomaticInputRoutingEnabledFeedback = new BoolFeedback(new Func(() => AirMedia.DisplayControl.EnableAutomaticRoutingFeedback.BoolValue)); + VideoOutFeedback = new IntFeedback(() => Convert.ToInt16(AirMedia.DisplayControl.VideoOutFeedback)); + AutomaticInputRoutingEnabledFeedback = new BoolFeedback(() => AirMedia.DisplayControl.EnableAutomaticRoutingFeedback.BoolValue); - AirMedia.HdmiIn.StreamChange += new Crestron.SimplSharpPro.DeviceSupport.StreamEventHandler(HdmiIn_StreamChange); + // Not all AirMedia versions support HDMI In like the 3200 + if (AirMedia.HdmiIn != null) + { + AirMedia.HdmiIn.StreamChange += HdmiIn_StreamChange; + HdmiVideoSyncDetectedFeedback = new BoolFeedback(() => AirMedia.HdmiIn.SyncDetectedFeedback.BoolValue); + return; + } - HdmiVideoSyncDetectedFeedback = new BoolFeedback(new Func(() => AirMedia.HdmiIn.SyncDetectedFeedback.BoolValue)); + // Return false if the AirMedia device doesn't support HDMI Input + HdmiVideoSyncDetectedFeedback = new BoolFeedback(() => false); } public override bool CustomActivate() @@ -182,31 +189,53 @@ namespace PepperDash.Essentials.DM.AirMedia /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType private void OnSwitchChange(RoutingNumericEventArgs e) { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, e); + var handler = NumericSwitchChange; + + if (handler == null) return; + + handler(this, e); } void AirMedia_AirMediaChange(object sender, Crestron.SimplSharpPro.DeviceSupport.GenericEventArgs args) { - if (args.EventId == AirMediaInputSlot.AirMediaStatusFeedbackEventId) - IsInSessionFeedback.FireUpdate(); - else if (args.EventId == AirMediaInputSlot.AirMediaErrorFeedbackEventId) - ErrorFeedback.FireUpdate(); - else if (args.EventId == AirMediaInputSlot.AirMediaNumberOfUserConnectedEventId) - NumberOfUsersConnectedFeedback.FireUpdate(); - else if (args.EventId == AirMediaInputSlot.AirMediaLoginCodeEventId) - LoginCodeFeedback.FireUpdate(); - else if (args.EventId == AirMediaInputSlot.AirMediaConnectionAddressFeedbackEventId) - ConnectionAddressFeedback.FireUpdate(); - else if (args.EventId == AirMediaInputSlot.AirMediaHostNameFeedbackEventId) - HostnameFeedback.FireUpdate(); + switch (args.EventId) + { + case AirMediaInputSlot.AirMediaStatusFeedbackEventId: + { + IsInSessionFeedback.FireUpdate(); + break; + } + case AirMediaInputSlot.AirMediaErrorFeedbackEventId: + { + ErrorFeedback.FireUpdate(); + break; + } + case AirMediaInputSlot.AirMediaNumberOfUserConnectedEventId: + { + NumberOfUsersConnectedFeedback.FireUpdate(); + break; + } + case AirMediaInputSlot.AirMediaLoginCodeEventId: + { + LoginCodeFeedback.FireUpdate(); + break; + } + case AirMediaInputSlot.AirMediaConnectionAddressFeedbackEventId: + { + ConnectionAddressFeedback.FireUpdate(); + break; + } + case AirMediaInputSlot.AirMediaHostNameFeedbackEventId: + { + HostnameFeedback.FireUpdate(); + break; + } + } } void DisplayControl_DisplayControlChange(object sender, Crestron.SimplSharpPro.DeviceSupport.GenericEventArgs args) { - if (args.EventId == AmX00.VideoOutFeedbackEventId) - { VideoOutFeedback.FireUpdate(); var localInputPort = @@ -214,8 +243,7 @@ namespace PepperDash.Essentials.DM.AirMedia OnSwitchChange(new RoutingNumericEventArgs(1, VideoOutFeedback.UShortValue, OutputPorts.First(), localInputPort, eRoutingSignalType.AudioVideo)); - } - else if (args.EventId == AmX00.EnableAutomaticRoutingFeedbackEventId) + AutomaticInputRoutingEnabledFeedback.FireUpdate(); } @@ -345,7 +373,7 @@ namespace PepperDash.Essentials.DM.AirMedia { public AirMediaControllerFactory() { - TypeNames = new List() { "am200", "am300" }; + TypeNames = new List() { "am200", "am300", "am3200" }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) @@ -354,12 +382,26 @@ namespace PepperDash.Essentials.DM.AirMedia Debug.Console(1, "Factory Attempting to create new AirMedia Device"); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - AmX00 amDevice = null; - if (type == "am200") - amDevice = new Crestron.SimplSharpPro.DM.AirMedia.Am200(props.Control.IpIdInt, Global.ControlSystem); - else if (type == "am300") - amDevice = new Crestron.SimplSharpPro.DM.AirMedia.Am300(props.Control.IpIdInt, Global.ControlSystem); + var props = dc.Properties.ToObject(); + Am3x00 amDevice = null; + switch (type) + { + case "am200" : + { + amDevice = new Am200(props.Control.IpIdInt, Global.ControlSystem); + break; + } + case "am300" : + { + amDevice = new Am300(props.Control.IpIdInt, Global.ControlSystem); + break; + } + case "am3200" : + { + amDevice = new Am3200(props.Control.IpIdInt, Global.ControlSystem); + break; + } + } return new AirMediaController(dc.Key, dc.Name, amDevice, dc, props); diff --git a/src/PepperDash.Essentials.DM/Chassis/DmBladeChassisController.cs b/src/PepperDash.Essentials.DM/Chassis/DmBladeChassisController.cs index 841c239a..3cdad1b8 100644 --- a/src/PepperDash.Essentials.DM/Chassis/DmBladeChassisController.cs +++ b/src/PepperDash.Essentials.DM/Chassis/DmBladeChassisController.cs @@ -24,7 +24,7 @@ namespace PepperDash.Essentials.DM /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions /// /// - public class DmBladeChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback + public class DmBladeChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitchWithEndpointOnlineFeedback, IRoutingNumericWithFeedback { private const string NonePortKey = "inputCard0--None"; diff --git a/src/PepperDash.Essentials.DM/Chassis/DmChassisController.cs b/src/PepperDash.Essentials.DM/Chassis/DmChassisController.cs index e5690166..a00f6d80 100644 --- a/src/PepperDash.Essentials.DM/Chassis/DmChassisController.cs +++ b/src/PepperDash.Essentials.DM/Chassis/DmChassisController.cs @@ -25,7 +25,7 @@ namespace PepperDash.Essentials.DM /// /// [Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")] - public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback + public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitchWithEndpointOnlineFeedback, IRoutingNumericWithFeedback { private const string NonePortKey = "inputCard0--None"; public DMChassisPropertiesConfig PropertiesConfig { get; set; } diff --git a/src/PepperDash.Essentials.DM/Chassis/HdPsXxxController.cs b/src/PepperDash.Essentials.DM/Chassis/HdPsXxxController.cs new file mode 100644 index 00000000..36e99bc6 --- /dev/null +++ b/src/PepperDash.Essentials.DM/Chassis/HdPsXxxController.cs @@ -0,0 +1,589 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; +using PepperDash_Essentials_Core.Bridges; +using PepperDash_Essentials_DM.Config; + +namespace PepperDash_Essentials_DM.Chassis +{ + [Description("Wrapper class for all HdPsXxx switchers")] + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks + { + private readonly HdPsXxx _chassis; + + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + + public FeedbackCollection InputNameFeedbacks { get; private set; } + public FeedbackCollection InputHdcpEnableFeedback { get; private set; } + + public FeedbackCollection OutputNameFeedbacks { get; private set; } + public FeedbackCollection OutputRouteNameFeedback { get; private set; } + + public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } + public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } + + public StringFeedback DeviceNameFeedback { get; private set; } + public BoolFeedback AutoRouteFeedback { get; private set; } + + public event EventHandler NumericSwitchChange; + public event EventHandler DmInputChange; + + + /// + /// Constructor + /// + /// + /// + /// HdPs401 device instance + /// + public HdPsXxxController(string key, string name, HdPsXxx chassis, HdPsXxxPropertiesConfig props) + : base(key, name, chassis) + { + _chassis = chassis; + Name = name; + + if (props == null) + { + Debug.Console(1, this, "HdPsXxxController properties are null, failed to build device"); + return; + } + + InputPorts = new RoutingPortCollection(); + InputNameFeedbacks = new FeedbackCollection(); + InputHdcpEnableFeedback = new FeedbackCollection(); + InputNames = new Dictionary(); + + OutputPorts = new RoutingPortCollection(); + OutputNameFeedbacks = new FeedbackCollection(); + OutputRouteNameFeedback = new FeedbackCollection(); + OutputNames = new Dictionary(); + + VideoInputSyncFeedbacks = new FeedbackCollection(); + VideoOutputRouteFeedbacks = new FeedbackCollection(); + + if (_chassis.NumberOfOutputs == 1) + AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); + + InputNames = props.Inputs; + SetupInputs(InputNames); + + OutputNames = props.Outputs; + SetupOutputs(OutputNames); + } + + // get input priorities + private byte[] SetInputPriorities(HdPsXxxPropertiesConfig props) + { + throw new NotImplementedException(); + } + + // input setup + private void SetupInputs(Dictionary dict) + { + if (dict == null) + { + Debug.Console(1, this, "Failed to setup inputs, properties are null"); + return; + } + + // iterate through HDMI inputs + foreach (var item in _chassis.HdmiInputs) + { + var input = item; + var index = item.Number; + var key = string.Format("hdmiIn{0}", index); + var name = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("HDMI Input {0}", index) + : InputNames[index]; + + input.Name.StringValue = name; + + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => InputNames[index])); + + var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + { + FeedbackMatchObject = input + }; + Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, name); + InputPorts.Add(port); + + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.VideoDetectedFeedback.BoolValue)); + } + + // iterate through DM Lite inputs + foreach (var item in _chassis.DmLiteInputs) + { + var input = item; + var index = item.Number; + var key = string.Format("dmLiteIn{0}", index); + var name = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("DM Input {0}", index) + : InputNames[index]; + + input.Name.StringValue = name; + + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => InputNames[index])); + + var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + { + FeedbackMatchObject = input + }; + Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, name); + InputPorts.Add(port); + + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.VideoDetectedFeedback.BoolValue)); + } + + _chassis.DMInputChange += _chassis_InputChange; + } + + // output setup + private void SetupOutputs(Dictionary dict) + { + if (dict == null) + { + Debug.Console(1, this, "Failed to setup outputs, properties are null"); + return; + } + + foreach (var item in _chassis.HdmiDmLiteOutputs) + { + var output = item; + var index = item.Number; + var name = string.IsNullOrEmpty(OutputNames[index]) + ? string.Format("Output {0}", index) + : OutputNames[index]; + + output.Name.StringValue = name; + + var hdmiKey = string.Format("hdmiOut{0}", index); + var hdmiPort = new RoutingOutputPort(hdmiKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + { + FeedbackMatchObject = output, + Port = output.HdmiOutput.HdmiOutputPort + }; + Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, name); + OutputPorts.Add(hdmiPort); + + var dmLiteKey = string.Format("dmLiteOut{0}", index); + var dmLitePort = new RoutingOutputPort(dmLiteKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) + { + FeedbackMatchObject = output, + Port = output.DmLiteOutput.DmLiteOutputPort + }; + Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, name); + OutputPorts.Add(dmLitePort); + + OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => output.VideoOutFeedback.NameFeedback.StringValue)); + + VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), + () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + } + + _chassis.DMOutputChange += _chassis_OutputChange; + } + + + public void ListRoutingPorts() + { + try + { + foreach (var port in InputPorts) + { + Debug.Console(0, this, @"Input Port Key: {0} +Port: {1} +Type: {2} +ConnectionType: {3} +Selector: {4} +", port.Key, port.Port, port.Type, port.ConnectionType, port.Selector); + } + + foreach (var port in OutputPorts) + { + Debug.Console(0, this, @"Output Port Key: {0} +Port: {1} +Type: {2} +ConnectionType: {3} +Selector: {4} +", port.Key, port.Port, port.Type, port.ConnectionType, port.Selector); + } + } + catch (Exception ex) + { + Debug.Console(0, this, "ListRoutingPorts Exception Message: {0}", ex.Message); + Debug.Console(0, this, "ListRoutingPorts Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) Debug.Console(0, this, "ListRoutingPorts InnerException: {0}", ex.InnerException); + } + } + + #region BridgeLinking + + /// + /// Link device to API + /// + /// + /// + /// + /// + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new HdPsXxxControllerJoinMap(joinStart); + + 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"); + } + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + DeviceNameFeedback.LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); + + _chassis.OnlineStatusChange += _chassis_OnlineStatusChange; + + LinkChassisInputsToApi(trilist, joinMap); + LinkChassisOutputsToApi(trilist, joinMap); + + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) return; + }; + } + + + // links inputs to API + private void LinkChassisInputsToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) + { + for (uint i = 1; i <= _chassis.NumberOfInputs; i++) + { + var input = i; + var inputName = InputNames[input]; + var indexWithOffset = input - 1; + + trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + indexWithOffset, () => EnableHdcp(input)); + trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + indexWithOffset, () => DisableHdcp(input)); + + InputHdcpEnableFeedback[inputName].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + indexWithOffset]); + InputHdcpEnableFeedback[inputName].LinkComplementInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + indexWithOffset]); + + VideoInputSyncFeedbacks[inputName].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + indexWithOffset]); + + InputNameFeedbacks[inputName].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + indexWithOffset]); + } + } + + + // links outputs to API + private void LinkChassisOutputsToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) + { + for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) + { + var output = i; + var outputName = OutputNames[output]; + var indexWithOffset = output - 1; + + trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + indexWithOffset, (a) => + ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.AudioVideo)); + + OutputNameFeedbacks[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + indexWithOffset]); + OutputRouteNameFeedback[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + indexWithOffset]); + + VideoOutputRouteFeedbacks[outputName].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + indexWithOffset]); + } + + AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); + } + + #endregion + + + /// + /// Executes a device switch using objects + /// + /// + /// + /// + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + var input = inputSelector as HdPsXxxInput; + var output = outputSelector as HdPsXxxOutput; + + Debug.Console(2, this, "ExecuteSwitch: input={0}, output={1}", input, output); + + if (output == null) + { + Debug.Console(0, this, "Unable to make switch, output selector is not HdPsXxxHdmiOutput"); + return; + } + + // TODO [ ] Validate if sending the same input toggles the switch + var current = output.VideoOut; + if (current != input) + output.VideoOut = input; + } + + + /// + /// Executes a device switch using numeric values + /// + /// + /// + /// + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) + { + var input = inputSelector == 0 ? null : _chassis.Inputs[inputSelector]; + var output = _chassis.Outputs[outputSelector]; + + Debug.Console(2, this, "ExecuteNumericSwitch: input={0}, output={1}", input, output); + + ExecuteSwitch(input, output, signalType); + } + + + /// + /// Enables Hdcp on the provided port + /// + /// + public void EnableHdcp(uint port) + { + if (port <= 0 || port > _chassis.NumberOfInputs) return; + + _chassis.HdmiInputs[port].InputPort.HdcpSupportOn(); + InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); + } + + + /// + /// Disables Hdcp on the provided port + /// + /// + public void DisableHdcp(uint port) + { + if (port <= 0 || port > _chassis.NumberOfInputs) return; + + _chassis.HdmiInputs[port].InputPort.HdcpSupportOff(); + InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); + } + + + /// + /// Enables switcher auto route + /// + public void EnableAutoRoute() + { + if (_chassis.NumberOfInputs == 1) return; + + _chassis.AutoRouteOn(); + } + + + /// + /// Disables switcher auto route + /// + public void DisableAutoRoute() + { + if (_chassis.NumberOfInputs == 1) return; + + _chassis.AutoRouteOff(); + } + + #region Events + + + // _chassis online/offline event + private void _chassis_OnlineStatusChange(GenericBase currentDevice, + OnlineOfflineEventArgs args) + { + IsOnline.FireUpdate(); + + if (!args.DeviceOnLine) return; + + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + + + // _chassis input change event + private void _chassis_InputChange(Switch device, DMInputEventArgs args) + { + var eventId = args.EventId; + + switch (eventId) + { + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + break; + } + case DMInputEventIds.InputNameFeedbackEventId: + case DMInputEventIds.InputNameEventId: + case DMInputEventIds.NameFeedbackEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); + + var input = args.Number; + var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; + + Debug.Console(1, this, "Input {0} Name {1}", input, name); + break; + } + default: + { + Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); + break; + } + } + + OnDmInputChange(args); + } + + + // _chassis output change event + private void _chassis_OutputChange(Switch device, DMOutputEventArgs args) + { + if (args.EventId != DMOutputEventIds.VideoOutEventId) return; + + var output = args.Number; + + var input = _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback == null + ? 0 + : _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = VideoOutputRouteFeedbacks[outputName]; + if (feedback == null) return; + + var inputPort = InputPorts.FirstOrDefault( + p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback); + + var outputPort = OutputPorts.FirstOrDefault( + p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output]); + + feedback.FireUpdate(); + + OnSwitchChange(new RoutingNumericEventArgs( + output, input, outputPort, inputPort, eRoutingSignalType.AudioVideo)); + } + + + // Raise an event when the status of a switch object changes. + private void OnSwitchChange(RoutingNumericEventArgs args) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, args); + } + + // Raise an event when the DM input changes. + private void OnDmInputChange(DMInputEventArgs args) + { + var newEvent = DmInputChange; + if (newEvent != null) newEvent(this, args); + } + + + #endregion + + + #region Factory + + + public class HdSp401ControllerFactory : EssentialsDeviceFactory + { + public HdSp401ControllerFactory() + { + TypeNames = new List() { "hdps401", "hdps402", "hdps621", "hdps622" }; + } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + var key = dc.Key; + var name = dc.Name; + var type = dc.Type.ToLower(); + + Debug.Console(1, "Factory Attempting to create new {0} device", type); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + if (props == null) + { + Debug.Console(1, "Factory failed to create new HD-PSXxx device, properties config was null"); + return null; + } + + var ipid = props.Control.IpIdInt; + + switch (type) + { + case ("hdps401"): + { + return new HdPsXxxController(key, name, new HdPs401(ipid, Global.ControlSystem), props); + } + case ("hdps402"): + { + return new HdPsXxxController(key, name, new HdPs402(ipid, Global.ControlSystem), props); + } + case ("hdps621"): + { + return new HdPsXxxController(key, name, new HdPs621(ipid, Global.ControlSystem), props); + } + case ("hdps622"): + { + return new HdPsXxxController(key, name, new HdPs622(ipid, Global.ControlSystem), props); + } + default: + { + Debug.Console(1, "Factory failed to create new {0} device", type); + return null; + } + } + } + } + + + #endregion + } + + + public class StreamCecWrapper : IKeyed, ICec + { + public string Key { get; private set; } + public Cec StreamCec { get; private set; } + + public StreamCecWrapper(string key, Cec streamCec) + { + Key = key; + StreamCec = streamCec; + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Config/HdPsXxxPropertiesConfig.cs b/src/PepperDash.Essentials.DM/Config/HdPsXxxPropertiesConfig.cs new file mode 100644 index 00000000..576b74f0 --- /dev/null +++ b/src/PepperDash.Essentials.DM/Config/HdPsXxxPropertiesConfig.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using PepperDash.Core; + +namespace PepperDash_Essentials_DM.Config +{ + public class HdPsXxxPropertiesConfig + { + [JsonProperty("control")] + public ControlPropertiesConfig Control { get; set; } + + [JsonProperty("inputs")] + public Dictionary Inputs { get; set; } + + [JsonProperty("outputs")] + public Dictionary Outputs { get; set; } + + // "inputPriorities": "1,4,3,2" + [JsonProperty("inputPriorities")] + public string InputPriorities { get; set; } + + public HdPsXxxPropertiesConfig() + { + Inputs = new Dictionary(); + Outputs = new Dictionary(); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/DGEs/Dge100Controller.cs b/src/PepperDash.Essentials.DM/Endpoints/DGEs/Dge100Controller.cs index 912f1498..9c40fdc5 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/DGEs/Dge100Controller.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/DGEs/Dge100Controller.cs @@ -19,11 +19,12 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Essentials.Core.DeviceInfo; +using PepperDash.Essentials.Core.Bridges; namespace PepperDash.Essentials.DM.Endpoints.DGEs { [Description("Wrapper class for DGE-100")] - public class Dge100Controller : CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IHasBasicTriListWithSmartObject, ICec, IDeviceInfoProvider + public class Dge100Controller : CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IHasBasicTriListWithSmartObject, ICec, IDeviceInfoProvider, IBridgeAdvanced { private const int CtpPort = 41795; private readonly Dge100 _dge; @@ -34,7 +35,10 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs private DeviceConfig _dc; - CrestronTouchpanelPropertiesConfig PropertiesConfig; + public VideoStatusOutputs VideoStatusFeedbacks { get; private set; } + + CrestronTouchpanelPropertiesConfig PropertiesConfig; + public Dge100Controller(string key, string name, Dge100 device, DeviceConfig dc, CrestronTouchpanelPropertiesConfig props) :base(key, name, device) @@ -51,7 +55,19 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs _dc = dc; PropertiesConfig = props; - } + + var videoStatusFuncs = new VideoStatusFuncsWrapper + { + HdcpActiveFeedbackFunc = () => _dge.HdmiIn.HdcpSupportOnFeedback.BoolValue, + VideoResolutionFeedbackFunc = () => _dge.HdmiIn.VideoAttributes.GetVideoResolutionString(), + VideoSyncFeedbackFunc = () => _dge.HdmiIn.SyncDetectedFeedback.BoolValue, + }; + + VideoStatusFeedbacks = new VideoStatusOutputs(videoStatusFuncs); + + _dge.HdmiIn.StreamChange += (s,a) => VideoStatusFeedbacks.FireAll(); + _dge.HdmiIn.VideoAttributes.AttributeChange += (o, a) => VideoStatusFeedbacks.FireAll(); + } #region IComPorts Members @@ -189,6 +205,63 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs handler(this, new DeviceInfoEventArgs(DeviceInfo)); } + #endregion + + #region IBridgeAdvanced Members + + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new DgeJoinMap(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."); + } + + Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + //Presses + trilist.SetSigTrueAction(joinMap.HdmiInHdcpOn.JoinNumber, () => _dge.HdmiIn.HdcpSupportOn()); + trilist.SetSigTrueAction(joinMap.HdmiInHdcpOff.JoinNumber,() => _dge.HdmiIn.HdcpSupportOff()); + trilist.SetSigTrueAction(joinMap.HdmiInHdcpToggle.JoinNumber, () => { + if(_dge.HdmiIn.HdcpSupportOnFeedback.BoolValue) + { + _dge.HdmiIn.HdcpSupportOff(); + return; + } + + _dge.HdmiIn.HdcpSupportOn(); + }); + + + // Feedbacks + VideoStatusFeedbacks.HdcpActiveFeedback.LinkInputSig(trilist.BooleanInput[joinMap.HdmiInHdcpOn.JoinNumber]); + VideoStatusFeedbacks.HdcpActiveFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.HdmiInHdcpOff.JoinNumber]); + + VideoStatusFeedbacks.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution.JoinNumber]); + VideoStatusFeedbacks.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SyncDetected.JoinNumber]); + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + + trilist.OnlineStatusChange += (o, a) => + { + if (!a.DeviceOnLine) return; + + VideoStatusFeedbacks.FireAll(); + }; + } + + + #endregion } diff --git a/src/PepperDash.Essentials.DM/Endpoints/DGEs/DgeJoinMap.cs b/src/PepperDash.Essentials.DM/Endpoints/DGEs/DgeJoinMap.cs new file mode 100644 index 00000000..f53e9383 --- /dev/null +++ b/src/PepperDash.Essentials.DM/Endpoints/DGEs/DgeJoinMap.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.DM.Endpoints.DGEs +{ + public class DgeJoinMap : JoinMapBaseAdvanced + { + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DGE Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("CurrentInputResolution")] + public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DGE Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("SyncDetected")] + public JoinDataComplete SyncDetected = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DGE Sync Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HdmiHdcpOn")] + public JoinDataComplete HdmiInHdcpOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DGE HDMI HDCP State On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HdmiHdcpOff")] + public JoinDataComplete HdmiInHdcpOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DGE HDMI HDCP State Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HdmiHdcpToggle")] + public JoinDataComplete HdmiInHdcpToggle = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "DGE HDMI HDCP State Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + public DgeJoinMap(uint joinStart) + : this(joinStart, typeof(DgeJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DgeJoinMap(uint joinStart, Type type) : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/DGEs/DmDge200CController.cs b/src/PepperDash.Essentials.DM/Endpoints/DGEs/DmDge200CController.cs index 57131d60..6198cee5 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/DGEs/DmDge200CController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/DGEs/DmDge200CController.cs @@ -60,37 +60,37 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs HdmiOut.Port = _dge.HdmiOut; ; } - - public class DmDge200CControllerFactory : EssentialsDeviceFactory - { - public DmDge200CControllerFactory() - { - TypeNames = new List() { "dmdge200c" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - var typeName = dc.Type.ToLower(); - var comm = CommFactory.GetControlPropertiesConfig(dc); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - - Debug.Console(1, "Factory Attempting to create new DgeController Device"); - - DmDge200C dgeDevice = null; - - if (typeName == "dmdge200c") - dgeDevice = new DmDge200C(comm.IpIdInt, Global.ControlSystem); - - if (dgeDevice == null) - { - Debug.Console(1, "Unable to create DGE device"); - return null; - } - - var dgeController = new DmDge200CController(dc.Key , dc.Name, dgeDevice, dc, props); - - return dgeController; - } - } } + + public class DmDge200CControllerFactory : EssentialsDeviceFactory + { + public DmDge200CControllerFactory() + { + TypeNames = new List() { "dmdge200c" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + var typeName = dc.Type.ToLower(); + var comm = CommFactory.GetControlPropertiesConfig(dc); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + + Debug.Console(1, "Factory Attempting to create new DgeController Device"); + + DmDge200C dgeDevice = null; + + if (typeName == "dmdge200c") + dgeDevice = new DmDge200C(comm.IpIdInt, Global.ControlSystem); + + if (dgeDevice == null) + { + Debug.Console(1, "Unable to create DGE device"); + return null; + } + + var dgeController = new DmDge200CController(dc.Key, dc.Name, dgeDevice, dc, props); + + return dgeController; + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/EndpointInterfaces.cs b/src/PepperDash.Essentials.DM/Endpoints/EndpointInterfaces.cs new file mode 100644 index 00000000..085d379b --- /dev/null +++ b/src/PepperDash.Essentials.DM/Endpoints/EndpointInterfaces.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DM; +using Crestron.SimplSharpPro.DM.Endpoints; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_DM +{ + public interface IHasDmInHdcpSet + { + void SetDmInHdcpState(eHdcpCapabilityType hdcpState); + } + + public interface IHasDmInHdcpGet + { + IntFeedback DmInHdcpStateFeedback { get; } + } + + public interface IHasDmInHdcp : IHasDmInHdcpGet, IHasDmInHdcpSet + { + eHdcpCapabilityType DmInHdcpCapability { get; } + } + + + public interface IHasHdmiInHdcpSet + { + void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState); + } + + public interface IHasHdmiInHdcpGet + { + IntFeedback HdmiInHdcpStateFeedback { get; } + } + + public interface IHasHdmiInHdcp : IHasHdmiInHdcpGet, IHasHdmiInHdcpSet + { + eHdcpCapabilityType HdmiInHdcpCapability { get; } + } + + + public interface IHasHdmiIn1HdcpSet + { + void SetHdmiIn1HdcpState(eHdcpCapabilityType hdcpState); + } + + public interface IHasHdmiIn1HdcpGet + { + IntFeedback HdmiIn1HdcpStateFeedback { get; } + } + + public interface IHasHdmiIn1Hdcp : IHasHdmiIn1HdcpGet, IHasHdmiIn1HdcpSet + { + eHdcpCapabilityType HdmiIn1HdcpCapability { get; } + } + + + public interface IHasHdmiIn2HdcpSet + { + void SetHdmiIn2HdcpState(eHdcpCapabilityType hdcpState); + } + + public interface IHasHdmiIn2HdcpGet + { + IntFeedback HdmiInIn2HdcpStateFeedback { get; } + } + + public interface IHasHdmi2InHdcp : IHasHdmiIn2HdcpGet, IHasHdmiIn2HdcpSet + { + eHdcpCapabilityType Hdmi2InHdcpCapability { get; } + } + + + + public interface IHasDisplayPortInHdcpGet + { + IntFeedback DisplayPortInHdcpStateFeedback { get; } + } + + public interface IHasDisplayPortInHdcpSet + { + void SetDisplayPortInHdcpState(eHdcpCapabilityType hdcpState); + } + + public interface IHasDisplayPortInHdcp : IHasDisplayPortInHdcpGet, IHasDisplayPortInHdcpSet + { + eHdcpCapabilityType DisplayPortInHdcpCapability { get; } + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs index 4a4ac67d..aab7996d 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmHdBaseTEndpointController.cs @@ -30,6 +30,8 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection {DmIn}; OutputPorts = new RoutingPortCollection {HDBaseTSink}; + PreventRegistration = true; + rmc.Register(); } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) diff --git a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4KScalerCController.cs b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4KScalerCController.cs index 8d4abadd..4496e64f 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4KScalerCController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4KScalerCController.cs @@ -6,56 +6,70 @@ using Crestron.SimplSharpPro.DM.Endpoints.Receivers; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; +using PepperDash_Essentials_DM; +using System.Collections.Generic; namespace PepperDash.Essentials.DM { - /// - /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions - /// - /// + /// + /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions + /// + /// [Description("Wrapper Class for DM-RMC-4K-SCALER-C")] public class DmRmc4kScalerCController : DmRmcControllerBase, IRoutingInputsOutputs, IBasicVolumeWithFeedback, - IIROutputPorts, IComPorts, ICec, IRelayPorts - { - private readonly DmRmc4kScalerC _rmc; + IIROutputPorts, IComPorts, ICec, IRelayPorts, IHasDmInHdcp, IBasicVideoMuteWithFeedback + { + private readonly DmRmc4kScalerC _rmc; - public RoutingInputPort DmIn { get; private set; } - public RoutingOutputPort HdmiOut { get; private set; } - public RoutingOutputPort BalancedAudioOut { get; private set; } + public RoutingInputPort DmIn { get; private set; } + public RoutingOutputPort HdmiOut { get; private set; } + public RoutingOutputPort BalancedAudioOut { get; private set; } - public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection InputPorts { get; private set; } - public RoutingPortCollection OutputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } - /// - /// Make a Crestron RMC and put it in here - /// - public DmRmc4kScalerCController(string key, string name, DmRmc4kScalerC rmc) - : base(key, name, rmc) - { - _rmc = rmc; + public EndpointDmInputStreamWithCec DmInput { get; private set; } - DmIn = new RoutingInputPort(DmPortName.DmIn, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.DmCat, 0, this); - HdmiOut = new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo, - eRoutingPortConnectionType.Hdmi, null, this); - BalancedAudioOut = new RoutingOutputPort(DmPortName.BalancedAudioOut, eRoutingSignalType.Audio, - eRoutingPortConnectionType.LineAudio, null, this); + public IntFeedback DmInHdcpStateFeedback { get; private set; } - MuteFeedback = new BoolFeedback(() => false); - VolumeLevelFeedback = new IntFeedback("MainVolumeLevelFeedback", () => - rmc.AudioOutput.VolumeFeedback.UShortValue); + + /// + /// Make a Crestron RMC and put it in here + /// + public DmRmc4kScalerCController(string key, string name, DmRmc4kScalerC rmc) + : base(key, name, rmc) + { + _rmc = rmc; + + DmIn = new RoutingInputPort(DmPortName.DmIn, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.DmCat, 0, this); + HdmiOut = new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo, + eRoutingPortConnectionType.Hdmi, null, this); + BalancedAudioOut = new RoutingOutputPort(DmPortName.BalancedAudioOut, eRoutingSignalType.Audio, + eRoutingPortConnectionType.LineAudio, null, this); + + MuteFeedback = new BoolFeedback(() => false); + + VolumeLevelFeedback = new IntFeedback("MainVolumeLevelFeedback", () => + rmc.AudioOutput.VolumeFeedback.UShortValue); EdidManufacturerFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.Manufacturer.StringValue); EdidNameFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.Name.StringValue); EdidPreferredTimingFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.PreferredTiming.StringValue); EdidSerialNumberFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.SerialNumber.StringValue); - InputPorts = new RoutingPortCollection {DmIn}; - OutputPorts = new RoutingPortCollection {HdmiOut, BalancedAudioOut}; + InputPorts = new RoutingPortCollection { DmIn }; + OutputPorts = new RoutingPortCollection { HdmiOut, BalancedAudioOut }; VideoOutputResolutionFeedback = new StringFeedback(() => _rmc.HdmiOutput.GetVideoResolutionString()); + DmInHdcpStateFeedback = new IntFeedback("DmInHdcpCapability", + () => (int)_rmc.DmInput.HdcpCapabilityFeedback); + + AddToFeedbackList(DmInHdcpStateFeedback); + + VideoMuteIsOn = new BoolFeedback("HdmiOutputVideoMuteIsOn", () => _rmc.HdmiOutput.BlankEnabledFeedback.BoolValue); _rmc.HdmiOutput.OutputStreamChange += HdmiOutput_OutputStreamChange; _rmc.HdmiOutput.ConnectedDevice.DeviceInformationChange += ConnectedDevice_DeviceInformationChange; @@ -71,6 +85,10 @@ namespace PepperDash.Essentials.DM { VideoOutputResolutionFeedback.FireUpdate(); } + else if (args.EventId == EndpointOutputStreamEventIds.BlankEnabledFeedbackEventId) + { + VideoMuteIsOn.FireUpdate(); + } } void ConnectedDevice_DeviceInformationChange(ConnectedDeviceInformation connectedDevice, ConnectedDeviceEventArgs args) @@ -92,105 +110,152 @@ namespace PepperDash.Essentials.DM } } - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkDmRmcToApi(this, trilist, joinStart, joinMapKey, bridge); - } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkDmRmcToApi(this, trilist, joinStart, joinMapKey, bridge); + } - #region IIROutputPorts Members - public CrestronCollection IROutputPorts { get { return _rmc.IROutputPorts; } } - public int NumberOfIROutputPorts { get { return _rmc.NumberOfIROutputPorts; } } - #endregion + #region IIROutputPorts Members + public CrestronCollection IROutputPorts { get { return _rmc.IROutputPorts; } } + public int NumberOfIROutputPorts { get { return _rmc.NumberOfIROutputPorts; } } + #endregion - #region IComPorts Members - public CrestronCollection ComPorts { get { return _rmc.ComPorts; } } - public int NumberOfComPorts { get { return _rmc.NumberOfComPorts; } } - #endregion + #region IComPorts Members + public CrestronCollection ComPorts { get { return _rmc.ComPorts; } } + public int NumberOfComPorts { get { return _rmc.NumberOfComPorts; } } + #endregion - #region ICec Members - /// - /// Gets the CEC stream directly from the HDMI port. - /// - public Cec StreamCec { get { return _rmc.HdmiOutput.StreamCec; } } - #endregion + #region ICec Members + /// + /// Gets the CEC stream directly from the HDMI port. + /// + public Cec StreamCec { get { return _rmc.HdmiOutput.StreamCec; } } + #endregion - #region IRelayPorts Members + #region IRelayPorts Members - public int NumberOfRelayPorts - { - get { return _rmc.NumberOfRelayPorts; } - } + public int NumberOfRelayPorts + { + get { return _rmc.NumberOfRelayPorts; } + } - public CrestronCollection RelayPorts - { - get { return _rmc.RelayPorts; } - } + public CrestronCollection RelayPorts + { + get { return _rmc.RelayPorts; } + } - #endregion + #endregion - #region IBasicVolumeWithFeedback Members + #region IBasicVolumeWithFeedback Members - public BoolFeedback MuteFeedback - { - get; - private set; - } + public BoolFeedback MuteFeedback + { + get; + private set; + } - /// - /// Not implemented - /// - public void MuteOff() - { + /// + /// Not implemented + /// + public void MuteOff() + { Debug.Console(2, this, "DM Endpoint {0} does not have a mute function", Key); - } + } - /// - /// Not implemented - /// - public void MuteOn() - { + /// + /// Not implemented + /// + public void MuteOn() + { Debug.Console(2, this, "DM Endpoint {0} does not have a mute function", Key); - } + } - public void SetVolume(ushort level) - { - _rmc.AudioOutput.Volume.UShortValue = level; - } + public void SetVolume(ushort level) + { + _rmc.AudioOutput.Volume.UShortValue = level; + } - public IntFeedback VolumeLevelFeedback - { - get; - private set; - } + public IntFeedback VolumeLevelFeedback + { + get; + private set; + } - #endregion + #endregion - #region IBasicVolumeControls Members + #region IBasicVolumeControls Members - /// - /// Not implemented - /// - public void MuteToggle() - { + /// + /// Not implemented + /// + public void MuteToggle() + { Debug.Console(2, this, "DM Endpoint {0} does not have a mute function", Key); - } + } - public void VolumeDown(bool pressRelease) - { - if (pressRelease) - SigHelper.RampTimeScaled(_rmc.AudioOutput.Volume, 0, 4000); - else - _rmc.AudioOutput.Volume.StopRamp(); - } + public void VolumeDown(bool pressRelease) + { + if (pressRelease) + SigHelper.RampTimeScaled(_rmc.AudioOutput.Volume, 0, 4000); + else + _rmc.AudioOutput.Volume.StopRamp(); + } - public void VolumeUp(bool pressRelease) - { - if (pressRelease) - SigHelper.RampTimeScaled(_rmc.AudioOutput.Volume, 65535, 4000); - else - _rmc.AudioOutput.Volume.StopRamp(); - } + public void VolumeUp(bool pressRelease) + { + if (pressRelease) + SigHelper.RampTimeScaled(_rmc.AudioOutput.Volume, 65535, 4000); + else + _rmc.AudioOutput.Volume.StopRamp(); + } - #endregion - } + #endregion + + public eHdcpCapabilityType DmInHdcpCapability + { + get { return eHdcpCapabilityType.Hdcp2_2Support; } + } + + public void SetDmInHdcpState(eHdcpCapabilityType hdcpState) + { + if (_rmc == null) return; + _rmc.DmInput.HdcpCapability = hdcpState; + } + + + #region IBasicVideoMuteWithFeedback Members + + public BoolFeedback VideoMuteIsOn + { + get; + private set; + } + + public void VideoMuteOn() + { + Debug.Console(2, this, "Video Mute On"); + _rmc.HdmiOutput.BlankEnabled(); + } + + public void VideoMuteOff() + { + Debug.Console(2, this, "Video Mute Off"); + _rmc.HdmiOutput.BlankDisabled(); + } + + #endregion + + #region IBasicVideoMute Members + + public void VideoMuteToggle() + { + Debug.Console(2, this, "Video Mute Toggle"); + if (_rmc.HdmiOutput.BlankEnabledFeedback.BoolValue == true) + VideoMuteOff(); + else + VideoMuteOn(); + } + + #endregion + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4k100C1GController.cs b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4k100C1GController.cs index 0664818d..51d2f202 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4k100C1GController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4k100C1GController.cs @@ -35,6 +35,8 @@ namespace PepperDash.Essentials.DM InputPorts = new RoutingPortCollection {DmIn}; OutputPorts = new RoutingPortCollection {HdmiOut}; + PreventRegistration = true; + rmc.Register(); } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) diff --git a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kScalerCDspController.cs b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kScalerCDspController.cs index 5c6db1aa..b83fd0e4 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kScalerCDspController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kScalerCDspController.cs @@ -5,8 +5,9 @@ using Crestron.SimplSharpPro.DM.Endpoints; using Crestron.SimplSharpPro.DM.Endpoints.Receivers; using PepperDash.Core; using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; - +using PepperDash.Essentials.Core.Bridges; +using PepperDash_Essentials_DM; + namespace PepperDash.Essentials.DM { /// @@ -15,7 +16,7 @@ namespace PepperDash.Essentials.DM /// [Description("Wrapper Class for DM-RMC-4K-SCALER-C-DSP")] public class DmRmc4kScalerCDspController : DmRmcControllerBase, IRoutingInputsOutputs, IBasicVolumeWithFeedback, - IIROutputPorts, IComPorts, ICec, IRelayPorts + IIROutputPorts, IComPorts, ICec, IRelayPorts, IHasDmInHdcp { private readonly DmRmc4kScalerCDsp _rmc; @@ -25,7 +26,12 @@ namespace PepperDash.Essentials.DM public RoutingPortCollection InputPorts { get; private set; } - public RoutingPortCollection OutputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public EndpointDmInputStreamWithCec DmInput { get; private set; } + + public IntFeedback DmInHdcpStateFeedback { get; private set; } + /// /// Make a Crestron RMC and put it in here @@ -51,7 +57,13 @@ namespace PepperDash.Essentials.DM EdidPreferredTimingFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.PreferredTiming.StringValue); EdidSerialNumberFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.SerialNumber.StringValue); - VideoOutputResolutionFeedback = new StringFeedback(() => _rmc.HdmiOutput.GetVideoResolutionString()); + VideoOutputResolutionFeedback = new StringFeedback(() => _rmc.HdmiOutput.GetVideoResolutionString()); + + DmInHdcpStateFeedback = new IntFeedback("DmInHdcpCapability", + () => (int) _rmc.DmInput.HdcpCapabilityFeedback); + + AddToFeedbackList(DmInHdcpStateFeedback); + InputPorts = new RoutingPortCollection {DmIn}; OutputPorts = new RoutingPortCollection {HdmiOut, BalancedAudioOut}; @@ -190,6 +202,18 @@ namespace PepperDash.Essentials.DM _rmc.AudioOutput.Volume.StopRamp(); } - #endregion + #endregion + + public eHdcpCapabilityType DmInHdcpCapability + { + get { return eHdcpCapabilityType.Hdcp2_2Support; } + } + + public void SetDmInHdcpState(eHdcpCapabilityType hdcpState) + { + if (_rmc == null) return; + _rmc.DmInput.HdcpCapability = hdcpState; + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs index eef6ea16..07b348e5 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs @@ -9,12 +9,13 @@ using Crestron.SimplSharpPro.DM.Endpoints.Receivers; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Core; +using PepperDash_Essentials_DM; namespace PepperDash.Essentials.DM { [Description("Wrapper Class for DM-RMC-4K-Z-SCALER-C")] public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRoutingWithFeedback, - IIROutputPorts, IComPorts, ICec, IRelayPorts + IIROutputPorts, IComPorts, ICec, IRelayPorts, IHasDmInHdcp, IHasHdmiInHdcp { private readonly DmRmc4kzScalerC _rmc; @@ -22,6 +23,13 @@ namespace PepperDash.Essentials.DM public RoutingInputPort HdmiIn { get; private set; } public RoutingOutputPort HdmiOut { get; private set; } + public IntFeedback DmInHdcpStateFeedback { get; private set; } + public IntFeedback HdmiInHdcpStateFeedback { get; private set; } + + public BoolFeedback HdmiVideoSyncFeedback { get; private set; } + + + /// /// The value of the current video source for the HDMI output on the receiver /// @@ -44,11 +52,11 @@ namespace PepperDash.Essentials.DM if (newEvent != null) newEvent(this, e); } - public DmRmc4kZScalerCController(string key, string name, DmRmc4kzScalerC rmc) : base(key, name, rmc) { _rmc = rmc; + DmIn = new RoutingInputPort(DmPortName.DmIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, 0, this) { @@ -62,6 +70,16 @@ namespace PepperDash.Essentials.DM HdmiOut = new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); + HdmiInHdcpStateFeedback = new IntFeedback("HdmiInHdcpCapability", + () => (int)_rmc.HdmiIn.HdcpCapabilityFeedback); + DmInHdcpStateFeedback = new IntFeedback("DmInHdcpCapability", + () => (int)_rmc.DmInput.HdcpCapabilityFeedback); + HdmiVideoSyncFeedback = new BoolFeedback("HdmiInVideoSync", + () => _rmc.HdmiIn.SyncDetectedFeedback.BoolValue); + + AddToFeedbackList(HdmiInHdcpStateFeedback, DmInHdcpStateFeedback, HdmiVideoSyncFeedback); + + EdidManufacturerFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.Manufacturer.StringValue); EdidNameFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.Name.StringValue); EdidPreferredTimingFeedback = new StringFeedback(() => _rmc.HdmiOutput.ConnectedDevice.PreferredTiming.StringValue); @@ -69,11 +87,13 @@ namespace PepperDash.Essentials.DM VideoOutputResolutionFeedback = new StringFeedback(() => _rmc.HdmiOutput.GetVideoResolutionString()); - InputPorts = new RoutingPortCollection {DmIn, HdmiIn}; - OutputPorts = new RoutingPortCollection {HdmiOut}; + InputPorts = new RoutingPortCollection { DmIn, HdmiIn }; + OutputPorts = new RoutingPortCollection { HdmiOut }; _rmc.HdmiOutput.OutputStreamChange += HdmiOutput_OutputStreamChange; _rmc.HdmiOutput.ConnectedDevice.DeviceInformationChange += ConnectedDevice_DeviceInformationChange; + _rmc.HdmiIn.InputStreamChange += InputStreamChangeEvent; + _rmc.DmInput.InputStreamChange += InputStreamChangeEvent; _rmc.OnlineStatusChange += _rmc_OnlineStatusChange; @@ -83,6 +103,20 @@ namespace PepperDash.Essentials.DM AudioVideoSourceNumericFeedback = new IntFeedback(() => (ushort)(_rmc.SelectedSourceFeedback)); } + void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args) + { + switch (args.EventId) + { + case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId: + if (inputStream == _rmc.HdmiIn) HdmiInHdcpStateFeedback.FireUpdate(); + if (inputStream == _rmc.DmInput) DmInHdcpStateFeedback.FireUpdate(); + break; + case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId: + if (inputStream == _rmc.HdmiIn) HdmiVideoSyncFeedback.FireUpdate(); + break; + } + } + private void _rmc_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) { AudioVideoSourceNumericFeedback.FireUpdate(); @@ -181,5 +215,31 @@ namespace PepperDash.Essentials.DM } #endregion + + + public eHdcpCapabilityType DmInHdcpCapability + { + get { return eHdcpCapabilityType.Hdcp2_2Support; } + } + + public void SetDmInHdcpState(eHdcpCapabilityType hdcpState) + { + + if (_rmc == null) return; + _rmc.DmInput.HdcpCapability = hdcpState; + } + + + public eHdcpCapabilityType HdmiInHdcpCapability + { + get { return eHdcpCapabilityType.Hdcp2_2Support; } + } + + public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) + { + if (_rmc == null) return; + _rmc.HdmiIn.HdcpCapability = hdcpState; + } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmcHelper.cs b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmcHelper.cs index 1d11db00..31836a45 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Receivers/DmRmcHelper.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; using Crestron.SimplSharpPro.DM.Cards; @@ -13,11 +14,12 @@ using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.DeviceInfo; using PepperDash.Essentials.DM.Config; using PepperDash.Essentials.Core.Config; +using PepperDash_Essentials_DM; namespace PepperDash.Essentials.DM { [Description("Wrapper class for all DM-RMC variants")] - public abstract class DmRmcControllerBase : CrestronGenericBridgeableBaseDevice, IDeviceInfoProvider + public abstract class DmRmcControllerBase : CrestronGenericBridgeableBaseDevice, IDeviceInfoProvider { private const int CtpPort = 41795; private readonly EndpointReceiverBase _rmc; //kept here just in case. Only property or method on this class that's not device-specific is the DMOutput that it's attached to. @@ -29,15 +31,15 @@ namespace PepperDash.Essentials.DM public StringFeedback EdidSerialNumberFeedback { get; protected set; } protected DmRmcControllerBase(string key, string name, EndpointReceiverBase device) - : base(key, name, device) + : base(key, name, device) { _rmc = device; - // if wired to a chassis, skip registration step in base class + // if wired to a chassis, skip registration step in base class PreventRegistration = _rmc.DMOutput != null; - + AddToFeedbackList(VideoOutputResolutionFeedback, EdidManufacturerFeedback, EdidSerialNumberFeedback, EdidNameFeedback, EdidPreferredTimingFeedback); - + DeviceInfo = new DeviceInfo(); IsOnline.OutputChange += (currentDevice, args) => { if (args.BoolValue) UpdateDeviceInfo(); }; @@ -59,8 +61,13 @@ namespace PepperDash.Essentials.DM else { Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + } + + LinkDmRmcToApi(rmc, trilist, joinMap); + } + protected void LinkDmRmcToApi(DmRmcControllerBase rmc, BasicTriList trilist, DmRmcControllerJoinMap joinMap) + { Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); @@ -75,19 +82,93 @@ namespace PepperDash.Essentials.DM rmc.EdidPreferredTimingFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidPrefferedTiming.JoinNumber]); if (rmc.EdidSerialNumberFeedback != null) rmc.EdidSerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidSerialNumber.JoinNumber]); - + + //If the device is an DM-RMC-4K-Z-SCALER-C - var routing = rmc as IRmcRouting; + var routing = rmc as IRoutingInputsOutputs; + + trilist.UShortInput[joinMap.HdcpInputPortCount.JoinNumber].UShortValue = (ushort)(routing == null + ? 1 + : routing.InputPorts.Count); if (routing == null) { return; } + var hdcpCapability = eHdcpCapabilityType.HdcpSupportOff; + if (routing.InputPorts[DmPortName.HdmiIn] != null) + { + var hdmiInHdcp = routing as IHasHdmiInHdcp; + if (hdmiInHdcp != null) + { + if (rmc.Feedbacks["HdmiInHdcpCapability"] != null) + { + var intFeedback = rmc.Feedbacks["HdmiInHdcpCapability"] as IntFeedback; + if (intFeedback != null) + intFeedback.LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState.JoinNumber]); + } + if (rmc.Feedbacks["HdmiInVideoSync"] != null) + { + var boolFeedback = rmc.Feedbacks["HdmiInVideoSync"] as BoolFeedback; + if (boolFeedback != null) + boolFeedback.LinkInputSig(trilist.BooleanInput[joinMap.HdmiInputSync.JoinNumber]); + } + hdcpCapability = hdmiInHdcp.HdmiInHdcpCapability > hdcpCapability + ? hdmiInHdcp.HdmiInHdcpCapability + : hdcpCapability; - if (routing.AudioVideoSourceNumericFeedback != null) - routing.AudioVideoSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.AudioVideoSource.JoinNumber]); + trilist.SetUShortSigAction(joinMap.Port1HdcpState.JoinNumber, a => hdmiInHdcp.SetHdmiInHdcpState((eHdcpCapabilityType)a)); + } + } + if (routing.InputPorts[DmPortName.DmIn] != null) + { + var dmInHdcp = rmc as IHasDmInHdcp; + + if (dmInHdcp != null) + { + if (rmc.Feedbacks["DmInHdcpCapability"] != null) + { + var intFeedback = rmc.Feedbacks["DmInHdcpCapability"] as IntFeedback; + if (intFeedback != null) + intFeedback.LinkInputSig(trilist.UShortInput[joinMap.Port2HdcpState.JoinNumber]); + } + + hdcpCapability = dmInHdcp.DmInHdcpCapability > hdcpCapability + ? dmInHdcp.DmInHdcpCapability + : hdcpCapability; + + + trilist.SetUShortSigAction(joinMap.Port2HdcpState.JoinNumber, a => dmInHdcp.SetDmInHdcpState((eHdcpCapabilityType)a)); + } + } + + trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)hdcpCapability; + + trilist.UShortInput[joinMap.HdcpInputPortCount.JoinNumber].UShortValue = (ushort)routing.InputPorts.Count; + + var dmRmcScalerCBasicVideoMuteWithFeedback = rmc as IBasicVideoMuteWithFeedback; + + if (dmRmcScalerCBasicVideoMuteWithFeedback != null) + { + Debug.Console(1, this, "Device is IBasicVideoMuteWithFeedback, linking video mute"); + trilist.SetSigTrueAction(joinMap.VideoMuteToggle.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteToggle()); + trilist.SetSigTrueAction(joinMap.VideoMuteOn.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteOn()); + trilist.SetSigTrueAction(joinMap.VideoMuteOff.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteOff()); + dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteIsOn.LinkInputSig(trilist.BooleanInput[joinMap.VideoMuteOn.JoinNumber]); + dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteIsOn.LinkComplementInputSig(trilist.BooleanInput[joinMap.VideoMuteOff.JoinNumber]); + } + + var routingWithFeedback = routing as IRmcRouting; + if (routingWithFeedback == null) return; + + if (routingWithFeedback.AudioVideoSourceNumericFeedback != null) + routingWithFeedback.AudioVideoSourceNumericFeedback.LinkInputSig( + trilist.UShortInput[joinMap.AudioVideoSource.JoinNumber]); + + + trilist.SetUShortSigAction(joinMap.AudioVideoSource.JoinNumber, + a => routingWithFeedback.ExecuteNumericSwitch(a, 1, eRoutingSignalType.AudioVideo)); - trilist.SetUShortSigAction(joinMap.AudioVideoSource.JoinNumber, a => routing.ExecuteNumericSwitch(a, 1, eRoutingSignalType.AudioVideo)); } #region Implementation of IDeviceInfoProvider @@ -145,13 +226,13 @@ namespace PepperDash.Essentials.DM return; } - + if (args.Text.ToLower().Contains("host")) { DeviceInfo.HostName = args.Text.Split(':')[1].Trim(); tcpClient.SendText("maca\r\n"); - + return; } @@ -204,17 +285,17 @@ namespace PepperDash.Essentials.DM } } - public class DmRmcHelper - { - private static readonly Dictionary> ProcessorFactoryDict; - private static readonly Dictionary> ChassisCpu3Dict; + public class DmRmcHelper + { + private static readonly Dictionary> ProcessorFactoryDict; + private static readonly Dictionary> ChassisCpu3Dict; - private static readonly Dictionary> - ChassisDict; + private static readonly Dictionary> + ChassisDict; - static DmRmcHelper() - { - ProcessorFactoryDict = new Dictionary> + static DmRmcHelper() + { + ProcessorFactoryDict = new Dictionary> { {"dmrmc100c", (k, n, i) => new DmRmcX100CController(k, n, new DmRmc100C(i, Global.ControlSystem))}, {"dmrmc100s", (k, n, i) => new DmRmc100SController(k, n, new DmRmc100S(i, Global.ControlSystem))}, @@ -308,31 +389,34 @@ namespace PepperDash.Essentials.DM {"dmrmc4k100c1g", (k,n,i,d) => new DmRmc4k100C1GController(k,n, new DmRmc4K100C1G(i, d))} }; } - /// - /// A factory method for various DmRmcControllers - /// - /// device key. Used to uniquely identify device - /// device name - /// device type name. Used to retrived the correct device - /// Config from config file - /// - public static CrestronGenericBaseDevice GetDmRmcController(string key, string name, string typeName, DmRmcPropertiesConfig props) - { - typeName = typeName.ToLower(); - var ipid = props.Control.IpIdInt; + /// + /// A factory method for various DmRmcControllers + /// + /// device key. Used to uniquely identify device + /// device name + /// device type name. Used to retrived the correct device + /// Config from config file + /// + public static CrestronGenericBaseDevice GetDmRmcController(string key, string name, string typeName, DmRmcPropertiesConfig props) + { + typeName = typeName.ToLower(); + var ipid = props.Control.IpIdInt; - var pKey = props.ParentDeviceKey.ToLower(); + var pKey = props.ParentDeviceKey.ToLower(); - // Non-DM-chassis endpoints - return pKey == "processor" ? GetDmRmcControllerForProcessor(key, name, typeName, ipid) : GetDmRmcControllerForChassis(key, name, typeName, props, pKey, ipid); - } + // Non-DM-chassis endpoints + return pKey == "processor" ? GetDmRmcControllerForProcessor(key, name, typeName, ipid) : GetDmRmcControllerForChassis(key, name, typeName, props, pKey, ipid); + } - private static CrestronGenericBaseDevice GetDmRmcControllerForChassis(string key, string name, string typeName, - DmRmcPropertiesConfig props, string pKey, uint ipid) - { - var parentDev = DeviceManager.GetDeviceForKey(pKey); - if (parentDev is DmpsRoutingController) - { + private static CrestronGenericBaseDevice GetDmRmcControllerForChassis(string key, string name, string typeName, + DmRmcPropertiesConfig props, string pKey, uint ipid) + { + var parentDev = DeviceManager.GetDeviceForKey(pKey); + CrestronGenericBaseDevice rx; + bool useChassisForOfflineFeedback = false; + + if (parentDev is DmpsRoutingController) + { var dmps = parentDev as DmpsRoutingController; //Check that the input is within range of this chassis' possible inputs var num = props.ParentOutputNumber; @@ -344,26 +428,37 @@ namespace PepperDash.Essentials.DM return null; } // Must use different constructor for DMPS4K types. No IPID - if (Global.ControlSystemIsDmps4kType || typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") + if (Global.ControlSystemIsDmps4kType) { - var rmc = GetDmRmcControllerForDmps4k(key, name, typeName, dmps, props.ParentOutputNumber); - Debug.Console(0, "DM endpoint output {0} is for Dmps4k, changing online feedback to chassis", num); - rmc.IsOnline.SetValueFunc(() => dmps.OutputEndpointOnlineFeedbacks[num].BoolValue); + rx = GetDmRmcControllerForDmps4k(key, name, typeName, dmps, props.ParentOutputNumber); + useChassisForOfflineFeedback = true; + } + else + { + rx = GetDmRmcControllerForDmps(key, name, typeName, ipid, dmps, props.ParentOutputNumber); + if (typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") + { + useChassisForOfflineFeedback = true; + } + } + if (useChassisForOfflineFeedback) + { + Debug.Console(0, "DM endpoint output {0} does not have direct online feedback, changing online feedback to chassis", num); + rx.IsOnline.SetValueFunc(() => dmps.OutputEndpointOnlineFeedbacks[num].BoolValue); dmps.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => { - foreach (var feedback in rmc.Feedbacks) + foreach (var feedback in rx.Feedbacks) { if (feedback != null) feedback.FireUpdate(); } }; - return rmc; } - return GetDmRmcControllerForDmps(key, name, typeName, ipid, dmps, props.ParentOutputNumber); - } - else if (parentDev is DmChassisController) + return rx; + } + else if (parentDev is IDmSwitchWithEndpointOnlineFeedback) { - var controller = parentDev as DmChassisController; + var controller = parentDev as IDmSwitchWithEndpointOnlineFeedback; var chassis = controller.Chassis; var num = props.ParentOutputNumber; Debug.Console(1, "Creating DM Chassis device '{0}'. Output number '{1}'.", key, num); @@ -373,7 +468,7 @@ namespace PepperDash.Essentials.DM Debug.Console(0, "Cannot create DM device '{0}'. Output number '{1}' is out of range", key, num); return null; - } + } controller.RxDictionary.Add(num, key); // Catch constructor failures, mainly dues to IPID try @@ -382,23 +477,33 @@ namespace PepperDash.Essentials.DM if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps || - chassis is DmMd128x128 || chassis is DmMd64x64 - || typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") + chassis is DmMd128x128 || chassis is DmMd64x64) { - var rmc = GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); - Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - rmc.IsOnline.SetValueFunc(() => controller.OutputEndpointOnlineFeedbacks[num].BoolValue); - controller.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => - { - foreach (var feedback in rmc.Feedbacks) - { - if (feedback != null) - feedback.FireUpdate(); - } - }; - return rmc; + rx = GetDmRmcControllerForCpu3Chassis(key, name, typeName, chassis, num, parentDev); + useChassisForOfflineFeedback = true; } - return GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); + else + { + rx = GetDmRmcControllerForCpu2Chassis(key, name, typeName, ipid, chassis, num, parentDev); + if (typeName == "hdbasetrx" || typeName == "dmrmc4k100c1g") + { + useChassisForOfflineFeedback = true; + } + } + if (useChassisForOfflineFeedback) + { + Debug.Console(0, "DM endpoint output {0} does not have direct online feedback, changing online feedback to chassis", num); + rx.IsOnline.SetValueFunc(() => controller.OutputEndpointOnlineFeedbacks[num].BoolValue); + controller.OutputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => + { + foreach (var feedback in rx.Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } + }; + } + return rx; } catch (Exception e) { @@ -412,31 +517,31 @@ namespace PepperDash.Essentials.DM key, pKey); return null; } - } + } - private static CrestronGenericBaseDevice GetDmRmcControllerForCpu2Chassis(string key, string name, string typeName, - uint ipid, Switch chassis, uint num, IKeyed parentDev) - { - Func handler; - if (ChassisDict.TryGetValue(typeName.ToLower(), out handler)) - { - return handler(key, name, ipid, chassis.Outputs[num]); - } - Debug.Console(0, "Cannot create DM-RMC of type '{0}' with parent device {1}", typeName, parentDev.Key); - return null; - } + private static CrestronGenericBaseDevice GetDmRmcControllerForCpu2Chassis(string key, string name, string typeName, + uint ipid, Switch chassis, uint num, IKeyed parentDev) + { + Func handler; + if (ChassisDict.TryGetValue(typeName.ToLower(), out handler)) + { + return handler(key, name, ipid, chassis.Outputs[num]); + } + Debug.Console(0, "Cannot create DM-RMC of type '{0}' with parent device {1}", typeName, parentDev.Key); + return null; + } - private static CrestronGenericBaseDevice GetDmRmcControllerForCpu3Chassis(string key, string name, string typeName, - Switch chassis, uint num, IKeyed parentDev) - { - Func cpu3Handler; - if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out cpu3Handler)) - { - return cpu3Handler(key, name, chassis.Outputs[num]); - } - Debug.Console(0, "Cannot create DM-RMC of type '{0}' with parent device {1}", typeName, parentDev.Key); - return null; - } + private static CrestronGenericBaseDevice GetDmRmcControllerForCpu3Chassis(string key, string name, string typeName, + Switch chassis, uint num, IKeyed parentDev) + { + Func cpu3Handler; + if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out cpu3Handler)) + { + return cpu3Handler(key, name, chassis.Outputs[num]); + } + Debug.Console(0, "Cannot create DM-RMC of type '{0}' with parent device {1}", typeName, parentDev.Key); + return null; + } private static CrestronGenericBaseDevice GetDmRmcControllerForDmps(string key, string name, string typeName, uint ipid, DmpsRoutingController controller, uint num) @@ -460,51 +565,49 @@ namespace PepperDash.Essentials.DM return null; } - private static CrestronGenericBaseDevice GetDmRmcControllerForDmps4k(string key, string name, string typeName, - DmpsRoutingController controller, uint num) - { - Func dmps4kHandler; - if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out dmps4kHandler)) - { - var output = controller.Dmps.SwitcherOutputs[num] as DMOutput; + private static CrestronGenericBaseDevice GetDmRmcControllerForDmps4k(string key, string name, string typeName, + DmpsRoutingController controller, uint num) + { + Func dmps4kHandler; + if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out dmps4kHandler)) + { + var output = controller.Dmps.SwitcherOutputs[num] as DMOutput; - if (output != null) - { - return dmps4kHandler(key, name, output); - } - Debug.Console(0, Debug.ErrorLogLevel.Error, - "Cannot attach DM-RMC of type '{0}' to output {1} on DMPS-4K chassis. Output is not a DM Output.", - typeName, num); - return null; - } + if (output != null) + { + return dmps4kHandler(key, name, output); + } + Debug.Console(0, Debug.ErrorLogLevel.Error, + "Cannot attach DM-RMC of type '{0}' to output {1} on DMPS-4K chassis. Output is not a DM Output.", + typeName, num); + return null; + } Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot create DM-RMC of type '{0}' to output {1} on DMPS-4K chassis", typeName, num); - return null; - } + return null; + } - private static CrestronGenericBaseDevice GetDmRmcControllerForProcessor(string key, string name, string typeName, uint ipid) - { - try - { - Func handler; + private static CrestronGenericBaseDevice GetDmRmcControllerForProcessor(string key, string name, string typeName, uint ipid) + { + try + { + Func handler; - if (ProcessorFactoryDict.TryGetValue(typeName.ToLower(), out handler)) - { - return handler(key, name, ipid); - } - Debug.Console(0, "Cannot create DM-RMC of type: '{0}'", typeName); + if (ProcessorFactoryDict.TryGetValue(typeName.ToLower(), out handler)) + { + return handler(key, name, ipid); + } + Debug.Console(0, "Cannot create DM-RMC of type: '{0}'", typeName); - return null; - } - catch (Exception e) - { - Debug.Console(0, "[{0}] WARNING: Cannot create DM-RMC device: {1}", key, e.Message); return null; - } - } - - - } + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-RMC device: {1}", key, e.Message); + return null; + } + } + } public class DmRmcControllerFactory : EssentialsDeviceFactory { @@ -524,7 +627,7 @@ namespace PepperDash.Essentials.DM var props = JsonConvert.DeserializeObject (dc.Properties.ToString()); - return DmRmcHelper.GetDmRmcController(dc.Key, dc.Name, type, props); + return DmRmcHelper.GetDmRmcController(dc.Key, dc.Name, type, props); } } diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k100Controller.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k100Controller.cs index d628110d..06d65e6c 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k100Controller.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k100Controller.cs @@ -80,6 +80,8 @@ namespace PepperDash.Essentials.DM IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); } + PreventRegistration = true; + tx.Register(); } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k202CController.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k202CController.cs index e39816d1..8d13a80f 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k202CController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k202CController.cs @@ -127,28 +127,23 @@ namespace PepperDash.Essentials.DM Tx.OnlineStatusChange += Tx_OnlineStatusChange; - VideoSourceNumericFeedback = new IntFeedback(() => (int) Tx.VideoSourceFeedback); + VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback); - AudioSourceNumericFeedback = new IntFeedback(() => (int) Tx.AudioSourceFeedback); + AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.AudioSourceFeedback); HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", - () => (int) tx.HdmiInputs[1].HdcpCapabilityFeedback); + () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback); HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", - () => (int) tx.HdmiInputs[2].HdcpCapabilityFeedback); - - HdcpStateFeedback = - new IntFeedback( - () => - tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback - ? (int) tx.HdmiInputs[1].HdcpCapabilityFeedback - : (int) tx.HdmiInputs[2].HdcpCapabilityFeedback); + () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support; - Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool) tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue); + HdcpStateFeedback = new IntFeedback(() => (int)HdcpSupportCapability); - Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool) tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue); + Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue); + + Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue); var combinedFuncs = new VideoStatusFuncsWrapper { @@ -249,50 +244,50 @@ namespace PepperDash.Essentials.DM switch (input) { case 0: - { - ExecuteSwitch(eVst.Auto, null, type); - break; - } + { + ExecuteSwitch(eVst.Auto, null, type); + break; + } case 1: - { - ExecuteSwitch(HdmiIn1.Selector, null, type); - break; - } + { + ExecuteSwitch(HdmiIn1.Selector, null, type); + break; + } case 2: - { - ExecuteSwitch(HdmiIn2.Selector, null, type); - break; - } + { + ExecuteSwitch(HdmiIn2.Selector, null, type); + break; + } case 3: - { - ExecuteSwitch(eVst.AllDisabled, null, type); - break; - } + { + ExecuteSwitch(eVst.AllDisabled, null, type); + break; + } } break; case eRoutingSignalType.Audio: switch (input) { case 0: - { - ExecuteSwitch(eAst.Auto, null, type); - break; - } + { + ExecuteSwitch(eAst.Auto, null, type); + break; + } case 1: - { - ExecuteSwitch(eAst.Hdmi1, null, type); - break; - } + { + ExecuteSwitch(eAst.Hdmi1, null, type); + break; + } case 2: - { - ExecuteSwitch(eAst.Hdmi2, null, type); - break; - } + { + ExecuteSwitch(eAst.Hdmi2, null, type); + break; + } case 3: - { - ExecuteSwitch(eAst.AllDisabled, null, type); - break; - } + { + ExecuteSwitch(eAst.AllDisabled, null, type); + break; + } } break; } diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k302CController.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k302CController.cs index f8bbeb10..fd3368ae 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k302CController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4k302CController.cs @@ -17,22 +17,22 @@ using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM { - using eVst = Crestron.SimplSharpPro.DeviceSupport.eX02VideoSourceType; + using eVst = Crestron.SimplSharpPro.DeviceSupport.eX02VideoSourceType; using eAst = Crestron.SimplSharpPro.DeviceSupport.eX02AudioSourceType; [Description("Wrapper class for DM-TX-4K-302-C")] - public class DmTx4k302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback, - IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls - { - public DmTx4k302C Tx { get; private set; } + public class DmTx4k302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback, + IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls + { + public DmTx4k302C Tx { get; private set; } - public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; } - public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; } - public RoutingInputPortWithVideoStatuses VgaIn { get; private set; } - public RoutingOutputPort DmOut { get; private set; } - public RoutingOutputPort HdmiLoopOut { get; private set; } + public RoutingInputPortWithVideoStatuses HdmiIn1 { get; private set; } + public RoutingInputPortWithVideoStatuses HdmiIn2 { get; private set; } + public RoutingInputPortWithVideoStatuses VgaIn { get; private set; } + public RoutingOutputPort DmOut { get; private set; } + public RoutingOutputPort HdmiLoopOut { get; private set; } - public override StringFeedback ActiveVideoInputFeedback { get; protected set; } + public override StringFeedback ActiveVideoInputFeedback { get; protected set; } public IntFeedback VideoSourceNumericFeedback { get; protected set; } public IntFeedback AudioSourceNumericFeedback { get; protected set; } public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; } @@ -60,78 +60,78 @@ namespace PepperDash.Essentials.DM } - /// - /// Helps get the "real" inputs, including when in Auto - /// - public Crestron.SimplSharpPro.DeviceSupport.eX02VideoSourceType ActualActiveVideoInput - { - get - { - if (Tx.VideoSourceFeedback != eVst.Auto) - return Tx.VideoSourceFeedback; - else // auto - { - if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) - return eVst.Hdmi1; - else if (Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) - return eVst.Hdmi2; - else if (Tx.VgaInput.SyncDetectedFeedback.BoolValue) - return eVst.Vga; - else - return eVst.AllDisabled; - } - } - } - public RoutingPortCollection InputPorts - { - get - { - return new RoutingPortCollection + /// + /// Helps get the "real" inputs, including when in Auto + /// + public Crestron.SimplSharpPro.DeviceSupport.eX02VideoSourceType ActualActiveVideoInput + { + get + { + if (Tx.VideoSourceFeedback != eVst.Auto) + return Tx.VideoSourceFeedback; + else // auto + { + if (Tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) + return eVst.Hdmi1; + else if (Tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) + return eVst.Hdmi2; + else if (Tx.VgaInput.SyncDetectedFeedback.BoolValue) + return eVst.Vga; + else + return eVst.AllDisabled; + } + } + } + public RoutingPortCollection InputPorts + { + get + { + return new RoutingPortCollection { HdmiIn1, HdmiIn2, VgaIn, AnyVideoInput }; - } - } - public RoutingPortCollection OutputPorts - { - get - { - return new RoutingPortCollection { DmOut, HdmiLoopOut }; - } - } + } + } + public RoutingPortCollection OutputPorts + { + get + { + return new RoutingPortCollection { DmOut, HdmiLoopOut }; + } + } public DmTx4k302CController(string key, string name, DmTx4k302C tx, bool preventRegistration) - : base(key, name, tx) - { - Tx = tx; + : base(key, name, tx) + { + Tx = tx; PreventRegistration = preventRegistration; - HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, + HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this, - VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1])) - { - FeedbackMatchObject = eVst.Hdmi1 - }; - HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2, + VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1])) + { + FeedbackMatchObject = eVst.Hdmi1 + }; + HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this, - VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2])) + VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2])) { FeedbackMatchObject = eVst.Hdmi2 }; - - VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn, - eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eVst.Vga, this, - VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput)) + + VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn, + eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eVst.Vga, this, + VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput)) { FeedbackMatchObject = eVst.Vga }; - ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput", - () => ActualActiveVideoInput.ToString()); + ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput", + () => ActualActiveVideoInput.ToString()); - Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent; + Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent; Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent; Tx.VgaInput.InputStreamChange += VgaInputOnInputStreamChange; Tx.BaseEvent += Tx_BaseEvent; @@ -145,15 +145,10 @@ namespace PepperDash.Essentials.DM HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); - HdcpStateFeedback = - new IntFeedback( - () => - tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback - ? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback - : (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); - HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support; + HdcpStateFeedback = new IntFeedback(() => (int)HdcpSupportCapability); + Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue); Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue); @@ -168,46 +163,46 @@ namespace PepperDash.Essentials.DM tx.VgaInput.VideoControls.ControlChange += new Crestron.SimplSharpPro.DeviceSupport.GenericEventHandler(VideoControls_ControlChange); - var combinedFuncs = new VideoStatusFuncsWrapper - { - HdcpActiveFeedbackFunc = () => - (ActualActiveVideoInput == eVst.Hdmi1 - && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue) - || (ActualActiveVideoInput == eVst.Hdmi2 - && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue), + var combinedFuncs = new VideoStatusFuncsWrapper + { + HdcpActiveFeedbackFunc = () => + (ActualActiveVideoInput == eVst.Hdmi1 + && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.Hdmi2 + && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue), - HdcpStateFeedbackFunc = () => - { - if (ActualActiveVideoInput == eVst.Hdmi1) - return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString(); - return ActualActiveVideoInput == eVst.Hdmi2 ? tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString() : ""; - }, + HdcpStateFeedbackFunc = () => + { + if (ActualActiveVideoInput == eVst.Hdmi1) + return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString(); + return ActualActiveVideoInput == eVst.Hdmi2 ? tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString() : ""; + }, - VideoResolutionFeedbackFunc = () => - { - if (ActualActiveVideoInput == eVst.Hdmi1) - return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString(); - if (ActualActiveVideoInput == eVst.Hdmi2) - return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString(); - return ActualActiveVideoInput == eVst.Vga ? tx.VgaInput.VideoAttributes.GetVideoResolutionString() : ""; - }, - VideoSyncFeedbackFunc = () => - (ActualActiveVideoInput == eVst.Hdmi1 - && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) - || (ActualActiveVideoInput == eVst.Hdmi2 - && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) - || (ActualActiveVideoInput == eVst.Vga - && tx.VgaInput.SyncDetectedFeedback.BoolValue) - - }; + VideoResolutionFeedbackFunc = () => + { + if (ActualActiveVideoInput == eVst.Hdmi1) + return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString(); + if (ActualActiveVideoInput == eVst.Hdmi2) + return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString(); + return ActualActiveVideoInput == eVst.Vga ? tx.VgaInput.VideoAttributes.GetVideoResolutionString() : ""; + }, + VideoSyncFeedbackFunc = () => + (ActualActiveVideoInput == eVst.Hdmi1 + && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.Hdmi2 + && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.Vga + && tx.VgaInput.SyncDetectedFeedback.BoolValue) - AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, - eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs); + }; - DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.DmCat, null, this); - HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.Hdmi, null, this); + AnyVideoInput = new RoutingInputPortWithVideoStatuses(DmPortName.AnyVideoIn, + eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.None, 0, this, combinedFuncs); + + DmOut = new RoutingOutputPort(DmPortName.DmOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.DmCat, null, this); + HdmiLoopOut = new RoutingOutputPort(DmPortName.HdmiLoopOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.Hdmi, null, this); AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback, @@ -221,7 +216,7 @@ namespace PepperDash.Essentials.DM HdmiIn2.Port = Tx.HdmiInputs[2]; HdmiLoopOut.Port = Tx.HdmiOutput; DmOut.Port = Tx.DmOutput; - } + } void VgaInputOnInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args) { @@ -254,21 +249,21 @@ namespace PepperDash.Essentials.DM - public override bool CustomActivate() - { - // Link up all of these damned events to the various RoutingPorts via a helper handler - Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId); - Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId); + public override bool CustomActivate() + { + // Link up all of these damned events to the various RoutingPorts via a helper handler + Tx.HdmiInputs[1].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn1, a.EventId); + Tx.HdmiInputs[1].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn1, a.EventId); - Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId); - Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId); + Tx.HdmiInputs[2].InputStreamChange += (o, a) => FowardInputStreamChange(HdmiIn2, a.EventId); + Tx.HdmiInputs[2].VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(HdmiIn2, a.EventId); - Tx.VgaInput.InputStreamChange += (o, a) => FowardInputStreamChange(VgaIn, a.EventId); - Tx.VgaInput.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(VgaIn, a.EventId); + Tx.VgaInput.InputStreamChange += (o, a) => FowardInputStreamChange(VgaIn, a.EventId); + Tx.VgaInput.VideoAttributes.AttributeChange += (o, a) => ForwardVideoAttributeChange(VgaIn, a.EventId); - // Base does register and sets up comm monitoring. - return base.CustomActivate(); - } + // Base does register and sets up comm monitoring. + return base.CustomActivate(); + } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { @@ -329,60 +324,60 @@ namespace PepperDash.Essentials.DM switch (input) { case 0: - { - ExecuteSwitch(eVst.Auto, null, type); - break; - } + { + ExecuteSwitch(eVst.Auto, null, type); + break; + } case 1: - { - ExecuteSwitch(HdmiIn1.Selector, null, type); - break; - } + { + ExecuteSwitch(HdmiIn1.Selector, null, type); + break; + } case 2: - { - ExecuteSwitch(HdmiIn2.Selector, null, type); - break; - } + { + ExecuteSwitch(HdmiIn2.Selector, null, type); + break; + } case 3: - { - ExecuteSwitch(VgaIn.Selector, null, type); - break; - } + { + ExecuteSwitch(VgaIn.Selector, null, type); + break; + } case 4: - { - ExecuteSwitch(eVst.AllDisabled, null, type); - break; - } + { + ExecuteSwitch(eVst.AllDisabled, null, type); + break; + } } break; case eRoutingSignalType.Audio: switch (input) { case 0: - { - ExecuteSwitch(eAst.Auto, null, type); - break; - } + { + ExecuteSwitch(eAst.Auto, null, type); + break; + } case 1: - { - ExecuteSwitch(eAst.Hdmi1, null, type); - break; - } + { + ExecuteSwitch(eAst.Hdmi1, null, type); + break; + } case 2: - { - ExecuteSwitch(eAst.Hdmi2, null, type); - break; - } + { + ExecuteSwitch(eAst.Hdmi2, null, type); + break; + } case 3: - { - ExecuteSwitch(eAst.AudioIn, null, type); - break; - } + { + ExecuteSwitch(eAst.AudioIn, null, type); + break; + } case 4: - { - ExecuteSwitch(eAst.AllDisabled, null, type); - break; - } + { + ExecuteSwitch(eAst.AllDisabled, null, type); + break; + } } break; } @@ -453,54 +448,54 @@ namespace PepperDash.Essentials.DM } /// - /// Relays the input stream change to the appropriate RoutingInputPort. - /// - void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) - { + /// Relays the input stream change to the appropriate RoutingInputPort. + /// + void FowardInputStreamChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) + { if (eventId != EndpointInputStreamEventIds.SyncDetectedFeedbackEventId) return; inputPort.VideoStatus.VideoSyncFeedback.FireUpdate(); AnyVideoInput.VideoStatus.VideoSyncFeedback.FireUpdate(); - } - - /// - /// Relays the VideoAttributes change to a RoutingInputPort - /// - void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) - { - //// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds - //Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}", - // args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType()); - switch (eventId) - { - case VideoAttributeEventIds.HdcpActiveFeedbackEventId: - inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate(); - break; - case VideoAttributeEventIds.HdcpStateFeedbackEventId: - inputPort.VideoStatus.HdcpStateFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate(); - break; - case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId: - case VideoAttributeEventIds.VerticalResolutionFeedbackEventId: - inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); - AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); - break; + } + + /// + /// Relays the VideoAttributes change to a RoutingInputPort + /// + void ForwardVideoAttributeChange(RoutingInputPortWithVideoStatuses inputPort, int eventId) + { + //// LOCATION: Crestron.SimplSharpPro.DM.VideoAttributeEventIds + //Debug.Console(2, this, "VideoAttributes_AttributeChange event id={0} from {1}", + // args.EventId, (sender as VideoAttributesEnhanced).Owner.GetType()); + switch (eventId) + { + case VideoAttributeEventIds.HdcpActiveFeedbackEventId: + inputPort.VideoStatus.HdcpActiveFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.HdcpActiveFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.HdcpStateFeedbackEventId: + inputPort.VideoStatus.HdcpStateFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.HdcpStateFeedback.FireUpdate(); + break; + case VideoAttributeEventIds.HorizontalResolutionFeedbackEventId: + case VideoAttributeEventIds.VerticalResolutionFeedbackEventId: + inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); + AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); + break; case VideoAttributeEventIds.FramesPerSecondFeedbackEventId: inputPort.VideoStatus.VideoResolutionFeedback.FireUpdate(); AnyVideoInput.VideoStatus.VideoResolutionFeedback.FireUpdate(); break; - } - } + } + } - #region IIROutputPorts Members - public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } } - public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } } - #endregion + #region IIROutputPorts Members + public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } } + public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } } + #endregion - #region IComPorts Members - public CrestronCollection ComPorts { get { return Tx.ComPorts; } } - public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } } - #endregion - } -} \ No newline at end of file + #region IComPorts Members + public CrestronCollection ComPorts { get { return Tx.ComPorts; } } + public int NumberOfComPorts { get { return Tx.NumberOfComPorts; } } + #endregion + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz100Controller.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz100Controller.cs index 2778082d..c0ef7eba 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz100Controller.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz100Controller.cs @@ -72,6 +72,7 @@ namespace PepperDash.Essentials.DM HdmiIn.Port = Tx; PreventRegistration = true; + tx.Register(); } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz302CController.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz302CController.cs index 90976a10..8a212be9 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz302CController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTx4kz302CController.cs @@ -18,7 +18,7 @@ namespace PepperDash.Essentials.DM [Description("Wrapper class for DM-TX-4K-Z-302-C")] - public class DmTx4kz302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback, + public class DmTx4kz302CController : DmTxControllerBase, ITxRoutingWithFeedback, IIROutputPorts, IComPorts { public DmTx4kz302C Tx { get; private set; } @@ -34,6 +34,7 @@ namespace PepperDash.Essentials.DM public IntFeedback AudioSourceNumericFeedback { get; protected set; } public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; } public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; } + public IntFeedback DisplayPortInHdcpCapabilityFeedback { get; protected set; } public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; } public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; } public BoolFeedback DisplayPortVideoSyncFeedback { get; protected set; } @@ -120,7 +121,7 @@ namespace PepperDash.Essentials.DM Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent; Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent; - Tx.DisplayPortInput.InputStreamChange += DisplayPortInputStreamChange; + Tx.DisplayPortInput.InputStreamChange += InputStreamChangeEvent; Tx.BaseEvent += Tx_BaseEvent; Tx.OnlineStatusChange += Tx_OnlineStatusChange; @@ -130,15 +131,32 @@ namespace PepperDash.Essentials.DM HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (int)tx.HdmiInputs[1].HdcpCapabilityFeedback); HdmiIn2HdcpCapabilityFeedback = new IntFeedback("HdmiIn2HdcpCapability", () => (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); + DisplayPortInHdcpCapabilityFeedback = new IntFeedback("DisplayPortInHdcpCapability", + () => (int)tx.DisplayPortInput.HdcpCapabilityFeedback); + + /* HdcpStateFeedback = new IntFeedback( () => tx.HdmiInputs[1].HdcpCapabilityFeedback > tx.HdmiInputs[2].HdcpCapabilityFeedback ? (int)tx.HdmiInputs[1].HdcpCapabilityFeedback : (int)tx.HdmiInputs[2].HdcpCapabilityFeedback); + */ + + //yeah this is gross - but it's the quickest way to do this... + /* + HdcpStateFeedback = new IntFeedback(() => { + var states = new[] {(int) tx.DisplayPortInput.HdcpCapabilityFeedback, (int) tx.HdmiInputs[1].HdcpCapabilityFeedback, (int) tx.HdmiInputs[2].HdcpCapabilityFeedback}; + + return states.Max(); + }); + */ HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support; + // I feel like we have had this as a misnomer for so long, that it really needed to be fixed + // All we were doing was reporting the best of the current statuses - not the actual capability of the device. + HdcpStateFeedback = new IntFeedback(() => (int)HdcpSupportCapability); Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue); @@ -146,20 +164,25 @@ namespace PepperDash.Essentials.DM DisplayPortVideoSyncFeedback = new BoolFeedback(() => (bool)tx.DisplayPortInput.SyncDetectedFeedback.BoolValue); - var combinedFuncs = new VideoStatusFuncsWrapper { HdcpActiveFeedbackFunc = () => (ActualActiveVideoInput == eVst.Hdmi1 && tx.HdmiInputs[1].VideoAttributes.HdcpActiveFeedback.BoolValue) || (ActualActiveVideoInput == eVst.Hdmi2 - && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue), + && tx.HdmiInputs[2].VideoAttributes.HdcpActiveFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.DisplayPort + && tx.DisplayPortInput.VideoAttributes.HdcpActiveFeedback.BoolValue), HdcpStateFeedbackFunc = () => { if (ActualActiveVideoInput == eVst.Hdmi1) - return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString(); - return ActualActiveVideoInput == eVst.Hdmi2 ? tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString() : ""; + return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString(); + if (ActualActiveVideoInput == eVst.Hdmi2) + return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString(); + return ActualActiveVideoInput == eVst.DisplayPort + ? tx.DisplayPortInput.VideoAttributes.HdcpStateFeedback.ToString() + : ""; }, VideoResolutionFeedbackFunc = () => @@ -168,6 +191,8 @@ namespace PepperDash.Essentials.DM return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString(); if (ActualActiveVideoInput == eVst.Hdmi2) return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString(); + if (ActualActiveVideoInput == eVst.DisplayPort) + return tx.DisplayPortInput.VideoAttributes.GetVideoResolutionString(); return ActualActiveVideoInput == eVst.Vga ? tx.DisplayPortInput.VideoAttributes.GetVideoResolutionString() : ""; }, VideoSyncFeedbackFunc = () => @@ -175,6 +200,8 @@ namespace PepperDash.Essentials.DM && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue) || (ActualActiveVideoInput == eVst.Hdmi2 && tx.HdmiInputs[2].SyncDetectedFeedback.BoolValue) + || (ActualActiveVideoInput == eVst.DisplayPort + && tx.DisplayPortInput.SyncDetectedFeedback.BoolValue) || (ActualActiveVideoInput == eVst.Vga && tx.DisplayPortInput.SyncDetectedFeedback.BoolValue) @@ -193,28 +220,15 @@ namespace PepperDash.Essentials.DM AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback, AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback, AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback, - Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback, DisplayPortVideoSyncFeedback); + Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback, DisplayPortVideoSyncFeedback, DisplayPortInHdcpCapabilityFeedback); - // Set Ports for CEC HdmiIn1.Port = Tx.HdmiInputs[1]; HdmiIn2.Port = Tx.HdmiInputs[2]; + DisplayPortIn.Port = Tx.DisplayPortInput; HdmiLoopOut.Port = Tx.HdmiOutput; DmOut.Port = Tx.DmOutput; } - void DisplayPortInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args) - { - Debug.Console(2, "{0} event {1} stream {2}", Tx.ToString(), inputStream.ToString(), args.EventId.ToString()); - - switch (args.EventId) - { - case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId: - DisplayPortVideoSyncFeedback.FireUpdate(); - break; - } - } - - public override bool CustomActivate() { @@ -256,41 +270,41 @@ namespace PepperDash.Essentials.DM { Debug.Console(2, this, "Executing Numeric Switch to input {0}.", input); - switch (input) - { - case 0: - { - ExecuteSwitch(eVst.Auto, null, type); - break; - } - case 1: - { - ExecuteSwitch(HdmiIn1.Selector, null, type); - break; - } - case 2: - { - ExecuteSwitch(HdmiIn2.Selector, null, type); - break; - } - case 3: - { - ExecuteSwitch(DisplayPortIn.Selector, null, type); - break; - } - case 4: - { - ExecuteSwitch(eVst.AllDisabled, null, type); - break; - } - default: + switch (input) + { + case 0: + { + ExecuteSwitch(eVst.Auto, null, type); + break; + } + case 1: + { + ExecuteSwitch(HdmiIn1.Selector, null, type); + break; + } + case 2: + { + ExecuteSwitch(HdmiIn2.Selector, null, type); + break; + } + case 3: + { + ExecuteSwitch(DisplayPortIn.Selector, null, type); + break; + } + case 4: + { + ExecuteSwitch(eVst.AllDisabled, null, type); + break; + } + default: { Debug.Console(2, this, "Unable to execute numeric switch to input {0}", input); break; } - } - + } + } @@ -326,11 +340,17 @@ namespace PepperDash.Essentials.DM case EndpointInputStreamEventIds.HdcpCapabilityFeedbackEventId: if (inputStream == Tx.HdmiInputs[1]) HdmiIn1HdcpCapabilityFeedback.FireUpdate(); if (inputStream == Tx.HdmiInputs[2]) HdmiIn2HdcpCapabilityFeedback.FireUpdate(); + if (inputStream == Tx.DisplayPortInput) DisplayPortInHdcpCapabilityFeedback.FireUpdate(); + + Debug.Console(2, this, "DisplayPortHDCP Mode Trigger = {0}", + DisplayPortInHdcpCapabilityFeedback.IntValue); + HdcpStateFeedback.FireUpdate(); break; case EndpointInputStreamEventIds.SyncDetectedFeedbackEventId: if (inputStream == Tx.HdmiInputs[1]) Hdmi1VideoSyncFeedback.FireUpdate(); if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate(); + if (inputStream == Tx.DisplayPortInput) DisplayPortVideoSyncFeedback.FireUpdate(); break; } } @@ -413,7 +433,6 @@ namespace PepperDash.Essentials.DM } } - #region IIROutputPorts Members public CrestronCollection IROutputPorts { get { return Tx.IROutputPorts; } } public int NumberOfIROutputPorts { get { return Tx.NumberOfIROutputPorts; } } diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTxHelpers.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTxHelpers.cs index 222fab39..4ba15c73 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTxHelpers.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/DmTxHelpers.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; @@ -20,8 +18,8 @@ using PepperDash.Essentials.Core.Config; namespace PepperDash.Essentials.DM { - public class DmTxHelper - { + public class DmTxHelper + { public static BasicDmTxControllerBase GetDmTxForChassisWithoutIpId(string key, string name, string typeName, DMInput dmInput) { @@ -46,7 +44,7 @@ namespace PepperDash.Essentials.DM if (typeName.StartsWith("dmtx401")) return new DmTx401CController(key, name, new DmTx401C(dmInput), true); if (typeName.StartsWith("hdbasettx")) - new HDBaseTTxController(key, name, new HDTx3CB(dmInput)); + return new HDBaseTTxController(key, name, new HDTx3CB(dmInput)); return null; } @@ -79,31 +77,32 @@ namespace PepperDash.Essentials.DM return null; } - /// - /// A factory method for various DmTxControllers - /// - /// - /// - /// - /// + /// + /// A factory method for various DmTxControllers + /// + /// + /// + /// + /// + /// public static BasicDmTxControllerBase GetDmTxController(string key, string name, string typeName, DmTxPropertiesConfig props) - { - // switch on type name... later... + { + // switch on type name... later... - typeName = typeName.ToLower(); - //uint ipid = Convert.ToUInt16(props.Id, 16); - var ipid = props.Control.IpIdInt; - var pKey = props.ParentDeviceKey.ToLower(); + typeName = typeName.ToLower(); + //uint ipid = Convert.ToUInt16(props.Id, 16); + var ipid = props.Control.IpIdInt; + var pKey = props.ParentDeviceKey.ToLower(); if (pKey == "processor") - { - // Catch constructor failures, mainly dues to IPID - try - { - if(typeName.StartsWith("dmtx200")) + { + // Catch constructor failures, mainly dues to IPID + try + { + if (typeName.StartsWith("dmtx200")) return new DmTx200Controller(key, name, new DmTx200C2G(ipid, Global.ControlSystem), false); - if (typeName.StartsWith("dmtx201c")) - return new DmTx201CController(key, name, new DmTx201C(ipid, Global.ControlSystem), false); + if (typeName.StartsWith("dmtx201c")) + return new DmTx201CController(key, name, new DmTx201C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx201s")) return new DmTx201SController(key, name, new DmTx201S(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4k202")) @@ -114,35 +113,36 @@ namespace PepperDash.Essentials.DM return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, Global.ControlSystem), false); if (typeName.StartsWith("dmtx4kz302")) return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, Global.ControlSystem), false); - if (typeName.StartsWith("dmtx401")) + if (typeName.StartsWith("dmtx401")) return new DmTx401CController(key, name, new DmTx401C(ipid, Global.ControlSystem), false); - Debug.Console(0, "{1} WARNING: Cannot create DM-TX of type: '{0}'", typeName, key); - } - catch (Exception e) - { - Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e); - } + Debug.Console(0, "{1} WARNING: Cannot create DM-TX of type: '{0}'", typeName, key); + } + catch (Exception e) + { + Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e); + } return null; - } + } var parentDev = DeviceManager.GetDeviceForKey(pKey); DMInput dmInput; BasicDmTxControllerBase tx; + bool useChassisForOfflineFeedback = false; - if (parentDev is DmChassisController) + if (parentDev is IDmSwitchWithEndpointOnlineFeedback) { // Get the Crestron chassis and link stuff up - var switchDev = (parentDev as DmChassisController); - var chassis = switchDev.Chassis; + var switchDev = (parentDev as IDmSwitchWithEndpointOnlineFeedback); + var chassis = switchDev.Chassis; //Check that the input is within range of this chassis' possible inputs - var num = props.ParentInputNumber; - if (num <= 0 || num > chassis.NumberOfInputs) - { - Debug.Console(0, "Cannot create DM device '{0}'. Input number '{1}' is out of range", - key, num); - return null; - } + var num = props.ParentInputNumber; + if (num <= 0 || num > chassis.NumberOfInputs) + { + Debug.Console(0, "Cannot create DM device '{0}'. Input number '{1}' is out of range", + key, num); + return null; + } switchDev.TxDictionary.Add(num, key); dmInput = chassis.Inputs[num]; @@ -157,15 +157,23 @@ namespace PepperDash.Essentials.DM chassis is DmMd128x128 || chassis is DmMd64x64) { tx = GetDmTxForChassisWithoutIpId(key, name, typeName, dmInput); - Debug.Console(0, "DM endpoint output {0} is for Cpu3, changing online feedback to chassis", num); - tx.IsOnline.SetValueFunc(() => switchDev.InputEndpointOnlineFeedbacks[num].BoolValue); - switchDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); - return tx; + useChassisForOfflineFeedback = true; } else { - return GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + tx = GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + if (typeName == "hdbasettx" || typeName == "dmtx4k100c1g") + { + useChassisForOfflineFeedback = true; + } } + if (useChassisForOfflineFeedback) + { + Debug.Console(0, "DM endpoint output {0} does not have direct online feedback, changing online feedback to chassis", num); + tx.IsOnline.SetValueFunc(() => switchDev.InputEndpointOnlineFeedbacks[num].BoolValue); + switchDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); + } + return tx; } catch (Exception e) { @@ -173,7 +181,8 @@ namespace PepperDash.Essentials.DM return null; } } - else if(parentDev is DmpsRoutingController) + + if (parentDev is DmpsRoutingController) { // Get the DMPS chassis and link stuff up var dmpsDev = (parentDev as DmpsRoutingController); @@ -202,33 +211,38 @@ namespace PepperDash.Essentials.DM try { - if(Global.ControlSystemIsDmps4kType) + if (Global.ControlSystemIsDmps4kType) { tx = GetDmTxForChassisWithoutIpId(key, name, typeName, dmInput); - Debug.Console(0, "DM endpoint output {0} is for DMPS3-4K, changing online feedback to chassis", num); - tx.IsOnline.SetValueFunc(() => dmpsDev.InputEndpointOnlineFeedbacks[num].BoolValue); - dmpsDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); - return tx; + useChassisForOfflineFeedback = true; } else { - return GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + tx = GetDmTxForChassisWithIpId(key, name, typeName, ipid, dmInput); + if (typeName == "hdbasettx" || typeName == "dmtx4k100c1g") + { + useChassisForOfflineFeedback = true; + } } + if (useChassisForOfflineFeedback) + { + Debug.Console(0, "DM endpoint output {0} does not have direct online feedback, changing online feedback to chassis", num); + tx.IsOnline.SetValueFunc(() => dmpsDev.InputEndpointOnlineFeedbacks[num].BoolValue); + dmpsDev.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => tx.IsOnline.FireUpdate(); + } + return tx; } catch (Exception e) { Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device for dmps: {1}", key, e); return null; - } + } } - else - { - Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a processor, DM Chassis or DMPS.", key, pKey); - return null; - } - } - } + Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a processor, DM Chassis or DMPS.", key, pKey); + return null; + } + } public abstract class BasicDmTxControllerBase : CrestronGenericBridgeableBaseDevice { @@ -239,21 +253,21 @@ namespace PepperDash.Essentials.DM } } - /// - /// - /// + /// + /// + /// [Description("Wrapper class for all DM-TX variants")] - public abstract class DmTxControllerBase : BasicDmTxControllerBase - { + public abstract class DmTxControllerBase : BasicDmTxControllerBase + { public virtual void SetPortHdcpCapability(eHdcpCapabilityType hdcpMode, uint port) { } public virtual eHdcpCapabilityType HdcpSupportCapability { get; protected set; } public abstract StringFeedback ActiveVideoInputFeedback { get; protected set; } public RoutingInputPortWithVideoStatuses AnyVideoInput { get; protected set; } public IntFeedback HdcpStateFeedback { get; protected set; } - protected DmTxControllerBase(string key, string name, EndpointTransmitterBase hardware) - : base(key, name, hardware) - { + protected DmTxControllerBase(string key, string name, EndpointTransmitterBase hardware) + : base(key, name, hardware) + { AddToFeedbackList(ActiveVideoInputFeedback); IsOnline.OutputChange += (currentDevice, args) => @@ -264,11 +278,12 @@ namespace PepperDash.Essentials.DM feedback.FireUpdate(); } }; - } + } - protected DmTxControllerBase(string key, string name, DmHDBasedTEndPoint hardware) : base(key, name, hardware) - { - } + protected DmTxControllerBase(string key, string name, DmHDBasedTEndPoint hardware) + : base(key, name, hardware) + { + } protected DmTxControllerJoinMap GetDmTxJoinMap(uint joinStart, string joinMapKey) { @@ -282,8 +297,8 @@ namespace PepperDash.Essentials.DM return joinMap; } - protected void LinkDmTxToApi(DmTxControllerBase tx, BasicTriList trilist, DmTxControllerJoinMap joinMap, EiscApiAdvanced bridge) - { + protected void LinkDmTxToApi(DmTxControllerBase tx, BasicTriList trilist, DmTxControllerJoinMap joinMap, EiscApiAdvanced bridge) + { if (bridge != null) { bridge.AddJoinMap(Key, joinMap); @@ -293,7 +308,7 @@ namespace PepperDash.Essentials.DM Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } - Debug.Console(1, tx, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.Console(1, tx, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); tx.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber]); @@ -320,8 +335,6 @@ namespace PepperDash.Essentials.DM txR.VideoSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.VideoInput.JoinNumber]); txR.AudioSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.AudioInput.JoinNumber]); - trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)tx.HdcpSupportCapability; - if (txR.InputPorts[DmPortName.HdmiIn] != null) { var inputPort = txR.InputPorts[DmPortName.HdmiIn]; @@ -368,7 +381,7 @@ namespace PepperDash.Essentials.DM { var intFeedback = tx.Feedbacks["HdmiIn2HdcpCapability"] as IntFeedback; if (intFeedback != null) - intFeedback.LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState.JoinNumber]); + intFeedback.LinkInputSig(trilist.UShortInput[joinMap.Port2HdcpState.JoinNumber]); } if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null) @@ -379,6 +392,40 @@ namespace PepperDash.Essentials.DM } } + if (txR.InputPorts[DmPortName.DisplayPortIn] != null) + { + var inputPort = txR.InputPorts[DmPortName.DisplayPortIn]; + + if (tx.Feedbacks["DisplayPortInHdcpCapability"] != null) + { + + var intFeedback = tx.Feedbacks["DisplayPortInHdcpCapability"] as IntFeedback; + if (intFeedback != null) + + intFeedback.LinkInputSig(trilist.UShortInput[joinMap.Port3HdcpState.JoinNumber]); + + if (inputPort.ConnectionType == eRoutingPortConnectionType.DisplayPort && inputPort.Port != null) + { + var port = inputPort.Port as EndpointDisplayPortInput; + SetHdcpCapabilityAction(port, joinMap.Port3HdcpState.JoinNumber, trilist); + } + } + } + + + var hdcpInputPortCount = + (ushort) + txR.InputPorts.Where( + x => (x.Type == eRoutingSignalType.Video) || (x.Type == eRoutingSignalType.AudioVideo)) + .Where( + x => + (x.ConnectionType == eRoutingPortConnectionType.DmCat) || + (x.ConnectionType == eRoutingPortConnectionType.Hdmi) || + (x.ConnectionType == eRoutingPortConnectionType.DisplayPort)) + .ToList().Count(); + + trilist.SetUshort(joinMap.HdcpInputPortCount.JoinNumber, hdcpInputPortCount); + } var txFreeRun = tx as IHasFreeRun; @@ -418,7 +465,7 @@ namespace PepperDash.Essentials.DM }); } else - { + { trilist.SetUShortSigAction(join, s => { @@ -426,14 +473,40 @@ namespace PepperDash.Essentials.DM }); } } - } + + private void SetHdcpCapabilityAction(EndpointDisplayPortInput port, uint join, + BasicTriList trilist) + { + trilist.SetUShortSigAction(join, + s => + { + Debug.Console(0, this, "Trying to set HDCP to {0} on port {1}", s, port.ToString()); + port.HdcpCapability = (eHdcpCapabilityType) s; + }); + } + + } public class DmTxControllerFactory : EssentialsDeviceFactory { public DmTxControllerFactory() { - TypeNames = new List() { "dmtx200c", "dmtx201c", "dmtx201s", "dmtx4k100c", "dmtx4k202c", "dmtx4kz202c", "dmtx4k302c", "dmtx4kz302c", - "dmtx401c", "dmtx401s", "dmtx4k100c1g", "dmtx4kz100c1g", "hdbasettx" }; + TypeNames = new List + { + "dmtx200c", + "dmtx201c", + "dmtx201s", + "dmtx4k100c", + "dmtx4k202c", + "dmtx4kz202c", + "dmtx4k302c", + "dmtx4kz302c", + "dmtx401c", + "dmtx401s", + "dmtx4k100c1g", + "dmtx4kz100c1g", + "hdbasettx" + }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) @@ -443,8 +516,8 @@ namespace PepperDash.Essentials.DM Debug.Console(1, "Factory Attempting to create new DM-TX Device"); var props = JsonConvert.DeserializeObject - (dc.Properties.ToString()); - return PepperDash.Essentials.DM.DmTxHelper.GetDmTxController(dc.Key, dc.Name, type, props); + (dc.Properties.ToString()); + return DmTxHelper.GetDmTxController(dc.Key, dc.Name, type, props); } } diff --git a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/HDBaseTTxController.cs b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/HDBaseTTxController.cs index a90cb443..b18598c1 100644 --- a/src/PepperDash.Essentials.DM/Endpoints/Transmitters/HDBaseTTxController.cs +++ b/src/PepperDash.Essentials.DM/Endpoints/Transmitters/HDBaseTTxController.cs @@ -54,6 +54,9 @@ namespace PepperDash.Essentials.DM IsOnline.SetValueFunc(() => controller.InputEndpointOnlineFeedbacks[num].BoolValue); controller.InputEndpointOnlineFeedbacks[num].OutputChange += (o, a) => IsOnline.FireUpdate(); } + + PreventRegistration = true; + tx.Register(); } #region IRoutingInputs Members diff --git a/src/PepperDash.Essentials.DM/IDmSwitch.cs b/src/PepperDash.Essentials.DM/IDmSwitch.cs index ef50f2ce..8f1af55e 100644 --- a/src/PepperDash.Essentials.DM/IDmSwitch.cs +++ b/src/PepperDash.Essentials.DM/IDmSwitch.cs @@ -16,10 +16,17 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.DM.Config; namespace PepperDash.Essentials.DM { - public interface IDmSwitch { + public interface IDmSwitch + { Switch Chassis { get; } Dictionary TxDictionary { get; } Dictionary RxDictionary { get; } } + + public interface IDmSwitchWithEndpointOnlineFeedback : IDmSwitch + { + Dictionary InputEndpointOnlineFeedbacks { get; } + Dictionary OutputEndpointOnlineFeedbacks { get; } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs index 41140c34..6ddf10c2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs @@ -218,6 +218,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec return joinable; } } + + [JsonProperty("dialable")] + public bool Dialable { get; set; } + //public string ConferenceNumberToDial { get; set; } [JsonProperty("conferencePassword")] public string ConferencePassword { get; set; } diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs index 59823bb9..05456ad4 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs @@ -348,6 +348,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (b.DialInfo.ConnectMode.Value.ToLower() == "obtp" || b.DialInfo.ConnectMode.Value.ToLower() == "manual") meeting.IsOneButtonToPushMeeting = true; + meeting.Dialable = b.DialInfo.Calls.Call.Count > 0; + if (b.DialInfo.Calls.Call != null) { foreach (Call c in b.DialInfo.Calls.Call) diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs index 3dd85100..9d8fbce1 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs @@ -940,7 +940,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0"); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Dialable); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 5e49b15f..0ba684a8 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -1512,6 +1512,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom meeting.Privacy = b.IsPrivate ? eMeetingPrivacy.Private : eMeetingPrivacy.Public; + meeting.Dialable = meeting.Id != "0"; + // No meeting.Calls data exists for Zoom Rooms. Leaving out for now. var now = DateTime.Now; if (meeting.StartTime < now && meeting.EndTime < now) diff --git a/src/PepperDash.Essentials/ControlSystem.cs b/src/PepperDash.Essentials/ControlSystem.cs index 04a4d992..09c95323 100644 --- a/src/PepperDash.Essentials/ControlSystem.cs +++ b/src/PepperDash.Essentials/ControlSystem.cs @@ -44,28 +44,29 @@ namespace PepperDash.Essentials /// public override void InitializeSystem() { - _startTimer = new CTimer(StartSystem,StartupTime); - - // If the control system is a DMPS type, we need to wait to exit this method until all devices have had time to activate // to allow any HD-BaseT DM endpoints to register first. - if (Global.ControlSystemIsDmpsType) + bool preventInitializationComplete = Global.ControlSystemIsDmpsType; + if (preventInitializationComplete) { Debug.Console(1, "******************* InitializeSystem() Entering **********************"); - - _initializeEvent = new CEvent(); - + _startTimer = new CTimer(StartSystem, preventInitializationComplete, StartupTime); + _initializeEvent = new CEvent(true, false); DeviceManager.AllDevicesRegistered += (o, a) => { _initializeEvent.Set(); - Debug.Console(1, "******************* InitializeSystem() Exiting **********************"); }; - _initializeEvent.Wait(30000); + Debug.Console(1, "******************* InitializeSystem() Exiting **********************"); + SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; + } + else + { + _startTimer = new CTimer(StartSystem, preventInitializationComplete, StartupTime); } } - private void StartSystem(object obj) + private void StartSystem(object preventInitialization) { DeterminePlatform(); @@ -77,7 +78,7 @@ namespace PepperDash.Essentials CrestronConsole.AddNewConsoleCommand(PluginLoader.ReportAssemblyVersions, "reportversions", "Reports the versions of the loaded assemblies", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(PepperDash.Essentials.Core.DeviceFactory.GetDeviceFactoryTypes, "gettypes", "Gets the device types that can be built. Accepts a filter string.", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(Core.DeviceFactory.GetDeviceFactoryTypes, "gettypes", "Gets the device types that can be built. Accepts a filter string.", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(BridgeHelper.PrintJoinMap, "getjoinmap", "map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); @@ -89,27 +90,28 @@ namespace PepperDash.Essentials CrestronConsole.AddNewConsoleCommand(s => { foreach (var tl in TieLineCollection.Default) - CrestronConsole.ConsoleCommandResponse(" {0}\r\n", tl); + CrestronConsole.ConsoleCommandResponse(" {0}{1}", tl, CrestronEnvironment.NewLine); }, "listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => { CrestronConsole.ConsoleCommandResponse - ("Current running configuration. This is the merged system and template configuration"); + ("Current running configuration. This is the merged system and template configuration" + CrestronEnvironment.NewLine); CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse( - "This system can be found at the following URLs:\r\n" + - "System URL: {0}\r\n" + - "Template URL: {1}", - ConfigReader.ConfigObject.SystemUrl, - ConfigReader.ConfigObject.TemplateUrl), - "portalinfo", - "Shows portal URLS from configuration", + "This system can be found at the following URLs:{2}" + + "System URL: {0}{2}" + + "Template URL: {1}{2}", + ConfigReader.ConfigObject.SystemUrl, + ConfigReader.ConfigObject.TemplateUrl, + CrestronEnvironment.NewLine), + "portalinfo", + "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator); @@ -122,7 +124,10 @@ namespace PepperDash.Essentials return; } - SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; + if (!(bool)preventInitialization) + { + SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; + } } /// diff --git a/src/PepperDash.Essentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/src/PepperDash.Essentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 46d481ef..8be5508e 100644 --- a/src/PepperDash.Essentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/src/PepperDash.Essentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -228,66 +228,66 @@ namespace PepperDash.Essentials } } - void Initialize() + public override void Initialize() { try { - if (DefaultAudioDevice is IBasicVolumeControls) - DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; - else if (DefaultAudioDevice is IHasVolumeDevice) - DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; - CurrentVolumeControls = DefaultVolumeControls; + //if (DefaultAudioDevice is IBasicVolumeControls) + // DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + //else if (DefaultAudioDevice is IHasVolumeDevice) + // DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + //CurrentVolumeControls = DefaultVolumeControls; - // Combines call feedback from both codecs if available - InCallFeedback = new BoolFeedback(() => - { - bool inAudioCall = false; - bool inVideoCall = false; + //// Combines call feedback from both codecs if available + //InCallFeedback = new BoolFeedback(() => + //{ + // bool inAudioCall = false; + // bool inVideoCall = false; - if (AudioCodec != null) - inAudioCall = AudioCodec.IsInCall; + // if (AudioCodec != null) + // inAudioCall = AudioCodec.IsInCall; - if (VideoCodec != null) - inVideoCall = VideoCodec.IsInCall; + // if (VideoCodec != null) + // inVideoCall = VideoCodec.IsInCall; - if (inAudioCall || inVideoCall) - return true; - else - return false; - }); + // if (inAudioCall || inVideoCall) + // return true; + // else + // return false; + //}); - SetupDisplays(); + //SetupDisplays(); - // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback - this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + //// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback + //this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); - Debug.Console(2, this, "Microphone Privacy Config evaluated."); + //Debug.Console(2, this, "Microphone Privacy Config evaluated."); - // Get emergency object, if any - this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + //// Get emergency object, if any + //this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); - Debug.Console(2, this, "Emergency Config evaluated."); + //Debug.Console(2, this, "Emergency Config evaluated."); - VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; + //VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + //VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; - if (AudioCodec != null) - AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + //if (AudioCodec != null) + // AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); - VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); + //IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); + //VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); - // link privacy to VC (for now?) - PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); - VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); + //// link privacy to VC (for now?) + //PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); + //VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); - CallTypeFeedback = new IntFeedback(() => 0); + //CallTypeFeedback = new IntFeedback(() => 0); SetSourceListKey(); - EnablePowerOnToLastSource = true; + //EnablePowerOnToLastSource = true; } catch (Exception e) { @@ -299,7 +299,9 @@ namespace PepperDash.Essentials { //DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; - var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey]; + var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey]; + + Displays.Clear(); foreach (var destination in destinationList) { @@ -316,37 +318,54 @@ namespace PepperDash.Essentials // Link power, warming, cooling to display var dispTwoWay = display as IHasPowerControlWithFeedback; if (dispTwoWay != null) - { - dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) - { - //if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - // CurrentSourceInfo = null; - OnFeedback.FireUpdate(); - } - if (dispTwoWay.PowerIsOnFeedback.BoolValue) - { - SetDefaultLevels(); - } - }; - } - - display.IsWarmingUpFeedback.OutputChange += (o, a) => - { - IsWarmingUpFeedback.FireUpdate(); - if (!IsWarmingUpFeedback.BoolValue) - (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); - }; - display.IsCoolingDownFeedback.OutputChange += (o, a) => - { - IsCoolingDownFeedback.FireUpdate(); - }; + { + dispTwoWay.PowerIsOnFeedback.OutputChange -= PowerIsOnFeedback_OutputChange; + dispTwoWay.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; + + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + } + + display.IsWarmingUpFeedback.OutputChange -= IsWarmingUpFeedback_OutputChange; + display.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + + display.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange; + display.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; } } + } + + void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsCoolingDownFeedback.FireUpdate(); + } + + void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + } + + void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var dispTwoWay = sender as IHasPowerControlWithFeedback; + + if (dispTwoWay != null && dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + //if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + // CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } } + + + + private void SetSourceListKey() { if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) @@ -356,9 +375,9 @@ namespace PepperDash.Essentials else { SetSourceListKey(Key); - } - - SetCodecExternalSources(); + } + + SetUpVideoCodec(); } protected override void CustomSetConfig(DeviceConfig config) @@ -369,26 +388,150 @@ namespace PepperDash.Essentials PropertiesConfig = newPropertiesConfig; ConfigWriter.UpdateRoomConfig(config); + } + + public override bool Deactivate() + { + // Stop listining to this event when room deactivated + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + + // Clear occupancy + RoomOccupancy = null; + + Debug.Console(0, this, "Room '{0}' Deactivated", Name); + + return base.Deactivate(); } public override bool CustomActivate() - { - // Add Occupancy object from config - if (PropertiesConfig.Occupancy != null) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); - this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as - IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); - } - - this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); - this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); - - this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; - this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); - + { + try + { + if (DefaultAudioDevice is IBasicVolumeControls) + DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + else if (DefaultAudioDevice is IHasVolumeDevice) + DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + CurrentVolumeControls = DefaultVolumeControls; + + + // Combines call feedback from both codecs if available + InCallFeedback = new BoolFeedback(() => + { + bool inAudioCall = false; + bool inVideoCall = false; + + if (AudioCodec != null) + inAudioCall = AudioCodec.IsInCall; + + if (VideoCodec != null) + inVideoCall = VideoCodec.IsInCall; + + if (inAudioCall || inVideoCall) + return true; + else + return false; + }); + + SetupDisplays(); + + // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback + this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + + Debug.Console(2, this, "Microphone Privacy Config evaluated."); + + // Get emergency object, if any + this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + + Debug.Console(2, this, "Emergency Config evaluated."); + + if (AudioCodec != null) + { + AudioCodec.CallStatusChange -= AudioCodec_CallStatusChange; + AudioCodec.CallStatusChange += AudioCodec_CallStatusChange; + } + + VideoCodec.CallStatusChange -= VideoCodec_CallStatusChange; + VideoCodec.CallStatusChange += VideoCodec_CallStatusChange; + + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + VideoCodec.IsReadyChange += VideoCodec_IsReadyChange; + + VideoCodec.SharingContentIsOnFeedback.OutputChange -= SharingContentIsOnFeedback_OutputChange; + VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; + + + IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); + + // link privacy to VC (for now?) + PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); + + VideoCodec.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; + VideoCodec.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; + + CallTypeFeedback = new IntFeedback(() => 0); + + SetSourceListKey(); + + EnablePowerOnToLastSource = true; + + + // Add Occupancy object from config + if (PropertiesConfig.Occupancy != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); + this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as + IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); + } + + this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); + this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); + + this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; + this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); + + } + catch (Exception e) + { + Debug.Console(0, this, "Error Activiating Room: {0}", e); + } + + + Debug.Console(0, this, "Room '{0}' Activated", Name); return base.CustomActivate(); - } + } + + void AudioCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PrivacyModeIsOnFeedback.FireUpdate(); + } + + void VideoCodec_IsReadyChange(object sender, EventArgs e) + { + SetUpVideoCodec(); + } + + void SetUpVideoCodec() + { + SetCodecExternalSources(); + SetCodecBranding(); + } + + void VideoCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsSharingFeedback.FireUpdate(); + } + + /// /// @@ -781,7 +924,9 @@ namespace PepperDash.Essentials videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop); videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); } - } + } + + Debug.Console(1, this, "Successfully set up codec external sources for room: {0}", Name); } catch (Exception e) { diff --git a/src/PepperDash.Essentials/Room/Types/EssentialsHuddleVtc1Room.cs b/src/PepperDash.Essentials/Room/Types/EssentialsHuddleVtc1Room.cs index c2942914..9c8c87e1 100644 --- a/src/PepperDash.Essentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/src/PepperDash.Essentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -21,6 +21,8 @@ namespace PepperDash.Essentials { public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room { + private IEssentialsRoomCombiner _roomCombiner; + private bool _codecExternalSourceChange; public event EventHandler CurrentVolumeDeviceChange; public event SourceInfoChangeHandler CurrentSourceChange; @@ -236,7 +238,7 @@ namespace PepperDash.Essentials throw new ArgumentNullException("DefaultAudioDevice cannot be null"); } - InitializeRoom(); + Initialize(); } catch (Exception e) { @@ -244,8 +246,65 @@ namespace PepperDash.Essentials } } - void InitializeRoom() - { + + private void SetupEnvironmentalControlDevices() + { + if (PropertiesConfig.Environment != null) + { + if (PropertiesConfig.Environment.Enabled) + { + EnvironmentalControlDevices.Clear(); + + foreach (var d in PropertiesConfig.Environment.DeviceKeys) + { + var envDevice = DeviceManager.GetDeviceForKey(d) as EssentialsDevice; + EnvironmentalControlDevices.Add(envDevice); + } + } + } + } + + + private void SetSourceListKey() + { + if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) + { + SetSourceListKey(PropertiesConfig.SourceListKey); + } + else + { + SetSourceListKey(Key); + } + + SetUpVideoCodec(); + } + + protected override void CustomSetConfig(DeviceConfig config) + { + var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); + + if (newPropertiesConfig != null) + PropertiesConfig = newPropertiesConfig; + + ConfigWriter.UpdateRoomConfig(config); + } + + public override bool Deactivate() + { + + // Stop listining to this event when room deactivated + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + + // Clear occupancy + RoomOccupancy = null; + + Debug.Console(0, this, "Room '{0}' Deactivated", Name); + + return base.Deactivate(); + } + + public override bool CustomActivate() + { try { if (DefaultAudioDevice is IBasicVolumeControls) @@ -280,32 +339,15 @@ namespace PepperDash.Essentials var dispTwoWay = disp as IHasPowerControlWithFeedback; if (dispTwoWay != null) { - dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) - { - if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - CurrentSourceInfo = null; - OnFeedback.FireUpdate(); - } - if (dispTwoWay.PowerIsOnFeedback.BoolValue) - { - SetDefaultLevels(); - } - }; + dispTwoWay.PowerIsOnFeedback.OutputChange -= PowerIsOnFeedback_OutputChange; + dispTwoWay.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; } - disp.IsWarmingUpFeedback.OutputChange += (o, a) => - { - IsWarmingUpFeedback.FireUpdate(); - if (!IsWarmingUpFeedback.BoolValue) - (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); - }; - disp.IsCoolingDownFeedback.OutputChange += (o, a) => - { - IsCoolingDownFeedback.FireUpdate(); - }; + disp.IsWarmingUpFeedback.OutputChange -= IsWarmingUpFeedback_OutputChange; + disp.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + disp.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange; + disp.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; } @@ -319,20 +361,30 @@ namespace PepperDash.Essentials this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); Debug.Console(2, this, "Emergency Config evaluated."); - - - VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; - + if (AudioCodec != null) - AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + { + AudioCodec.CallStatusChange -= AudioCodec_CallStatusChange; + AudioCodec.CallStatusChange += AudioCodec_CallStatusChange; + } + + VideoCodec.CallStatusChange -= VideoCodec_CallStatusChange; + VideoCodec.CallStatusChange += VideoCodec_CallStatusChange; + + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + VideoCodec.IsReadyChange += VideoCodec_IsReadyChange; + + VideoCodec.SharingContentIsOnFeedback.OutputChange -= SharingContentIsOnFeedback_OutputChange; + VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; + IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); - VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); // link privacy to VC (for now?) PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); - VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); + + VideoCodec.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; + VideoCodec.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; CallTypeFeedback = new IntFeedback(() => 0); @@ -341,72 +393,92 @@ namespace PepperDash.Essentials SetSourceListKey(); EnablePowerOnToLastSource = true; + + + // Add Occupancy object from config + if (PropertiesConfig.Occupancy != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); + this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as + IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); + } + + this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); + this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); + + this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; + this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); } catch (Exception e) { - Debug.Console(0, this, "Error Initializing Room: {0}", e); - } - } - - private void SetupEnvironmentalControlDevices() - { - if (PropertiesConfig.Environment != null) - { - if (PropertiesConfig.Environment.Enabled) - { - foreach (var d in PropertiesConfig.Environment.DeviceKeys) - { - var envDevice = DeviceManager.GetDeviceForKey(d) as EssentialsDevice; - EnvironmentalControlDevices.Add(envDevice); - } - } - } - } - - - private void SetSourceListKey() - { - if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) - { - SetSourceListKey(PropertiesConfig.SourceListKey); - } - else - { - SetSourceListKey(Key); + Debug.Console(0, this, "Error Activiating Room: {0}", e); } - SetCodecExternalSources(); - } - - protected override void CustomSetConfig(DeviceConfig config) - { - var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); - - if (newPropertiesConfig != null) - PropertiesConfig = newPropertiesConfig; - - ConfigWriter.UpdateRoomConfig(config); - } - - public override bool CustomActivate() - { - // Add Occupancy object from config - if (PropertiesConfig.Occupancy != null) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); - this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as - IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); - } - - this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); - this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); - - this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; - this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); - + Debug.Console(0, this, "Room '{0}' Activated", Name); return base.CustomActivate(); } + void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PrivacyModeIsOnFeedback.FireUpdate(); + } + + void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsSharingFeedback.FireUpdate(); + } + + void AudioCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void VideoCodec_IsReadyChange(object sender, EventArgs e) + { + SetUpVideoCodec(); + } + + void SetUpVideoCodec() + { + SetCodecExternalSources(); + SetCodecBranding(); + } + + void VideoCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsCoolingDownFeedback.FireUpdate(); + } + + void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + + } + + void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var dispTwoWay = DefaultDisplay as IHasPowerControlWithFeedback; + + if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + + } + /// @@ -834,6 +906,8 @@ namespace PepperDash.Essentials videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); } } + Debug.Console(1, this, "Successfully set up codec external sources for room: {0}", Name); + } catch (Exception e) { diff --git a/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs b/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs index 41616d96..dccae06a 100644 --- a/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs +++ b/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs @@ -7,7 +7,8 @@ using PepperDash.Essentials.Room.Config; namespace PepperDash.Essentials { - public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls + public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy, + IEmergency, IMicrophonePrivacy { bool ExcludeFromGlobalFunctions { get; } diff --git a/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs b/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs index 03f7340b..85937828 100644 --- a/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs +++ b/src/PepperDash.Essentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs @@ -8,7 +8,8 @@ using PepperDash.Essentials.Devices.Common.AudioCodec; namespace PepperDash.Essentials { public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, - IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback + IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback, + IRoomOccupancy, IEmergency, IMicrophonePrivacy { EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }