diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 0af60e3d..003b1f66 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -32,7 +32,6 @@ jobs:
uses: actions/checkout@v2
with:
fetch-depth: 0
- submodules: true
# Fetch all tags
- name: Fetch tags
run: git fetch --tags
@@ -41,12 +40,11 @@ jobs:
shell: powershell
run: |
$version = ./.github/scripts/GenerateVersionNumber.ps1
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Use the version number to set the version of the assemblies
- name: Update AssemblyInfo.cs
shell: powershell
run: |
- Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
@@ -123,7 +121,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
- name: Download Build output
@@ -180,7 +178,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch
@@ -259,7 +257,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 1ee70fd3..f1a6a278 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -24,25 +24,18 @@ jobs:
# First we checkout the source repo
- name: Checkout repo
uses: actions/checkout@v2
- # And any submodules
- - name: Checkout submodules
- shell: bash
- run: |
- git config --global url."https://github.com/".insteadOf "git@github.com:"
- auth_header="$(git config --local --get http.https://github.com/.extraheader)"
- git submodule sync --recursive
- git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
+ with:
+ fetch-depth: 0
# Generate the appropriate version number
- name: Set Version Number
shell: powershell
env:
TAG_NAME: ${{ github.event.release.tag_name }}
- run: Write-Output "::set-env name=VERSION::$($Env:TAG_NAME)"
+ run: echo "VERSION=$($Env:TAG_NAME)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Use the version number to set the version of the assemblies
- name: Update AssemblyInfo.cs
shell: powershell
run: |
- Write-Output ${{ env.VERSION }}
./.github/scripts/UpdateAssemblyVersion.ps1 ${{ env.VERSION }}
- name: restore Nuget Packages
run: nuget install .\packages.config -OutputDirectory .\packages -ExcludeVersion
@@ -101,7 +94,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
- name: Download Build output
@@ -155,7 +148,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch
@@ -228,7 +221,7 @@ jobs:
Get-ChildItem "./Version"
$version = Get-Content -Path ./Version/version.txt
Write-Host "Version: $version"
- Write-Output "::set-env name=VERSION::$version"
+ echo "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout main branch
diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs
index 9f8022de..2801e561 100644
--- a/PepperDashEssentials/ControlSystem.cs
+++ b/PepperDashEssentials/ControlSystem.cs
@@ -16,7 +16,6 @@ using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.DM;
using PepperDash.Essentials.Fusion;
using PepperDash.Essentials.Room.Config;
-//using PepperDash.Essentials.Room.MobileControl;
using Newtonsoft.Json;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
@@ -290,33 +289,14 @@ namespace PepperDash.Essentials
DeviceManager.ActivateAll();
- var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl;
+ var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
mobileControl.LinkSystemMonitorToAppServer();
- //LinkSystemMonitorToAppServer();
+
}
- //void LinkSystemMonitorToAppServer()
- //{
- // var sysMon = DeviceManager.GetDeviceForKey("systemMonitor") as PepperDash.Essentials.Core.Monitoring.SystemMonitorController;
-
- // var appServer = DeviceManager.GetDeviceForKey("appServer") as MobileControlSystemController;
-
-
- // if (sysMon != null && appServer != null)
- // {
- // var key = sysMon.Key + "-" + appServer.Key;
- // var messenger = new PepperDash.Essentials.AppServer.Messengers.SystemMonitorMessenger
- // (key, sysMon, "/device/systemMonitor");
-
- // messenger.RegisterWithAppServer(appServer);
-
- // DeviceManager.AddDevice(messenger);
- // }
- //}
-
///
/// Reads all devices from config and adds them to DeviceManager
///
@@ -394,11 +374,6 @@ namespace PepperDash.Essentials
if (newDev == null)
newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf);
- //
- //if (newDev == null)
- // newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf);
- //
-
if (newDev != null)
DeviceManager.AddDevice(newDev);
else
@@ -465,10 +440,6 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
- // Mobile Control bridge
- //var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
- //AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
- //DeviceManager.AddDevice(bridge);
CreateMobileControlBridge(room);
}
@@ -480,10 +451,6 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
- // Mobile Control bridge
- //var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room);
- //AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
- //DeviceManager.AddDevice(bridge);
CreateMobileControlBridge(room);
}
@@ -504,34 +471,35 @@ namespace PepperDash.Essentials
private static void CreateMobileControlBridge(EssentialsRoomBase room)
{
- var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl;
+ var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
- mobileControl.CreateMobileControlRoomBridge(room);
+ mobileControl.CreateMobileControlRoomBridge(room, mobileControl);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added...");
}
- ///
- /// Helps add the post activation steps that link bridges to main controller
- ///
- ///
- //void AddBridgePostActivationHelper(MobileControlBridgeBase bridge)
- //{
- // bridge.AddPostActivationAction(() =>
- // {
- // var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as MobileControlSystemController;
- // if (parent == null)
- // {
- // Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present");
- // return;
- // }
- // Debug.Console(0, bridge, "Linking to parent controller");
- // bridge.AddParent(parent);
- // parent.AddBridge(bridge);
- // });
- //}
+ private static IMobileControl GetMobileControlDevice()
+ {
+ var mobileControlList = DeviceManager.AllDevices.OfType().ToList();
+
+ if (mobileControlList.Count > 1)
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Warning,
+ "Multiple instances of Mobile Control Server found.");
+
+ return null;
+ }
+
+ if (mobileControlList.Count > 0)
+ {
+ return mobileControlList[0];
+ }
+
+ Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control not enabled for this system");
+ return null;
+ }
///
/// Fires up a logo server if not already running
diff --git a/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs b/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs
index 4159212c..8d9da386 100644
--- a/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs
+++ b/PepperDashEssentials/Fusion/EssentialsHuddleVtc1FusionController.cs
@@ -273,15 +273,18 @@ namespace PepperDash.Essentials.Fusion
// Display to fusion room sigs
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
+
+ var defaultDisplayTwoWay = defaultDisplay as IHasPowerControlWithFeedback;
+ if (defaultDisplayTwoWay != null)
+ {
+ defaultDisplayTwoWay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
+ }
+
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
-
-
MapDisplayToRoomJoins(1, 158, defaultDisplay);
-
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
//Check for existing asset in GUIDs collection
@@ -302,8 +305,18 @@ namespace PepperDash.Essentials.Fusion
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
- // NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
+
+
+ var defaultTwoWayDisplay = defaultDisplay as IHasPowerControlWithFeedback;
+ if (defaultTwoWayDisplay != null)
+ {
+ defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
+ if (defaultDisplay is IDisplayUsage)
+ (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
+
+ defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
+ }
+
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
@@ -325,12 +338,17 @@ namespace PepperDash.Essentials.Fusion
// Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
// Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+
+ var displayTwoWay = display as IHasPowerControlWithFeedback;
+ if (displayTwoWay != null)
+ {
+ displayTwoWay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+ displayTwoWay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+ }
// Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj
index cd8062ce..42d0e288 100644
--- a/PepperDashEssentials/PepperDashEssentials.csproj
+++ b/PepperDashEssentials/PepperDashEssentials.csproj
@@ -71,7 +71,7 @@
..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll
-
+
False
..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll
diff --git a/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs b/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs
index 34432269..2cfb33f7 100644
--- a/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs
+++ b/PepperDashEssentials/Room/Types/EssentialsDualDisplayRoom.cs
@@ -283,19 +283,23 @@ namespace PepperDash.Essentials
if (disp != null)
{
// Link power, warming, cooling to display
- disp.PowerIsOnFeedback.OutputChange += (o, a) =>
- {
- if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ var dispTwoWay = disp as IHasPowerControlWithFeedback;
+ if (dispTwoWay != null)
+ {
+ dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
- if (!disp.PowerIsOnFeedback.BoolValue)
- disp.CurrentSourceInfo = null;
- OnFeedback.FireUpdate();
- }
- if (disp.PowerIsOnFeedback.BoolValue)
- {
- SetDefaultLevels();
- }
- };
+ if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ {
+ if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
+ disp.CurrentSourceInfo = null;
+ OnFeedback.FireUpdate();
+ }
+ if (dispTwoWay.PowerIsOnFeedback.BoolValue)
+ {
+ SetDefaultLevels();
+ }
+ };
+ }
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
@@ -579,8 +583,8 @@ namespace PepperDash.Essentials
- if (dest is IPower)
- (dest as IPower).PowerOff();
+ if (dest is IHasPowerControl)
+ (dest as IHasPowerControl).PowerOff();
}
else
{
diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
index f0604308..4af7697a 100644
--- a/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
+++ b/PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
@@ -176,15 +176,19 @@ namespace PepperDash.Essentials
if (disp != null)
{
// Link power, warming, cooling to display
- disp.PowerIsOnFeedback.OutputChange += (o, a) =>
- {
- if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
- {
- if (!disp.PowerIsOnFeedback.BoolValue)
- CurrentSourceInfo = null;
- OnFeedback.FireUpdate();
- }
- };
+ 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();
+ }
+ };
+ }
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
@@ -495,8 +499,8 @@ namespace PepperDash.Essentials
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
- if (dest is IPower)
- (dest as IPower).PowerOff();
+ if (dest is IHasPowerControl)
+ (dest as IHasPowerControl).PowerOff();
}
else
{
diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
index 97c1775e..efb0ad7b 100644
--- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
+++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
@@ -190,6 +190,12 @@ namespace PepperDash.Essentials
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
+
+ var vc = VideoCodec as IHasExternalSourceSwitching;
+ if (vc != null)
+ {
+ vc.SetSelectedSource(CurrentSourceInfoKey);
+ }
}
}
SourceListItem _CurrentSourceInfo;
@@ -273,19 +279,23 @@ namespace PepperDash.Essentials
if (disp != null)
{
// Link power, warming, cooling to display
- disp.PowerIsOnFeedback.OutputChange += (o, a) =>
- {
- if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ var dispTwoWay = disp as IHasPowerControlWithFeedback;
+ if (dispTwoWay != null)
+ {
+ dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
- if (!disp.PowerIsOnFeedback.BoolValue)
- CurrentSourceInfo = null;
- OnFeedback.FireUpdate();
- }
- if (disp.PowerIsOnFeedback.BoolValue)
- {
- SetDefaultLevels();
- }
- };
+ if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
+ {
+ if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
+ CurrentSourceInfo = null;
+ OnFeedback.FireUpdate();
+ }
+ if (dispTwoWay.PowerIsOnFeedback.BoolValue)
+ {
+ SetDefaultLevels();
+ }
+ };
+ }
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
@@ -383,6 +393,8 @@ namespace PepperDash.Essentials
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
+ VideoCodec.StopSharing();
+ VideoCodec.StandbyActivate();
}
///
@@ -580,6 +592,19 @@ namespace PepperDash.Essentials
OnFeedback.FireUpdate();
+ if (OnFeedback.BoolValue)
+ {
+ if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
+ {
+ Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
+ }
+
+ if (VideoCodec.StandbyIsOnFeedback.BoolValue)
+ {
+ VideoCodec.StandbyDeactivate();
+ }
+ }
+
// report back when done
if (successCallback != null)
successCallback();
@@ -640,8 +665,9 @@ namespace PepperDash.Essentials
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
- if (dest is IPower)
- (dest as IPower).PowerOff();
+ if (dest is IHasPowerControl)
+ (dest as IHasPowerControl).PowerOff();
+
}
else
{
@@ -693,37 +719,44 @@ namespace PepperDash.Essentials
}
- ///
- /// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
- ///
- private void SetCodecExternalSources()
- {
- var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
+ ///
+ /// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
+ ///
+ private void SetCodecExternalSources()
+ {
+ var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
- if (videoCodecWithExternalSwitching == null)
- {
- return;
- }
+ if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
+ {
+ return;
+ }
- string codecTieLine = ConfigReader.ConfigObject.TieLines.SingleOrDefault(x => x.DestinationKey == VideoCodec.Key).DestinationPort;
- videoCodecWithExternalSwitching.ClearExternalSources();
- videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
- var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
+ try
+ {
+ // Get the tie line that the external switcher is connected to
+ string codecInputConnectorName = ConfigReader.ConfigObject.TieLines.SingleOrDefault(
+ x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
- foreach (var kvp in srcList)
- {
- var srcConfig = kvp.Value;
+ videoCodecWithExternalSwitching.ClearExternalSources();
+ videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
+ var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
- if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
- {
+ foreach (var kvp in srcList)
+ {
+ var srcConfig = kvp.Value;
- videoCodecWithExternalSwitching.AddExternalSource(codecTieLine, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
- videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
-
-
- }
- }
- }
+ if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
+ {
+ 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);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(2, this, "Error setting codec external sources: {0}", e);
+ }
+ }
private void SetCodecBranding()
{
diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs
index a2a80af3..f22565e5 100644
--- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs
+++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs
@@ -305,9 +305,9 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.ShowPowerOffPress, EndMeetingPress);
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
- {
- if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower)
- (CurrentRoom.DefaultDisplay as IPower).PowerToggle();
+ {
+ if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
+ (CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});
base.Show();
@@ -984,8 +984,8 @@ namespace PepperDash.Essentials
(previousDev as IDvr).UnlinkButtons(TriList);
if (previousDev is INumericKeypad)
(previousDev as INumericKeypad).UnlinkButtons(TriList);
- if (previousDev is IPower)
- (previousDev as IPower).UnlinkButtons(TriList);
+ if (previousDev is IHasPowerControl)
+ (previousDev as IHasPowerControl).UnlinkButtons(TriList);
if (previousDev is ITransport)
(previousDev as ITransport).UnlinkButtons(TriList);
//if (previousDev is IRadio)
@@ -1044,8 +1044,8 @@ namespace PepperDash.Essentials
(dev as IDvr).LinkButtons(TriList);
if (dev is INumericKeypad)
(dev as INumericKeypad).LinkButtons(TriList);
- if (dev is IPower)
- (dev as IPower).LinkButtons(TriList);
+ if (dev is IHasPowerControl)
+ (dev as IHasPowerControl).LinkButtons(TriList);
if (dev is ITransport)
(dev as ITransport).LinkButtons(TriList);
//if (dev is IRadio)
diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
index d8af370b..a4e88e7e 100644
--- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
+++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs
@@ -319,8 +319,8 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{
- if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IPower)
- (CurrentRoom.DefaultDisplay as IPower).PowerToggle();
+ if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
+ (CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
});
SetupNextMeetingTimer();
@@ -1293,8 +1293,8 @@ namespace PepperDash.Essentials
(previousDev as IDvr).UnlinkButtons(TriList);
if (previousDev is INumericKeypad)
(previousDev as INumericKeypad).UnlinkButtons(TriList);
- if (previousDev is IPower)
- (previousDev as IPower).UnlinkButtons(TriList);
+ if (previousDev is IHasPowerControl)
+ (previousDev as IHasPowerControl).UnlinkButtons(TriList);
if (previousDev is ITransport)
(previousDev as ITransport).UnlinkButtons(TriList);
}
@@ -1351,8 +1351,8 @@ namespace PepperDash.Essentials
(dev as IDvr).LinkButtons(TriList);
if (dev is INumericKeypad)
(dev as INumericKeypad).LinkButtons(TriList);
- if (dev is IPower)
- (dev as IPower).LinkButtons(TriList);
+ if (dev is IHasPowerControl)
+ (dev as IHasPowerControl).LinkButtons(TriList);
if (dev is ITransport)
(dev as ITransport).LinkButtons(TriList);
}
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs
index e57e869d..db905bfa 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericDigitalInputDevice.cs
@@ -1,38 +1,39 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.DeviceSupport;
-using Newtonsoft.Json;
-using PepperDash.Core;
-using PepperDash.Essentials.Core.Bridges;
-using PepperDash.Essentials.Core.Config;
-
-
-namespace PepperDash.Essentials.Core.CrestronIO
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core.Bridges;
+using PepperDash.Essentials.Core.Config;
+
+
+namespace PepperDash.Essentials.Core.CrestronIO
{
[Description("Wrapper class for Digital Input")]
- public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
- {
- public DigitalInput InputPort { get; private set; }
-
- public BoolFeedback InputStateFeedback { get; private set; }
-
- Func InputStateFeedbackFunc
- {
- get
- {
- return () => InputPort.State;
- }
- }
+ public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
+ {
+ public DigitalInput InputPort { get; private set; }
+
+ public BoolFeedback InputStateFeedback { get; private set; }
+
+ Func InputStateFeedbackFunc
+ {
+ get
+ {
+ return () => InputPort.State;
+ }
+ }
public GenericDigitalInputDevice(string key, string name, Func postActivationFunc,
IOPortConfig config)
: base(key, name)
{
+ InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
AddPostActivationAction(() =>
{
@@ -40,15 +41,15 @@ namespace PepperDash.Essentials.Core.CrestronIO
InputPort.Register();
- InputPort.StateChange += InputPort_StateChange;
+ InputPort.StateChange += InputPort_StateChange;
});
}
#region Events
- void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
- {
+ void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
+ {
InputStateFeedback.FireUpdate();
}
@@ -81,7 +82,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
if (ioPortDevice == null)
{
- Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IRelayPorts Device", dc.PortDeviceKey);
+ Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey);
return null;
}
@@ -99,13 +100,13 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Bridge Linking
- public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
- var joinMap = new IDigitalInputJoinMap(joinStart);
-
- var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
-
- if (!string.IsNullOrEmpty(joinMapSerialized))
+ var joinMap = new IDigitalInputJoinMap(joinStart);
+
+ var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
+
+ if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject(joinMapSerialized);
if (bridge != null)
@@ -115,19 +116,19 @@ namespace PepperDash.Essentials.Core.CrestronIO
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
- }
-
- try
- {
- Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
-
- // Link feedback for input state
- InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
- Debug.Console(1, this, "Error: {0}", e);
+ }
+
+ try
+ {
+ Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
+
+ // Link feedback for input state
+ InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
+ Debug.Console(1, this, "Error: {0}", e);
}
}
@@ -144,7 +145,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
- Debug.Console(1, "Factory Attempting to create new Generic Relay Device");
+ Debug.Console(1, "Factory Attempting to create new Generic Digital Input Device");
var props = JsonConvert.DeserializeObject(dc.Properties.ToString());
@@ -158,7 +159,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion
- }
-
-
+ }
+
+
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs
index 90ff4fa0..20acdd4d 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs
@@ -4,15 +4,21 @@ using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Bridges;
+
+
+using Newtonsoft.Json;
namespace PepperDash.Essentials.Core.CrestronIO
{
///
/// Represents a generic digital input deviced tied to a versiport
///
- public class GenericVersiportDigitalInputDevice : EssentialsDevice, IDigitalInput
+ public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
{
public Versiport InputPort { get; private set; }
@@ -26,17 +32,29 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
}
- public GenericVersiportDigitalInputDevice(string key, Versiport inputPort, IOPortConfig props):
- base(key)
+ public GenericVersiportDigitalInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) :
+ base(key, name)
{
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
- InputPort = inputPort;
- InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
- if (props.DisablePullUpResistor)
- InputPort.DisablePullUpResistor = true;
- InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange);
- Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", props.PortNumber, InputPort.DisablePullUpResistor);
+ AddPostActivationAction(() =>
+ {
+ InputPort = postActivationFunc(config);
+
+ InputPort.Register();
+
+ InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
+ if (config.DisablePullUpResistor)
+ InputPort.DisablePullUpResistor = true;
+
+ InputPort.VersiportChange += InputPort_VersiportChange;
+
+
+
+ Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
+
+ });
+
}
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
@@ -46,5 +64,105 @@ namespace PepperDash.Essentials.Core.CrestronIO
if(args.Event == eVersiportEvent.DigitalInChange)
InputStateFeedback.FireUpdate();
}
+
+
+ #region Bridge Linking
+
+ public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ {
+ var joinMap = new IDigitalInputJoinMap(joinStart);
+
+ var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
+
+ if (!string.IsNullOrEmpty(joinMapSerialized))
+ joinMap = JsonConvert.DeserializeObject(joinMapSerialized);
+
+ if (bridge != null)
+ {
+ bridge.AddJoinMap(Key, joinMap);
+ }
+ else
+ {
+ Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
+ }
+
+ try
+ {
+ Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
+
+ // Link feedback for input state
+ InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
+ Debug.Console(1, this, "Error: {0}", e);
+ }
+ }
+
+ #endregion
+
+
+ public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
+ {
+
+ IIOPorts ioPortDevice;
+
+ if (dc.PortDeviceKey.Equals("processor"))
+ {
+ if (!Global.ControlSystem.SupportsVersiport)
+ {
+ Debug.Console(0, "GetVersiportDigitalInput: Processor does not support Versiports");
+ return null;
+ }
+ ioPortDevice = Global.ControlSystem;
+ }
+ else
+ {
+ var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
+ if (ioPortDev == null)
+ {
+ Debug.Console(0, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
+ return null;
+ }
+ ioPortDevice = ioPortDev;
+ }
+ if (ioPortDevice == null)
+ {
+ Debug.Console(0, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
+ return null;
+ }
+
+ if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
+ {
+ Debug.Console(0, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
+ }
+
+ return ioPortDevice.VersiPorts[dc.PortNumber];
+
+
+ }
+ }
+
+
+ public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory
+ {
+ public GenericVersiportDigitalInputDeviceFactory()
+ {
+ TypeNames = new List() { "versiportinput" };
+ }
+
+ public override EssentialsDevice BuildDevice(DeviceConfig dc)
+ {
+ Debug.Console(1, "Factory Attempting to create new Generic Versiport Device");
+
+ var props = JsonConvert.DeserializeObject(dc.Properties.ToString());
+
+ if (props == null) return null;
+
+ var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput, props);
+
+ return portDevice;
+ }
}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs
index 050ac23b..445ac338 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Crestron IO/Relay/GenericRelayDevice.cs
@@ -1,25 +1,25 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.DeviceSupport;
-using Newtonsoft.Json;
-using PepperDash.Core;
-using PepperDash.Essentials.Core.Bridges;
-using PepperDash.Essentials.Core.Config;
-
-namespace PepperDash.Essentials.Core.CrestronIO
-{
- ///
- /// Represents a generic device controlled by relays
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core.Bridges;
+using PepperDash.Essentials.Core.Config;
+
+namespace PepperDash.Essentials.Core.CrestronIO
+{
+ ///
+ /// Represents a generic device controlled by relays
///
[Description("Wrapper class for a Relay")]
- public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput
- {
- public Relay RelayOutput { get; private set; }
-
+ public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput
+ {
+ public Relay RelayOutput { get; private set; }
+
public BoolFeedback OutputIsOnFeedback { get; private set; }
//Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor
@@ -94,11 +94,11 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Events
- void RelayOutput_StateChange(Relay relay, RelayEventArgs args)
- {
+ void RelayOutput_StateChange(Relay relay, RelayEventArgs args)
+ {
OutputIsOnFeedback.FireUpdate();
- }
-
+ }
+
#endregion
#region Methods
@@ -119,33 +119,33 @@ namespace PepperDash.Essentials.Core.CrestronIO
OpenRelay();
else
CloseRelay();
- }
+ }
#endregion
-
- #region ISwitchedOutput Members
-
- void ISwitchedOutput.On()
- {
- CloseRelay();
- }
-
- void ISwitchedOutput.Off()
- {
- OpenRelay();
- }
-
+
+ #region ISwitchedOutput Members
+
+ void ISwitchedOutput.On()
+ {
+ CloseRelay();
+ }
+
+ void ISwitchedOutput.Off()
+ {
+ OpenRelay();
+ }
+
#endregion
#region Bridge Linking
- public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
- var joinMap = new GenericRelayControllerJoinMap(joinStart);
-
- var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
-
- if (!string.IsNullOrEmpty(joinMapSerialized))
+ var joinMap = new GenericRelayControllerJoinMap(joinStart);
+
+ var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
+
+ if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject(joinMapSerialized);
if (bridge != null)
@@ -155,26 +155,26 @@ namespace PepperDash.Essentials.Core.CrestronIO
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
- }
-
- if (RelayOutput == null)
- {
- Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key);
- return;
- }
-
- Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
-
- trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b =>
- {
- if (b)
- CloseRelay();
- else
- OpenRelay();
- });
-
- // feedback for relay state
-
+ }
+
+ if (RelayOutput == null)
+ {
+ Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key);
+ return;
+ }
+
+ Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
+
+ trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b =>
+ {
+ if (b)
+ CloseRelay();
+ else
+ OpenRelay();
+ });
+
+ // feedback for relay state
+
OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]);
}
@@ -202,54 +202,54 @@ namespace PepperDash.Essentials.Core.CrestronIO
return portDevice;
- /*
- if (props.PortDeviceKey == "processor")
- portDevice = Global.ControlSystem as IRelayPorts;
- else
- portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
-
- if (portDevice == null)
- Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
- else
- {
- var cs = (portDevice as CrestronControlSystem);
-
- if (cs != null)
- {
- // The relay is on a control system processor
- if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
- {
- Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
- return null;
- }
- }
- else
- {
- // The relay is on another device type
-
- if (props.PortNumber > portDevice.NumberOfRelayPorts)
- {
- Debug.Console(0, "Port Device: {0} does not have enough relays");
- return null;
- }
- }
-
- Relay relay = portDevice.RelayPorts[props.PortNumber];
-
- if (!relay.Registered)
- {
- if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
- return new GenericRelayDevice(key, relay);
- else
- Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
- }
- else
- {
- return new GenericRelayDevice(key, relay);
- }
-
- // Future: Check if portDevice is 3-series card or other non control system that supports versiports
- }
+ /*
+ if (props.PortDeviceKey == "processor")
+ portDevice = Global.ControlSystem as IRelayPorts;
+ else
+ portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
+
+ if (portDevice == null)
+ Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
+ else
+ {
+ var cs = (portDevice as CrestronControlSystem);
+
+ if (cs != null)
+ {
+ // The relay is on a control system processor
+ if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
+ {
+ Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
+ return null;
+ }
+ }
+ else
+ {
+ // The relay is on another device type
+
+ if (props.PortNumber > portDevice.NumberOfRelayPorts)
+ {
+ Debug.Console(0, "Port Device: {0} does not have enough relays");
+ return null;
+ }
+ }
+
+ Relay relay = portDevice.RelayPorts[props.PortNumber];
+
+ if (!relay.Registered)
+ {
+ if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
+ return new GenericRelayDevice(key, relay);
+ else
+ Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
+ }
+ else
+ {
+ return new GenericRelayDevice(key, relay);
+ }
+
+ // Future: Check if portDevice is 3-series card or other non control system that supports versiports
+ }
*/
}
@@ -258,7 +258,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion
- }
-
-
+ }
+
+
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/DeviceInfo.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/DeviceInfo.cs
new file mode 100644
index 00000000..9b03ec11
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/DeviceInfo.cs
@@ -0,0 +1,11 @@
+namespace PepperDash.Essentials.Core.DeviceInfo
+{
+ public class DeviceInfo
+ {
+ public string HostName { get; set; }
+ public string IpAddress { get; set; }
+ public string MacAddress { get; set; }
+ public string SerialNumber { get; set; }
+ public string FirmwareVersion { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/DeviceInfoEventArgs.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/DeviceInfoEventArgs.cs
new file mode 100644
index 00000000..6727bce6
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/DeviceInfoEventArgs.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace PepperDash.Essentials.Core.DeviceInfo
+{
+ public class DeviceInfoEventArgs:EventArgs
+ {
+ public DeviceInfo DeviceInfo { get; set; }
+
+ public DeviceInfoEventArgs()
+ {
+
+ }
+
+ public DeviceInfoEventArgs(DeviceInfo devInfo)
+ {
+ DeviceInfo = devInfo;
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/IDeviceInfoProvider.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/IDeviceInfoProvider.cs
new file mode 100644
index 00000000..ea9c16e6
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/IDeviceInfoProvider.cs
@@ -0,0 +1,16 @@
+using System;
+using PepperDash.Core;
+
+namespace PepperDash.Essentials.Core.DeviceInfo
+{
+ public interface IDeviceInfoProvider:IKeyed
+ {
+ DeviceInfo DeviceInfo { get; }
+
+ event DeviceInfoChangeHandler DeviceInfoChanged;
+
+ void UpdateDeviceInfo();
+ }
+
+ public delegate void DeviceInfoChangeHandler(IKeyed device, DeviceInfoEventArgs args);
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDiscPlayerControls.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDiscPlayerControls.cs
index 31fb83b4..024bac27 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDiscPlayerControls.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDiscPlayerControls.cs
@@ -6,7 +6,7 @@ using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials.Core
{
- public interface IDiscPlayerControls : IColor, IDPad, INumericKeypad, IPower, ITransport, IUiDisplayInfo
+ public interface IDiscPlayerControls : IColor, IDPad, INumericKeypad, IHasPowerControl, ITransport, IUiDisplayInfo
{
}
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs
index 616d61b1..2dfa7c41 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IMobileControl.cs
@@ -8,11 +8,9 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
///
public interface IMobileControl : IKeyed
{
- void CreateMobileControlRoomBridge(EssentialsRoomBase room);
+ void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent);
void LinkSystemMonitorToAppServer();
-
-
}
///
@@ -26,6 +24,8 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
string QrCodeUrl { get; }
+ string QrCodeChecksum { get; }
+
string McServerUrl { get; }
string RoomName { get; }
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs
index a392d149..0fcf32e9 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IPower.cs
@@ -14,35 +14,64 @@ using PepperDash.Essentials.Core.SmartObjects;
namespace PepperDash.Essentials.Core
{
///
- ///
+ /// Defines the ability to power a device on and off
///
+ [Obsolete("Will be replaced by IHasPowerControlWithFeedback")]
public interface IPower
{
void PowerOn();
void PowerOff();
void PowerToggle();
- BoolFeedback PowerIsOnFeedback { get; }
+ BoolFeedback PowerIsOnFeedback { get; }
}
+ ///
+ /// Adds feedback for current power state
+ ///
+ public interface IHasPowerControlWithFeedback : IHasPowerControl
+ {
+ BoolFeedback PowerIsOnFeedback { get; }
+ }
+
+ ///
+ /// Defines the ability to power a device on and off
+ ///
+ public interface IHasPowerControl
+ {
+ void PowerOn();
+ void PowerOff();
+ void PowerToggle();
+ }
+
///
///
///
- public static class IPowerExtensions
+ public static class IHasPowerControlExtensions
{
- public static void LinkButtons(this IPower dev, BasicTriList triList)
+ public static void LinkButtons(this IHasPowerControl dev, BasicTriList triList)
{
triList.SetSigFalseAction(101, dev.PowerOn);
triList.SetSigFalseAction(102, dev.PowerOff);
triList.SetSigFalseAction(103, dev.PowerToggle);
- dev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]);
+
+ var fbdev = dev as IHasPowerControlWithFeedback;
+ if (fbdev != null)
+ {
+ fbdev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]);
+ }
}
- public static void UnlinkButtons(this IPower dev, BasicTriList triList)
+ public static void UnlinkButtons(this IHasPowerControl dev, BasicTriList triList)
{
triList.ClearBoolSigAction(101);
triList.ClearBoolSigAction(102);
triList.ClearBoolSigAction(103);
- dev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]);
+
+ var fbdev = dev as IHasPowerControlWithFeedback;
+ if (fbdev != null)
+ {
+ fbdev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]);
+ }
}
}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs
index d50de428..0e4efa10 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs
@@ -1,342 +1,355 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro;
-
-using PepperDash.Core;
-
-
-namespace PepperDash.Essentials.Core
-{
- public static class DeviceManager
- {
- private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
- private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
- //public static List Devices { get { return _Devices; } }
- //static List _Devices = new List();
-
- static readonly Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase);
-
- ///
- /// Returns a copy of all the devices in a list
- ///
- public static List AllDevices { get { return new List(Devices.Values); } }
-
- public static bool AddDeviceEnabled;
-
- public static void Initialize(CrestronControlSystem cs)
- {
- AddDeviceEnabled = true;
- CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
- "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
-
- CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
- }
-
- ///
- /// Calls activate steps on all Device class items
- ///
- public static void ActivateAll()
- {
- try
- {
- DeviceCriticalSection.Enter();
- AddDeviceEnabled = false;
- // PreActivate all devices
- foreach (var d in Devices.Values)
- {
- try
- {
- if (d is Device)
- (d as Device).PreActivate();
- }
- catch (Exception e)
- {
- Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
- }
- }
-
- // Activate all devices
- foreach (var d in Devices.Values)
- {
- try
- {
- if (d is Device)
- (d as Device).Activate();
- }
- catch (Exception e)
- {
- Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
- }
- }
-
- // PostActivate all devices
- foreach (var d in Devices.Values)
- {
- try
- {
- if (d is Device)
- (d as Device).PostActivate();
- }
- catch (Exception e)
- {
- Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
- }
- }
- }
- finally
- {
- DeviceCriticalSection.Leave();
- }
- }
-
- ///
- /// Calls activate on all Device class items
- ///
- public static void DeactivateAll()
- {
- try
- {
- DeviceCriticalSection.Enter();
- foreach (var d in Devices.Values.OfType())
- {
- d.Deactivate();
- }
- }
- finally
- {
- DeviceCriticalSection.Leave();
- }
- }
-
- //static void ListMethods(string devKey)
- //{
- // var dev = GetDeviceForKey(devKey);
- // if(dev != null)
- // {
- // var type = dev.GetType().GetCType();
- // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
- // var sb = new StringBuilder();
- // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
- // foreach (var m in methods)
- // {
- // sb.Append(string.Format("{0}(", m.Name));
- // var pars = m.GetParameters();
- // foreach (var p in pars)
- // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
- // sb.AppendLine(")");
- // }
- // CrestronConsole.ConsoleCommandResponse(sb.ToString());
- // }
- //}
-
- private static void ListDevices(string s)
- {
- Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count);
- var sorted = Devices.Values.ToList();
- sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
-
- foreach (var d in sorted)
- {
- var name = d is IKeyName ? (d as IKeyName).Name : "---";
- Debug.Console(0, " [{0}] {1}", d.Key, name);
- }
- }
-
- private static void ListDeviceFeedbacks(string devKey)
- {
- var dev = GetDeviceForKey(devKey);
- if (dev == null)
- {
- Debug.Console(0, "Device '{0}' not found", devKey);
- return;
- }
- var statusDev = dev as IHasFeedback;
- if (statusDev == null)
- {
- Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey);
- return;
- }
- statusDev.DumpFeedbacksToConsole(true);
- }
-
- //static void ListDeviceCommands(string devKey)
- //{
- // var dev = GetDeviceForKey(devKey);
- // if (dev == null)
- // {
- // Debug.Console(0, "Device '{0}' not found", devKey);
- // return;
- // }
- // Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey);
- //}
-
- private static void ListDeviceCommStatuses(string input)
- {
- var sb = new StringBuilder();
- foreach (var dev in Devices.Values.OfType())
- {
- sb.Append(string.Format("{0}: {1}\r", dev,
- dev.CommunicationMonitor.Status));
- }
- CrestronConsole.ConsoleCommandResponse(sb.ToString());
- }
-
-
- //static void DoDeviceCommand(string command)
- //{
- // Debug.Console(0, "Not yet implemented. Stay tuned");
- //}
-
- public static void AddDevice(IKeyed newDev)
- {
- try
- {
- if (!DeviceCriticalSection.TryEnter())
- {
- Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again");
- return;
- }
- // Check for device with same key
- //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
- ////// If it exists, remove or warn??
- //if (existingDevice != null)
-
- if (!AddDeviceEnabled)
- {
- Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed.");
- return;
- }
-
- if (Devices.ContainsKey(newDev.Key))
- {
- Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager");
- return;
- }
- Devices.Add(newDev.Key, newDev);
- //if (!(_Devices.Contains(newDev)))
- // _Devices.Add(newDev);
- }
- finally
- {
- DeviceCriticalSection.Leave();
- }
- }
-
- public static void AddDevice(IEnumerable devicesToAdd)
- {
- try
- {
- if (!DeviceCriticalSection.TryEnter())
- {
- Debug.Console(0, Debug.ErrorLogLevel.Error,
- "Currently unable to add devices to Device Manager. Please try again");
- return;
- }
- if (!AddDeviceEnabled)
- {
- Debug.Console(0, Debug.ErrorLogLevel.Error,
- "All devices have been activated. Adding new devices is not allowed.");
- return;
- }
-
- foreach (var dev in devicesToAdd)
- {
- try
- {
- Devices.Add(dev.Key, dev);
- }
- catch (ArgumentException ex)
- {
- Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}",
- dev.Key, ex.Message, ex.StackTrace);
- }
- }
- }
- finally
- {
- DeviceCriticalSection.Leave();
- }
- }
-
- public static void RemoveDevice(IKeyed newDev)
- {
- try
- {
- DeviceCriticalSection.Enter();
- if (newDev == null)
- return;
- if (Devices.ContainsKey(newDev.Key))
- Devices.Remove(newDev.Key);
- //if (_Devices.Contains(newDev))
- // _Devices.Remove(newDev);
- else
- Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
- }
- finally
- {
- DeviceCriticalSection.Leave();
- }
- }
-
- public static IEnumerable GetDeviceKeys()
- {
- //return _Devices.Select(d => d.Key).ToList();
- return Devices.Keys;
- }
-
- public static IEnumerable GetDevices()
- {
- //return _Devices.Select(d => d.Key).ToList();
- return Devices.Values;
- }
-
- public static IKeyed GetDeviceForKey(string key)
- {
- //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
- if (key != null && Devices.ContainsKey(key))
- return Devices[key];
-
- return null;
- }
-
- ///
- /// Console handler that simulates com port data receive
- ///
- ///
- public static void SimulateComReceiveOnDevice(string s)
- {
- // devcomsim:1 xyzabc
- var match = Regex.Match(s, @"(\S*)\s*(.*)");
- if (match.Groups.Count < 3)
- {
- CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P ");
- return;
- }
- //Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
-
- var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
- if (com == null)
- {
- CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
- return;
- }
- com.SimulateReceive(match.Groups[2].Value);
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+
+using PepperDash.Core;
+
+
+namespace PepperDash.Essentials.Core
+{
+ public static class DeviceManager
+ {
+ public static event EventHandler AllDevicesActivated;
+
+ private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
+ private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
+ //public static List Devices { get { return _Devices; } }
+ //static List _Devices = new List();
+
+ static readonly Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase);
+
+ ///
+ /// Returns a copy of all the devices in a list
+ ///
+ public static List AllDevices { get { return new List(Devices.Values); } }
+
+ public static bool AddDeviceEnabled;
+
+ public static void Initialize(CrestronControlSystem cs)
+ {
+ AddDeviceEnabled = true;
+ CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
+ "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
+
+ CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
+ }
+
+ ///
+ /// Calls activate steps on all Device class items
+ ///
+ public static void ActivateAll()
+ {
+ try
+ {
+ DeviceCriticalSection.Enter();
+ AddDeviceEnabled = false;
+ // PreActivate all devices
+ foreach (var d in Devices.Values)
+ {
+ try
+ {
+ if (d is Device)
+ (d as Device).PreActivate();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
+ }
+ }
+
+ // Activate all devices
+ foreach (var d in Devices.Values)
+ {
+ try
+ {
+ if (d is Device)
+ (d as Device).Activate();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
+ }
+ }
+
+ // PostActivate all devices
+ foreach (var d in Devices.Values)
+ {
+ try
+ {
+ if (d is Device)
+ (d as Device).PostActivate();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
+ }
+ }
+
+ OnAllDevicesActivated();
+ }
+ finally
+ {
+ DeviceCriticalSection.Leave();
+ }
+ }
+
+ private static void OnAllDevicesActivated()
+ {
+ var handler = AllDevicesActivated;
+ if (handler != null)
+ {
+ handler(null, new EventArgs());
+ }
+ }
+
+ ///
+ /// Calls activate on all Device class items
+ ///
+ public static void DeactivateAll()
+ {
+ try
+ {
+ DeviceCriticalSection.Enter();
+ foreach (var d in Devices.Values.OfType())
+ {
+ d.Deactivate();
+ }
+ }
+ finally
+ {
+ DeviceCriticalSection.Leave();
+ }
+ }
+
+ //static void ListMethods(string devKey)
+ //{
+ // var dev = GetDeviceForKey(devKey);
+ // if(dev != null)
+ // {
+ // var type = dev.GetType().GetCType();
+ // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
+ // var sb = new StringBuilder();
+ // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
+ // foreach (var m in methods)
+ // {
+ // sb.Append(string.Format("{0}(", m.Name));
+ // var pars = m.GetParameters();
+ // foreach (var p in pars)
+ // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
+ // sb.AppendLine(")");
+ // }
+ // CrestronConsole.ConsoleCommandResponse(sb.ToString());
+ // }
+ //}
+
+ private static void ListDevices(string s)
+ {
+ Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count);
+ var sorted = Devices.Values.ToList();
+ sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
+
+ foreach (var d in sorted)
+ {
+ var name = d is IKeyName ? (d as IKeyName).Name : "---";
+ Debug.Console(0, " [{0}] {1}", d.Key, name);
+ }
+ }
+
+ private static void ListDeviceFeedbacks(string devKey)
+ {
+ var dev = GetDeviceForKey(devKey);
+ if (dev == null)
+ {
+ Debug.Console(0, "Device '{0}' not found", devKey);
+ return;
+ }
+ var statusDev = dev as IHasFeedback;
+ if (statusDev == null)
+ {
+ Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey);
+ return;
+ }
+ statusDev.DumpFeedbacksToConsole(true);
+ }
+
+ //static void ListDeviceCommands(string devKey)
+ //{
+ // var dev = GetDeviceForKey(devKey);
+ // if (dev == null)
+ // {
+ // Debug.Console(0, "Device '{0}' not found", devKey);
+ // return;
+ // }
+ // Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey);
+ //}
+
+ private static void ListDeviceCommStatuses(string input)
+ {
+ var sb = new StringBuilder();
+ foreach (var dev in Devices.Values.OfType())
+ {
+ sb.Append(string.Format("{0}: {1}\r", dev,
+ dev.CommunicationMonitor.Status));
+ }
+ CrestronConsole.ConsoleCommandResponse(sb.ToString());
+ }
+
+
+ //static void DoDeviceCommand(string command)
+ //{
+ // Debug.Console(0, "Not yet implemented. Stay tuned");
+ //}
+
+ public static void AddDevice(IKeyed newDev)
+ {
+ try
+ {
+ if (!DeviceCriticalSection.TryEnter())
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again");
+ return;
+ }
+ // Check for device with same key
+ //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
+ ////// If it exists, remove or warn??
+ //if (existingDevice != null)
+
+ if (!AddDeviceEnabled)
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed.");
+ return;
+ }
+
+ if (Devices.ContainsKey(newDev.Key))
+ {
+ Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager");
+ return;
+ }
+ Devices.Add(newDev.Key, newDev);
+ //if (!(_Devices.Contains(newDev)))
+ // _Devices.Add(newDev);
+ }
+ finally
+ {
+ DeviceCriticalSection.Leave();
+ }
+ }
+
+ public static void AddDevice(IEnumerable devicesToAdd)
+ {
+ try
+ {
+ if (!DeviceCriticalSection.TryEnter())
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Error,
+ "Currently unable to add devices to Device Manager. Please try again");
+ return;
+ }
+ if (!AddDeviceEnabled)
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Error,
+ "All devices have been activated. Adding new devices is not allowed.");
+ return;
+ }
+
+ foreach (var dev in devicesToAdd)
+ {
+ try
+ {
+ Devices.Add(dev.Key, dev);
+ }
+ catch (ArgumentException ex)
+ {
+ Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}",
+ dev.Key, ex.Message, ex.StackTrace);
+ }
+ }
+ }
+ finally
+ {
+ DeviceCriticalSection.Leave();
+ }
+ }
+
+ public static void RemoveDevice(IKeyed newDev)
+ {
+ try
+ {
+ DeviceCriticalSection.Enter();
+ if (newDev == null)
+ return;
+ if (Devices.ContainsKey(newDev.Key))
+ Devices.Remove(newDev.Key);
+ //if (_Devices.Contains(newDev))
+ // _Devices.Remove(newDev);
+ else
+ Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
+ }
+ finally
+ {
+ DeviceCriticalSection.Leave();
+ }
+ }
+
+ public static IEnumerable GetDeviceKeys()
+ {
+ //return _Devices.Select(d => d.Key).ToList();
+ return Devices.Keys;
+ }
+
+ public static IEnumerable GetDevices()
+ {
+ //return _Devices.Select(d => d.Key).ToList();
+ return Devices.Values;
+ }
+
+ public static IKeyed GetDeviceForKey(string key)
+ {
+ //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
+ if (key != null && Devices.ContainsKey(key))
+ return Devices[key];
+
+ return null;
+ }
+
+ ///
+ /// Console handler that simulates com port data receive
+ ///
+ ///
+ public static void SimulateComReceiveOnDevice(string s)
+ {
+ // devcomsim:1 xyzabc
+ var match = Regex.Match(s, @"(\S*)\s*(.*)");
+ if (match.Groups.Count < 3)
+ {
+ CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P ");
+ return;
+ }
+ //Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
+
+ var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
+ if (com == null)
+ {
+ CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
+ return;
+ }
+ com.SimulateReceive(match.Groups[2].Value);
}
///
@@ -366,82 +379,82 @@ namespace PepperDash.Essentials.Core
Debug.Console(0, "{0}", routingOutputPort.Key);
}
}
- }
-
- ///
- /// Attempts to set the debug level of a device
- ///
- ///
- public static void SetDeviceStreamDebugging(string s)
- {
- var args = s.Split(' ');
-
- var deviceKey = args[0];
- var setting = args[1];
-
- var timeout= String.Empty;
-
- if (args.Length >= 3)
- {
- timeout = args[2];
- }
-
- var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
-
- if (device == null)
- {
- Debug.Console(0, "Unable to get device with key: {0}", deviceKey);
- return;
- }
-
- eStreamDebuggingSetting debugSetting;
-
- try
- {
- debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true);
- }
- catch
- {
- Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both");
- return;
- }
-
- if (!string.IsNullOrEmpty(timeout))
- {
- try
- {
- 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);
-
- }
- catch (Exception e)
- {
- Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e);
- }
- }
- else
- {
- device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
- Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
- }
- }
-
- ///
- /// Sets stream debugging settings to off for all devices
- ///
- public static void DisableAllDeviceStreamDebugging()
- {
- foreach (var device in AllDevices)
- {
- var streamDevice = device as IStreamDebugging;
-
- if (streamDevice != null)
- {
- streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
- }
- }
- }
- }
+ }
+
+ ///
+ /// Attempts to set the debug level of a device
+ ///
+ ///
+ public static void SetDeviceStreamDebugging(string s)
+ {
+ var args = s.Split(' ');
+
+ var deviceKey = args[0];
+ var setting = args[1];
+
+ var timeout= String.Empty;
+
+ if (args.Length >= 3)
+ {
+ timeout = args[2];
+ }
+
+ var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
+
+ if (device == null)
+ {
+ Debug.Console(0, "Unable to get device with key: {0}", deviceKey);
+ return;
+ }
+
+ eStreamDebuggingSetting debugSetting;
+
+ try
+ {
+ debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true);
+ }
+ catch
+ {
+ Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both");
+ return;
+ }
+
+ if (!string.IsNullOrEmpty(timeout))
+ {
+ try
+ {
+ 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);
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e);
+ }
+ }
+ else
+ {
+ device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
+ Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
+ }
+ }
+
+ ///
+ /// Sets stream debugging settings to off for all devices
+ ///
+ public static void DisableAllDeviceStreamDebugging()
+ {
+ foreach (var device in AllDevices)
+ {
+ var streamDevice = device as IStreamDebugging;
+
+ if (streamDevice != null)
+ {
+ streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/BasicIrDisplay.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/BasicIrDisplay.cs
index f06c8380..8d70bd55 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/BasicIrDisplay.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/BasicIrDisplay.cs
@@ -20,10 +20,12 @@ namespace PepperDash.Essentials.Core
public IrOutputPortController IrPort { get; private set; }
public ushort IrPulseTime { get; set; }
- protected override Func PowerIsOnFeedbackFunc
- {
- get { return () => _PowerIsOn; }
- }
+ public BoolFeedback PowerIsOnFeedback { get; private set; }
+
+ protected Func PowerIsOnFeedbackFunc
+ {
+ get { return () => _PowerIsOn; }
+ }
protected override Func IsCoolingDownFeedbackFunc
{
get { return () => _IsCoolingDown; }
@@ -33,7 +35,7 @@ namespace PepperDash.Essentials.Core
get { return () => _IsWarmingUp; }
}
- bool _PowerIsOn;
+ bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
@@ -43,11 +45,14 @@ namespace PepperDash.Essentials.Core
IrPort = new IrOutputPortController(key + "-ir", port, irDriverFilepath);
DeviceManager.AddDevice(IrPort);
- PowerIsOnFeedback.OutputChange += (o, a) => {
- Debug.Console(2, this, "Power on={0}", _PowerIsOn);
- if (_PowerIsOn) StartWarmingTimer();
- else StartCoolingTimer();
- };
+ PowerIsOnFeedback = new BoolFeedback(PowerIsOnFeedbackFunc);
+
+ PowerIsOnFeedback.OutputChange += (o, a) =>
+ {
+ Debug.Console(2, this, "Power on={0}", _PowerIsOn);
+ if (_PowerIsOn) StartWarmingTimer();
+ else StartCoolingTimer();
+ };
IsWarmingUpFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Warming up={0}", _IsWarmingUp);
IsCoolingDownFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Cooling down={0}", _IsCoolingDown);
@@ -110,21 +115,21 @@ namespace PepperDash.Essentials.Core
public override void PowerOn()
{
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
- _PowerIsOn = true;
- PowerIsOnFeedback.FireUpdate();
+ _PowerIsOn = true;
+ PowerIsOnFeedback.FireUpdate();
}
public override void PowerOff()
{
- _PowerIsOn = false;
- PowerIsOnFeedback.FireUpdate();
+ _PowerIsOn = false;
+ PowerIsOnFeedback.FireUpdate();
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
public override void PowerToggle()
{
- _PowerIsOn = false;
- PowerIsOnFeedback.FireUpdate();
+ _PowerIsOn = false;
+ PowerIsOnFeedback.FireUpdate();
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs
index 5ad143c9..e4a2cb26 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/DisplayBase.cs
@@ -1,131 +1,117 @@
-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;
-using Crestron.SimplSharpPro.DM.Endpoints;
-using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
-using Newtonsoft.Json;
-using PepperDash.Core;
-using PepperDash.Essentials.Core.Bridges;
-
-
-namespace PepperDash.Essentials.Core
-{
- ///
- ///
- ///
- public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IPower, IWarmingCooling, IUsageTracking
- {
- public event SourceInfoChangeHandler CurrentSourceChange;
-
- public string CurrentSourceInfoKey { get; set; }
- public SourceListItem CurrentSourceInfo
- {
- get
- {
- return _CurrentSourceInfo;
- }
- set
- {
- if (value == _CurrentSourceInfo) return;
-
- var handler = CurrentSourceChange;
-
- if (handler != null)
- handler(_CurrentSourceInfo, ChangeType.WillChange);
-
- _CurrentSourceInfo = value;
-
- if (handler != null)
- handler(_CurrentSourceInfo, ChangeType.DidChange);
- }
- }
- SourceListItem _CurrentSourceInfo;
-
- public BoolFeedback PowerIsOnFeedback { get; protected set; }
- public BoolFeedback IsCoolingDownFeedback { get; protected set; }
- public BoolFeedback IsWarmingUpFeedback { get; private set; }
-
- public UsageTracking UsageTracker { get; set; }
-
- public uint WarmupTime { get; set; }
- public uint CooldownTime { get; set; }
-
- ///
- /// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
- /// by concrete sub-classes
- ///
- abstract protected Func PowerIsOnFeedbackFunc { get; }
- abstract protected Func IsCoolingDownFeedbackFunc { get; }
- abstract protected Func IsWarmingUpFeedbackFunc { get; }
-
-
- protected CTimer WarmupTimer;
- protected CTimer CooldownTimer;
-
- #region IRoutingInputs Members
-
- public RoutingPortCollection InputPorts { get; private set; }
-
- #endregion
-
- protected DisplayBase(string key, string name)
- : base(key, name)
- {
- PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
- IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
- IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
-
- InputPorts = new RoutingPortCollection();
-
- PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
- }
-
- void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
- {
- if (UsageTracker != null)
- {
- if (PowerIsOnFeedback.BoolValue)
- UsageTracker.StartDeviceUsage();
- else
- UsageTracker.EndDeviceUsage();
- }
- }
-
- public abstract void PowerOn();
- public abstract void PowerOff();
- public abstract void PowerToggle();
-
- public virtual FeedbackCollection Feedbacks
- {
- get
- {
- return new FeedbackCollection
- {
- PowerIsOnFeedback,
- IsCoolingDownFeedback,
- IsWarmingUpFeedback
- };
- }
- }
-
- public abstract void ExecuteSwitch(object selector);
-
- protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
- EiscApiAdvanced bridge)
- {
- var inputNumber = 0;
- var inputKeys = new List();
-
- var joinMap = new DisplayControllerJoinMap(joinStart);
-
- var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
-
- if (!string.IsNullOrEmpty(joinMapSerialized))
+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;
+using Crestron.SimplSharpPro.DM.Endpoints;
+using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core.Bridges;
+
+
+namespace PepperDash.Essentials.Core
+{
+ ///
+ ///
+ ///
+ public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking
+ {
+ public event SourceInfoChangeHandler CurrentSourceChange;
+
+ public string CurrentSourceInfoKey { get; set; }
+ public SourceListItem CurrentSourceInfo
+ {
+ get
+ {
+ return _CurrentSourceInfo;
+ }
+ set
+ {
+ if (value == _CurrentSourceInfo) return;
+
+ var handler = CurrentSourceChange;
+
+ if (handler != null)
+ handler(_CurrentSourceInfo, ChangeType.WillChange);
+
+ _CurrentSourceInfo = value;
+
+ if (handler != null)
+ handler(_CurrentSourceInfo, ChangeType.DidChange);
+ }
+ }
+ SourceListItem _CurrentSourceInfo;
+
+ public BoolFeedback IsCoolingDownFeedback { get; protected set; }
+ public BoolFeedback IsWarmingUpFeedback { get; private set; }
+
+ public UsageTracking UsageTracker { get; set; }
+
+ public uint WarmupTime { get; set; }
+ public uint CooldownTime { get; set; }
+
+ ///
+ /// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
+ /// by concrete sub-classes
+ ///
+ abstract protected Func IsCoolingDownFeedbackFunc { get; }
+ abstract protected Func IsWarmingUpFeedbackFunc { get; }
+
+
+ protected CTimer WarmupTimer;
+ protected CTimer CooldownTimer;
+
+ #region IRoutingInputs Members
+
+ public RoutingPortCollection InputPorts { get; private set; }
+
+ #endregion
+
+ protected DisplayBase(string key, string name)
+ : base(key, name)
+ {
+ IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
+ IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
+
+ InputPorts = new RoutingPortCollection();
+
+ }
+
+
+
+ public abstract void PowerOn();
+ public abstract void PowerOff();
+ public abstract void PowerToggle();
+
+ public virtual FeedbackCollection Feedbacks
+ {
+ get
+ {
+ return new FeedbackCollection
+ {
+ IsCoolingDownFeedback,
+ IsWarmingUpFeedback
+ };
+ }
+ }
+
+ public abstract void ExecuteSwitch(object selector);
+
+ protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
+ EiscApiAdvanced bridge)
+ {
+ var inputNumber = 0;
+ var inputKeys = new List();
+
+ var joinMap = new DisplayControllerJoinMap(joinStart);
+
+ var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
+
+ if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject(joinMapSerialized);
if (bridge != null)
@@ -137,163 +123,199 @@ namespace PepperDash.Essentials.Core
Debug.Console(0,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
- Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
- Debug.Console(0, "Linking to Display: {0}", displayDevice.Name);
-
- trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
-
- var commMonitor = displayDevice as ICommunicationMonitor;
- if (commMonitor != null)
- {
- commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
- }
-
- var inputNumberFeedback = new IntFeedback(() => inputNumber);
-
- // Two way feedbacks
- var twoWayDisplay = displayDevice as TwoWayDisplayBase;
-
- if (twoWayDisplay != null)
- {
- trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
-
- twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
-
-
- inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
- }
-
- // Power Off
- trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
- {
- inputNumber = 102;
- inputNumberFeedback.FireUpdate();
- displayDevice.PowerOff();
- });
-
- displayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
- {
- if (!a.BoolValue)
- {
- inputNumber = 102;
- inputNumberFeedback.FireUpdate();
-
- }
- else
- {
- inputNumber = 0;
- inputNumberFeedback.FireUpdate();
- }
- };
-
- displayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
-
- // PowerOn
- trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
- {
- inputNumber = 0;
- inputNumberFeedback.FireUpdate();
- displayDevice.PowerOn();
- });
-
-
- displayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
-
- for (int i = 0; i < displayDevice.InputPorts.Count; i++)
- {
- if (i < joinMap.InputNamesOffset.JoinSpan)
- {
- inputKeys.Add(displayDevice.InputPorts[i].Key);
- var tempKey = inputKeys.ElementAt(i);
- trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
- () => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
- Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
- joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
- trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
- }
- else
- Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
- displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
- }
-
- Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
- trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
- {
- if (a == 0)
- {
- displayDevice.PowerOff();
- inputNumber = 0;
- }
- else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
- {
- displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
- inputNumber = a;
- }
- else if (a == 102)
- {
- displayDevice.PowerToggle();
-
- }
- if (twoWayDisplay != null)
- inputNumberFeedback.FireUpdate();
- });
-
-
- var volumeDisplay = displayDevice as IBasicVolumeControls;
- if (volumeDisplay == null) return;
-
- trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
- trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
- trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
-
- var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
-
- if (volumeDisplayWithFeedback == null) return;
- trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
- trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
-
-
- trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
- volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
- volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
- volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
- volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
- }
- }
-
- ///
- ///
- ///
- public abstract class TwoWayDisplayBase : DisplayBase
- {
- public StringFeedback CurrentInputFeedback { get; private set; }
-
- abstract protected Func CurrentInputFeedbackFunc { get; }
-
-
- public static MockDisplay DefaultDisplay
- {
- get
- {
- if (_DefaultDisplay == null)
- _DefaultDisplay = new MockDisplay("default", "Default Display");
- return _DefaultDisplay;
- }
- }
- static MockDisplay _DefaultDisplay;
-
- public TwoWayDisplayBase(string key, string name)
- : base(key, name)
- {
- CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
-
- WarmupTime = 7000;
- CooldownTime = 15000;
-
- Feedbacks.Add(CurrentInputFeedback);
-
-
- }
-
- }
+ Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
+ Debug.Console(0, "Linking to Display: {0}", displayDevice.Name);
+
+ trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
+
+ var commMonitor = displayDevice as ICommunicationMonitor;
+ if (commMonitor != null)
+ {
+ commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
+ }
+
+ var inputNumberFeedback = new IntFeedback(() => inputNumber);
+
+ // Two way feedbacks
+ var twoWayDisplay = displayDevice as TwoWayDisplayBase;
+
+ if (twoWayDisplay != null)
+ {
+ trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
+
+ twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.Console(0, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
+
+
+ inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
+ }
+
+ // Power Off
+ trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
+ {
+ inputNumber = 102;
+ inputNumberFeedback.FireUpdate();
+ displayDevice.PowerOff();
+ });
+
+ var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
+ if (twoWayDisplayDevice != null)
+ {
+ twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
+ {
+ if (!a.BoolValue)
+ {
+ inputNumber = 102;
+ inputNumberFeedback.FireUpdate();
+
+ }
+ else
+ {
+ inputNumber = 0;
+ inputNumberFeedback.FireUpdate();
+ }
+ };
+
+ twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
+ twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
+ }
+
+ // PowerOn
+ trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
+ {
+ inputNumber = 0;
+ inputNumberFeedback.FireUpdate();
+ displayDevice.PowerOn();
+ });
+
+
+
+ for (int i = 0; i < displayDevice.InputPorts.Count; i++)
+ {
+ if (i < joinMap.InputNamesOffset.JoinSpan)
+ {
+ inputKeys.Add(displayDevice.InputPorts[i].Key);
+ var tempKey = inputKeys.ElementAt(i);
+ trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
+ () => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
+ Debug.Console(2, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
+ joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
+ trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
+ }
+ else
+ Debug.Console(0, displayDevice, Debug.ErrorLogLevel.Warning, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
+ displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
+ }
+
+ Debug.Console(2, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
+ trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
+ {
+ if (a == 0)
+ {
+ displayDevice.PowerOff();
+ inputNumber = 0;
+ }
+ else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
+ {
+ displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
+ inputNumber = a;
+ }
+ else if (a == 102)
+ {
+ displayDevice.PowerToggle();
+
+ }
+ if (twoWayDisplay != null)
+ inputNumberFeedback.FireUpdate();
+ });
+
+
+ var volumeDisplay = displayDevice as IBasicVolumeControls;
+ if (volumeDisplay == null) return;
+
+ trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
+ trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
+ trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
+
+ var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
+
+ if (volumeDisplayWithFeedback == null) return;
+ trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
+ trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
+
+
+ trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
+ volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
+ volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
+ volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
+ volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
+ }
+
+ }
+
+ ///
+ ///
+ ///
+ public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
+ {
+ public StringFeedback CurrentInputFeedback { get; private set; }
+
+ abstract protected Func CurrentInputFeedbackFunc { get; }
+
+ public BoolFeedback PowerIsOnFeedback { get; protected set; }
+ abstract protected Func PowerIsOnFeedbackFunc { get; }
+
+
+ public static MockDisplay DefaultDisplay
+ {
+ get
+ {
+ if (_DefaultDisplay == null)
+ _DefaultDisplay = new MockDisplay("default", "Default Display");
+ return _DefaultDisplay;
+ }
+ }
+ static MockDisplay _DefaultDisplay;
+
+ public TwoWayDisplayBase(string key, string name)
+ : base(key, name)
+ {
+ CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
+
+ WarmupTime = 7000;
+ CooldownTime = 15000;
+
+ PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
+
+ Feedbacks.Add(CurrentInputFeedback);
+ Feedbacks.Add(PowerIsOnFeedback);
+
+ PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
+
+ }
+
+ void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
+ {
+ if (UsageTracker != null)
+ {
+ if (PowerIsOnFeedback.BoolValue)
+ UsageTracker.StartDeviceUsage();
+ else
+ UsageTracker.EndDeviceUsage();
+ }
+ }
+
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ protected void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
+
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs
index 52c30e19..39cd7d78 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs
@@ -1,170 +1,170 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Crestron.SimplSharp;
-using Crestron.SimplSharp.CrestronIO;
-using Crestron.SimplSharp.CrestronXml;
-using Crestron.SimplSharp.CrestronXml.Serialization;
-using Crestron.SimplSharp.CrestronXmlLinq;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.DeviceSupport;
-using Crestron.SimplSharpPro.Fusion;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-using PepperDash.Core;
-using PepperDash.Essentials;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Config;
-
-
-
-namespace PepperDash.Essentials.Core.Fusion
-{
- public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider
- {
- public event EventHandler ScheduleChange;
- //public event EventHandler MeetingEndWarning;
- //public event EventHandler NextMeetingBeginWarning;
-
- public event EventHandler RoomInfoChange;
-
- public FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
-
- protected FusionRoom FusionRoom;
- protected EssentialsRoomBase Room;
- Dictionary SourceToFeedbackSigs =
- new Dictionary();
-
- StatusMonitorCollection ErrorMessageRollUp;
-
- protected StringSigData CurrentRoomSourceNameSig;
-
- #region System Info Sigs
- //StringSigData SystemName;
- //StringSigData Model;
- //StringSigData SerialNumber;
- //StringSigData Uptime;
- #endregion
-
-
- #region Processor Info Sigs
- StringSigData Ip1;
- StringSigData Ip2;
- StringSigData Gateway;
- StringSigData Hostname;
- StringSigData Domain;
- StringSigData Dns1;
- StringSigData Dns2;
- StringSigData Mac1;
- StringSigData Mac2;
- StringSigData NetMask1;
- StringSigData NetMask2;
- StringSigData Firmware;
-
- StringSigData[] Program = new StringSigData[10];
- #endregion
-
- #region Default Display Source Sigs
-
- BooleanSigData[] Source = new BooleanSigData[10];
-
- #endregion
-
- RoomSchedule CurrentSchedule;
-
- Event NextMeeting;
-
- Event CurrentMeeting;
-
- protected string RoomGuid
- {
- get
- {
- return GUIDs.RoomGuid;
- }
-
- }
-
- uint IpId;
-
- FusionRoomGuids GUIDs;
-
- bool GuidFileExists;
-
- bool IsRegisteredForSchedulePushNotifications = false;
-
- CTimer PollTimer = null;
-
- CTimer PushNotificationTimer = null;
-
- CTimer DailyTimeRequestTimer = null;
-
- // Default poll time is 5 min unless overridden by config value
- public long SchedulePollInterval = 300000;
-
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.CrestronIO;
+using Crestron.SimplSharp.CrestronXml;
+using Crestron.SimplSharp.CrestronXml.Serialization;
+using Crestron.SimplSharp.CrestronXmlLinq;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.Fusion;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+using PepperDash.Core;
+using PepperDash.Essentials;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+
+
+
+namespace PepperDash.Essentials.Core.Fusion
+{
+ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider
+ {
+ public event EventHandler ScheduleChange;
+ //public event EventHandler MeetingEndWarning;
+ //public event EventHandler NextMeetingBeginWarning;
+
+ public event EventHandler RoomInfoChange;
+
+ public FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
+
+ protected FusionRoom FusionRoom;
+ protected EssentialsRoomBase Room;
+ Dictionary SourceToFeedbackSigs =
+ new Dictionary();
+
+ StatusMonitorCollection ErrorMessageRollUp;
+
+ protected StringSigData CurrentRoomSourceNameSig;
+
+ #region System Info Sigs
+ //StringSigData SystemName;
+ //StringSigData Model;
+ //StringSigData SerialNumber;
+ //StringSigData Uptime;
+ #endregion
+
+
+ #region Processor Info Sigs
+ StringSigData Ip1;
+ StringSigData Ip2;
+ StringSigData Gateway;
+ StringSigData Hostname;
+ StringSigData Domain;
+ StringSigData Dns1;
+ StringSigData Dns2;
+ StringSigData Mac1;
+ StringSigData Mac2;
+ StringSigData NetMask1;
+ StringSigData NetMask2;
+ StringSigData Firmware;
+
+ StringSigData[] Program = new StringSigData[10];
+ #endregion
+
+ #region Default Display Source Sigs
+
+ BooleanSigData[] Source = new BooleanSigData[10];
+
+ #endregion
+
+ RoomSchedule CurrentSchedule;
+
+ Event NextMeeting;
+
+ Event CurrentMeeting;
+
+ protected string RoomGuid
+ {
+ get
+ {
+ return GUIDs.RoomGuid;
+ }
+
+ }
+
+ uint IpId;
+
+ FusionRoomGuids GUIDs;
+
+ bool GuidFileExists;
+
+ bool IsRegisteredForSchedulePushNotifications = false;
+
+ CTimer PollTimer = null;
+
+ CTimer PushNotificationTimer = null;
+
+ CTimer DailyTimeRequestTimer = null;
+
+ // Default poll time is 5 min unless overridden by config value
+ public long SchedulePollInterval = 300000;
+
public long PushNotificationTimeout = 5000;
- private const string RemoteOccupancyXml = "Local{0}";
-
- protected Dictionary FusionStaticAssets;
-
- // For use with local occ sensor devices which will relay to Fusion the current occupancy status
- protected FusionRemoteOccupancySensor FusionRemoteOccSensor;
-
- // For use with occ sensor attached to a scheduling panel in Fusion
- protected FusionOccupancySensorAsset FusionOccSensor;
-
+ private const string RemoteOccupancyXml = "Local{0}";
+
+ protected Dictionary FusionStaticAssets;
+
+ // For use with local occ sensor devices which will relay to Fusion the current occupancy status
+ protected FusionRemoteOccupancySensor FusionRemoteOccSensor;
+
+ // For use with occ sensor attached to a scheduling panel in Fusion
+ protected FusionOccupancySensorAsset FusionOccSensor;
+
public BoolFeedback RoomIsOccupiedFeedback { get; private set; }
- private string _roomOccupancyRemoteString;
- public StringFeedback RoomOccupancyRemoteStringFeedback { get; private set; }
-
- protected Func RoomIsOccupiedFeedbackFunc
- {
- get
- {
- return () => FusionRemoteOccSensor.RoomOccupied.OutputSig.BoolValue;
- }
- }
-
- //ScheduleResponseEvent NextMeeting;
-
- public EssentialsHuddleSpaceFusionSystemControllerBase(EssentialsRoomBase room, uint ipId)
- : base(room.Key + "-fusion")
- {
-
- try
- {
-
- Room = room;
-
- IpId = ipId;
-
- FusionStaticAssets = new Dictionary();
-
- GUIDs = new FusionRoomGuids();
-
- var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
-
- var slot = Global.ControlSystem.ProgramNumber;
-
- string guidFilePath = Global.FilePathPrefix + string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
-
- GuidFileExists = File.Exists(guidFilePath);
-
- // Check if file exists
- if (!GuidFileExists)
- {
- // Does not exist. Create GUIDs
- GUIDs = new FusionRoomGuids(Room.Name, ipId, GUIDs.GenerateNewRoomGuid(slot, mac), FusionStaticAssets);
- }
- else
- {
- // Exists. Read GUIDs
- ReadGuidFile(guidFilePath);
+ private string _roomOccupancyRemoteString;
+ public StringFeedback RoomOccupancyRemoteStringFeedback { get; private set; }
+
+ protected Func RoomIsOccupiedFeedbackFunc
+ {
+ get
+ {
+ return () => FusionRemoteOccSensor.RoomOccupied.OutputSig.BoolValue;
+ }
+ }
+
+ //ScheduleResponseEvent NextMeeting;
+
+ public EssentialsHuddleSpaceFusionSystemControllerBase(EssentialsRoomBase room, uint ipId)
+ : base(room.Key + "-fusion")
+ {
+
+ try
+ {
+
+ Room = room;
+
+ IpId = ipId;
+
+ FusionStaticAssets = new Dictionary();
+
+ GUIDs = new FusionRoomGuids();
+
+ var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
+
+ var slot = Global.ControlSystem.ProgramNumber;
+
+ string guidFilePath = Global.FilePathPrefix + string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
+
+ GuidFileExists = File.Exists(guidFilePath);
+
+ // Check if file exists
+ if (!GuidFileExists)
+ {
+ // Does not exist. Create GUIDs
+ GUIDs = new FusionRoomGuids(Room.Name, ipId, GUIDs.GenerateNewRoomGuid(slot, mac), FusionStaticAssets);
+ }
+ else
+ {
+ // Exists. Read GUIDs
+ ReadGuidFile(guidFilePath);
}
if (Room.RoomOccupancy != null)
@@ -175,10 +175,10 @@ namespace PepperDash.Essentials.Core.Fusion
{
SetUpLocalOccupancy();
}
- }
-
-
-
+ }
+
+
+
AddPostActivationAction(() =>
{
CreateSymbolAndBasicSigs(IpId);
@@ -191,1199 +191,1210 @@ namespace PepperDash.Essentials.Core.Fusion
FusionRVI.GenerateFileForAllFusionDevices();
GenerateGuidFile(guidFilePath);
- });
-
- }
- catch (Exception e)
- {
- Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Building Fusion System Controller: {0}", e);
- }
- }
-
- ///
- /// Used for extension classes to execute whatever steps are necessary before generating the RVI and GUID files
- ///
- protected virtual void ExecuteCustomSteps()
- {
-
- }
-
- ///
- /// Generates the guid file in NVRAM. If the file already exists it will be overwritten.
- ///
- /// path for the file
- void GenerateGuidFile(string filePath)
- {
- if (string.IsNullOrEmpty(filePath))
- {
- Debug.Console(0, this, "Error writing guid file. No path specified.");
- return;
- }
-
- CCriticalSection _fileLock = new CCriticalSection();
-
- try
- {
- if (_fileLock == null || _fileLock.Disposed)
- return;
-
- _fileLock.Enter();
-
- Debug.Console(1, this, "Writing GUIDs to file");
-
- if (FusionOccSensor == null)
- GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets);
- else
- GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets, FusionOccSensor);
-
- var JSON = JsonConvert.SerializeObject(GUIDs, Newtonsoft.Json.Formatting.Indented);
-
- using (StreamWriter sw = new StreamWriter(filePath))
- {
- sw.Write(JSON);
- sw.Flush();
- }
-
- Debug.Console(1, this, "Guids successfully written to file '{0}'", filePath);
-
- }
- catch (Exception e)
- {
- Debug.Console(0, this, "Error writing guid file: {0}", e);
- }
- finally
- {
- if (_fileLock != null && !_fileLock.Disposed)
- _fileLock.Leave();
- }
- }
-
- ///
- /// Reads the guid file from NVRAM
- ///
- /// path for te file
- void ReadGuidFile(string filePath)
- {
- if(string.IsNullOrEmpty(filePath))
- {
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Error reading guid file. No path specified.");
- return;
- }
-
- CCriticalSection _fileLock = new CCriticalSection();
-
- try
- {
- if(_fileLock == null || _fileLock.Disposed)
- return;
-
- _fileLock.Enter();
-
- if(File.Exists(filePath))
- {
- var JSON = File.ReadToEnd(filePath, Encoding.ASCII);
-
- GUIDs = JsonConvert.DeserializeObject(JSON);
-
- IpId = GUIDs.IpId;
-
- FusionStaticAssets = GUIDs.StaticAssets;
-
- }
-
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Fusion Guids successfully read from file: {0}", filePath);
-
- Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1:x}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid);
-
- foreach (var item in FusionStaticAssets)
- {
- Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, item.Value.SlotNumber, item.Value.InstanceId);
- }
- }
- catch (Exception e)
- {
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Error reading guid file: {0}", e);
- }
- finally
- {
- if(_fileLock != null && !_fileLock.Disposed)
- _fileLock.Leave();
- }
-
- }
-
- protected virtual void CreateSymbolAndBasicSigs(uint ipId)
- {
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
-
- FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
- FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
-
- FusionRoom.Register();
-
- FusionRoom.FusionStateChange += new FusionStateEventHandler(FusionRoom_FusionStateChange);
-
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(FusionRoomSchedule_DeviceExtenderSigChange);
- FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange);
- FusionRoom.OnlineStatusChange += new OnlineStatusChangeEventHandler(FusionRoom_OnlineStatusChange);
-
- CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
-
- // Room to fusion room
- Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
-
- // Moved to
- CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
- // Don't think we need to get current status of this as nothing should be alive yet.
- (Room as IHasCurrentSourceInfoChange).CurrentSourceChange += new SourceInfoChangeHandler(Room_CurrentSourceInfoChange);
-
-
- FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsRoomBase).PowerOnToDefaultOrLastSource);
- FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as IRunRouteAction).RunRouteAction("roomOff", Room.SourceListKey));
- // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
- FusionRoom.ErrorMessage.InputSig.StringValue =
- "3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;";
-
- SetUpEthernetValues();
-
- GetProcessorEthernetValues();
-
- GetSystemInfo();
-
- GetProcessorInfo();
-
- CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
- }
-
- protected void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
- {
- if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp)
- {
- GetProcessorEthernetValues();
- }
- }
-
- protected void GetSystemInfo()
- {
- //SystemName.InputSig.StringValue = Room.Name;
- //Model.InputSig.StringValue = InitialParametersClass.ControllerPromptName;
- //SerialNumber.InputSig.StringValue = InitialParametersClass.
-
- string response = string.Empty;
-
- var systemReboot = FusionRoom.CreateOffsetBoolSig(74, "Processor - Reboot", eSigIoMask.OutputSigOnly);
- systemReboot.OutputSig.SetSigFalseAction(() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
- }
-
- protected void SetUpEthernetValues()
- {
- Ip1 = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - IP 1", eSigIoMask.InputSigOnly);
- Ip2 = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - IP 2", eSigIoMask.InputSigOnly);
- Gateway = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Gateway", eSigIoMask.InputSigOnly);
- Hostname = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Hostname", eSigIoMask.InputSigOnly);
- Domain = FusionRoom.CreateOffsetStringSig(54, "Info - Processor - Domain", eSigIoMask.InputSigOnly);
- Dns1 = FusionRoom.CreateOffsetStringSig(55, "Info - Processor - DNS 1", eSigIoMask.InputSigOnly);
- Dns2 = FusionRoom.CreateOffsetStringSig(56, "Info - Processor - DNS 2", eSigIoMask.InputSigOnly);
- Mac1 = FusionRoom.CreateOffsetStringSig(57, "Info - Processor - MAC 1", eSigIoMask.InputSigOnly);
- Mac2 = FusionRoom.CreateOffsetStringSig(58, "Info - Processor - MAC 2", eSigIoMask.InputSigOnly);
- NetMask1 = FusionRoom.CreateOffsetStringSig(59, "Info - Processor - Net Mask 1", eSigIoMask.InputSigOnly);
- NetMask2 = FusionRoom.CreateOffsetStringSig(60, "Info - Processor - Net Mask 2", eSigIoMask.InputSigOnly);
- }
-
- protected void GetProcessorEthernetValues()
- {
- Ip1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
- Gateway.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0);
- Hostname.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
- Domain.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0);
-
- var dnsServers = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, 0).Split(',');
- Dns1.InputSig.StringValue = dnsServers[0];
- if (dnsServers.Length > 1)
- Dns2.InputSig.StringValue = dnsServers[1];
-
- Mac1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
- NetMask1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 0);
-
- // Interface 1
-
- if (InitialParametersClass.NumberOfEthernetInterfaces > 1) // Only get these values if the processor has more than 1 NIC
- {
- Ip2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 1);
- Mac2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 1);
- NetMask2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 1);
- }
- }
-
- protected void GetProcessorInfo()
- {
-
- Firmware = FusionRoom.CreateOffsetStringSig(61, "Info - Processor - Firmware", eSigIoMask.InputSigOnly);
-
- if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
- {
- for (int i = 0; i < Global.ControlSystem.NumProgramsSupported; i++)
- {
- var join = 62 + i;
- var progNum = i + 1;
- Program[i] = FusionRoom.CreateOffsetStringSig((uint)join, string.Format("Info - Processor - Program {0}", progNum), eSigIoMask.InputSigOnly);
- }
- }
-
- Firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
-
- }
-
- protected void GetCustomProperties()
- {
- if (FusionRoom.IsOnline)
- {
- string fusionRoomCustomPropertiesRequest = @"RoomConfigurationRequest";
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigQuery.StringValue = fusionRoomCustomPropertiesRequest;
- }
- }
-
- void GetTouchpanelInfo()
- {
- // TODO: Get IP and Project Name from TP
- }
-
- protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
- {
- if (args.DeviceOnLine)
- {
- CrestronEnvironment.Sleep(200);
-
- // Send Push Notification Action request:
-
- string requestID = "InitialPushRequest";
-
-
- string actionRequest =
- string.Format("\n{0}\n", requestID) +
- "RegisterPushModel\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n" +
- "\n";
-
- Debug.Console(2, this, "Sending Fusion ActionRequest: \n{0}", actionRequest);
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
-
- GetCustomProperties();
-
- // Request current Fusion Server Time
- RequestLocalDateTime(null);
-
- // Setup timer to request time daily
- if (DailyTimeRequestTimer != null && !DailyTimeRequestTimer.Disposed)
- {
- DailyTimeRequestTimer.Stop();
- DailyTimeRequestTimer.Dispose();
- }
-
- DailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000);
-
- DailyTimeRequestTimer.Reset(86400000, 86400000);
- }
-
- }
-
- ///
- /// Requests the local date and time from the Fusion Server
- ///
- ///
- public void RequestLocalDateTime(object callbackObject)
- {
- string timeRequestID = "TimeRequest";
-
- string timeRequest = string.Format("{0}", timeRequestID);
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest;
- }
-
- ///
- /// Generates a room schedule request for this room for the next 24 hours.
- ///
- /// string identifying this request. Used with a corresponding ScheduleResponse value
- public void RequestFullRoomSchedule(object callbackObject)
- {
- DateTime now = DateTime.Today;
-
- string currentTime = now.ToString("s");
-
- string requestTest =
- string.Format("FullSchedleRequest{0}{1}24", RoomGuid, currentTime);
-
- Debug.Console(2, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest);
-
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest;
-
- if (IsRegisteredForSchedulePushNotifications)
- PushNotificationTimer.Stop();
- }
-
- ///
- /// Wrapper method to allow console commands to modify the current meeting end time
- ///
- /// meetingID extendTime
- public void ModifyMeetingEndTimeConsoleHelper(string command)
- {
- string requestID;
- string meetingID = null;
- int extendMinutes = -1;
-
- requestID = "ModifyMeetingTest12345";
-
- try
- {
- var tokens = command.Split(' ');
-
- meetingID = tokens[0];
- extendMinutes = Int32.Parse(tokens[1]);
-
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing console command: {0}", e);
- }
-
- ModifyMeetingEndTime(requestID, extendMinutes);
-
- }
-
- ///
- /// Ends or Extends the current meeting by the specified number of minutes.
- ///
- /// Number of minutes to extend the meeting. A value of 0 will end the meeting.
- public void ModifyMeetingEndTime(string requestID, int extendMinutes)
- {
- if(CurrentMeeting == null)
- {
- Debug.Console(1, this, "No meeting in progress. Unable to modify end time.");
- return;
- }
-
- if (extendMinutes > -1)
- {
- if(extendMinutes > 0)
- {
- var extendTime = CurrentMeeting.dtEnd - DateTime.Now;
- double extendMinutesRaw = extendTime.TotalMinutes;
-
- extendMinutes = extendMinutes + (int)Math.Round(extendMinutesRaw);
- }
-
-
- string requestTest = string.Format(
- "{0}{1}MeetingChange"
- , requestID, RoomGuid, CurrentMeeting.MeetingID, extendMinutes);
-
- Debug.Console(1, this, "Sending MeetingChange Request: \n{0}", requestTest);
-
- FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest;
- }
- else
- {
- Debug.Console(1, this, "Invalid time specified");
- }
-
-
- }
-
- ///
- /// Creates and Ad Hoc meeting with a duration of 1 hour, or until the next meeting if in less than 1 hour.
- ///
- public void CreateAsHocMeeting(string command)
- {
- string requestID = "CreateAdHocMeeting";
-
- DateTime now = DateTime.Now.AddMinutes(1);
-
- now.AddSeconds(-now.Second);
-
- // Assume 1 hour meeting if possible
- DateTime dtEnd = now.AddHours(1);
-
- // Check if room is available for 1 hour before next meeting
- if (NextMeeting != null)
- {
- var roomAvailable = NextMeeting.dtEnd.Subtract(dtEnd);
-
- if (roomAvailable.TotalMinutes < 60)
- {
- /// Room not available for full hour, book until next meeting starts
- dtEnd = NextMeeting.dtEnd;
- }
- }
-
- string createMeetingRequest =
- "" +
- string.Format("{0}", requestID) +
- string.Format("{0}", RoomGuid) +
- "" +
- string.Format("{0}", now.ToString("s")) +
- string.Format("{0}", dtEnd.ToString("s")) +
- "AdHoc Meeting" +
- "Room User" +
- "Example Message" +
- "" +
- "";
-
- Debug.Console(2, this, "Sending CreateMeeting Request: \n{0}", createMeetingRequest);
-
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = createMeetingRequest;
-
- //Debug.Console(1, this, "Sending CreateMeeting Request: \n{0}", command);
-
- //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = command;
-
- }
-
- ///
- /// Event handler method for Device Extender sig changes
- ///
- ///
- ///
- protected void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
- {
- Debug.Console(2, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
-
-
- if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse)
- {
- try
- {
- XmlDocument message = new XmlDocument();
-
- message.LoadXml(args.Sig.StringValue);
-
- var actionResponse = message["ActionResponse"];
-
- if (actionResponse != null)
- {
- var requestID = actionResponse["RequestID"];
-
- if (requestID.InnerText == "InitialPushRequest")
- {
- if (actionResponse["ActionID"].InnerText == "RegisterPushModel")
- {
- var parameters = actionResponse["Parameters"];
-
- foreach (XmlElement parameter in parameters)
- {
- if (parameter.HasAttributes)
- {
- var attributes = parameter.Attributes;
-
- if (attributes["ID"].Value == "Registered")
- {
- var isRegistered = Int32.Parse(attributes["Value"].Value);
-
- if (isRegistered == 1)
- {
- IsRegisteredForSchedulePushNotifications = true;
-
- if (PollTimer != null && !PollTimer.Disposed)
- {
- PollTimer.Stop();
- PollTimer.Dispose();
- }
-
- PushNotificationTimer = new CTimer(RequestFullRoomSchedule, null, PushNotificationTimeout, PushNotificationTimeout);
-
- PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
- }
- else if (isRegistered == 0)
- {
- IsRegisteredForSchedulePushNotifications = false;
-
- if (PushNotificationTimer != null && !PushNotificationTimer.Disposed)
- {
- PushNotificationTimer.Stop();
- PushNotificationTimer.Dispose();
- }
-
- PollTimer = new CTimer(RequestFullRoomSchedule, null, SchedulePollInterval, SchedulePollInterval);
-
- PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
- }
- }
- }
- }
- }
- }
- }
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing ActionQueryResponse: {0}", e);
- }
- }
- else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQueryResponse)
- {
- try
- {
- XmlDocument message = new XmlDocument();
-
- message.LoadXml(args.Sig.StringValue);
-
- var localDateTimeResponse = message["LocalTimeResponse"];
-
- if (localDateTimeResponse != null)
- {
- var localDateTime = localDateTimeResponse["LocalDateTime"];
-
- if (localDateTime != null)
- {
- var tempLocalDateTime = localDateTime.InnerText;
-
- DateTime currentTime = DateTime.Parse(tempLocalDateTime);
-
- Debug.Console(1, this, "DateTime from Fusion Server: {0}", currentTime);
-
- // Parse time and date from response and insert values
- CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute, (ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day, (ushort)currentTime.Year);
-
- Debug.Console(1, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
- }
- }
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing LocalDateTimeQueryResponse: {0}", e);
- }
- }
- else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigResponse)
- {
- // Room info response with custom properties
-
- string roomConfigResponseArgs = args.Sig.StringValue.Replace("&", "and");
-
- Debug.Console(2, this, "Fusion Response: \n {0}", roomConfigResponseArgs);
-
- try
- {
- XmlDocument roomConfigResponse = new XmlDocument();
-
- roomConfigResponse.LoadXml(roomConfigResponseArgs);
-
- var requestRoomConfiguration = roomConfigResponse["RoomConfigurationResponse"];
-
- if (requestRoomConfiguration != null)
- {
- RoomInformation roomInformation = new RoomInformation();
-
- foreach (XmlElement e in roomConfigResponse.FirstChild.ChildNodes)
- {
- if (e.Name == "RoomInformation")
- {
- XmlReader roomInfo = new XmlReader(e.OuterXml);
-
- roomInformation = CrestronXMLSerialization.DeSerializeObject(roomInfo);
- }
- else if (e.Name == "CustomFields")
- {
- foreach (XmlElement el in e)
- {
- FusionCustomProperty customProperty = new FusionCustomProperty();
-
- if (el.Name == "CustomField")
- {
- customProperty.ID = el.Attributes["ID"].Value;
- }
-
- foreach (XmlElement elm in el)
- {
- if (elm.Name == "CustomFieldName")
- {
- customProperty.CustomFieldName = elm.InnerText;
- }
- if (elm.Name == "CustomFieldType")
- {
- customProperty.CustomFieldType = elm.InnerText;
- }
- if (elm.Name == "CustomFieldValue")
- {
- customProperty.CustomFieldValue = elm.InnerText;
- }
- }
-
- roomInformation.FusionCustomProperties.Add(customProperty);
- }
- }
- }
-
- var handler = RoomInfoChange;
- if (handler != null)
- handler(this, new EventArgs());
-
- CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation);
- }
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing Custom Properties response: {0}", e);
- }
- //PrintRoomInfo();
- //getRoomInfoBusy = false;
- //_DynFusion.API.EISC.BooleanInput[Constants.GetRoomInfo].BoolValue = getRoomInfoBusy;
- }
-
- }
-
- ///
- /// Event handler method for Device Extender sig changes
- ///
- ///
- ///
- protected void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
- {
- Debug.Console(2, this, "Scehdule Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
-
-
- if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse)
- {
- try
- {
- ScheduleResponse scheduleResponse = new ScheduleResponse();
-
- XmlDocument message = new XmlDocument();
-
- message.LoadXml(args.Sig.StringValue);
-
- var response = message["ScheduleResponse"];
-
- if (response != null)
- {
- // Check for push notification
- if (response["RequestID"].InnerText == "RVRequest")
- {
- var action = response["Action"];
-
- if (action.OuterXml.IndexOf("RequestSchedule") > -1)
- {
- PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
- }
- }
- else // Not a push notification
- {
- CurrentSchedule = new RoomSchedule(); // Clear Current Schedule
- CurrentMeeting = null; // Clear Current Meeting
- NextMeeting = null; // Clear Next Meeting
-
- bool isNextMeeting = false;
-
- foreach (XmlElement element in message.FirstChild.ChildNodes)
- {
- if (element.Name == "RequestID")
- {
- scheduleResponse.RequestID = element.InnerText;
- }
- else if (element.Name == "RoomID")
- {
- scheduleResponse.RoomID = element.InnerText;
- }
- else if (element.Name == "RoomName")
- {
- scheduleResponse.RoomName = element.InnerText;
- }
- else if (element.Name == "Event")
- {
- Debug.Console(2, this, "Event Found:\n{0}", element.OuterXml);
-
- XmlReader reader = new XmlReader(element.OuterXml);
-
- Event tempEvent = new Event();
-
- tempEvent = CrestronXMLSerialization.DeSerializeObject(reader);
-
- scheduleResponse.Events.Add(tempEvent);
-
- // Check is this is the current event
- if (tempEvent.dtStart <= DateTime.Now && tempEvent.dtEnd >= DateTime.Now)
- {
- CurrentMeeting = tempEvent; // Set Current Meeting
- isNextMeeting = true; // Flag that next element is next meeting
- }
-
- if (isNextMeeting)
- {
- NextMeeting = tempEvent; // Set Next Meeting
- isNextMeeting = false;
- }
-
- CurrentSchedule.Meetings.Add(tempEvent);
- }
-
- }
-
- PrintTodaysSchedule();
-
- if (!IsRegisteredForSchedulePushNotifications)
- PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
-
- // Fire Schedule Change Event
- var handler = ScheduleChange;
-
- if (handler != null)
- {
- handler(this, new ScheduleChangeEventArgs() { Schedule = CurrentSchedule });
- }
-
- }
- }
-
-
-
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e);
- }
- }
- else if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateResponse)
- {
- Debug.Console(2, this, "Create Meeting Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
- }
-
- }
-
- ///
- /// Prints today's schedule to console for debugging
- ///
- void PrintTodaysSchedule()
- {
- if (Debug.Level > 1)
- {
- if (CurrentSchedule.Meetings.Count > 0)
- {
- Debug.Console(1, this, "Today's Schedule for '{0}'\n", Room.Name);
-
- foreach (Event e in CurrentSchedule.Meetings)
- {
- Debug.Console(1, this, "Subject: {0}", e.Subject);
- Debug.Console(1, this, "Organizer: {0}", e.Organizer);
- Debug.Console(1, this, "MeetingID: {0}", e.MeetingID);
- Debug.Console(1, this, "Start Time: {0}", e.dtStart);
- Debug.Console(1, this, "End Time: {0}", e.dtEnd);
- Debug.Console(1, this, "Duration: {0}\n", e.DurationInMinutes);
- }
- }
- }
- }
-
- protected virtual void SetUpSources()
- {
- // Sources
- var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsRoomBase).SourceListKey);
- if (dict != null)
- {
- // NEW PROCESS:
- // Make these lists and insert the fusion attributes by iterating these
- var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
- uint i = 1;
- foreach (var kvp in setTopBoxes)
- {
- TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 5) // We only have five spots
- break;
- }
-
- var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
- i = 1;
- foreach (var kvp in discPlayers)
- {
- TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 5) // We only have five spots
- break;
- }
-
- var laptops = dict.Where(d => d.Value.SourceDevice is Devices.Laptop);
- i = 1;
- foreach (var kvp in laptops)
- {
- TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 10) // We only have ten spots???
- break;
- }
-
- foreach (var kvp in dict)
- {
- var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
-
- if (usageDevice != null)
- {
- usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
- usageDevice.UsageTracker.UsageIsTracked = true;
- usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
- }
- }
-
- }
- else
- {
- Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
- (Room as EssentialsRoomBase).SourceListKey, Room.Key);
- }
- }
-
- ///
- /// Collects usage data from source and sends to Fusion
- ///
- ///
- ///
- protected void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
- {
- var deviceTracker = sender as UsageTracking;
-
- var configDevice = ConfigReader.ConfigObject.Devices.Where(d => d.Key.Equals(deviceTracker.Parent));
-
- string group = ConfigReader.GetGroupForDeviceKey(deviceTracker.Parent.Key);
-
- string currentMeetingId = "-";
-
- if (CurrentMeeting != null)
- currentMeetingId = CurrentMeeting.MeetingID;
-
- //String Format: "USAGE||[Date YYYY-MM-DD]||[Time HH-mm-ss]||TIME||[Asset_Type]||[Asset_Name]||[Minutes_used]||[Asset_ID]||[Meeting_ID]"
- // [Asset_ID] property does not appear to be used in Crestron SSI examples. They are sending "-" instead so that's what is replicated here
- string deviceUsage = string.Format("USAGE||{0}||{1}||TIME||{2}||{3}||-||{4}||-||{5}||{6}||\r\n", e.UsageEndTime.ToString("yyyy-MM-dd"), e.UsageEndTime.ToString("HH:mm:ss"),
- group, deviceTracker.Parent.Name, e.MinutesUsed, "-", currentMeetingId);
-
- Debug.Console(1, this, "Device usage for: {0} ended at {1}. In use for {2} minutes", deviceTracker.Parent.Name, e.UsageEndTime, e.MinutesUsed);
-
- FusionRoom.DeviceUsage.InputSig.StringValue = deviceUsage;
-
- Debug.Console(1, this, "Device usage string: {0}", deviceUsage);
- }
-
-
- protected void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc)
- {
- Debug.Console(2, this, "Creating attribute '{0}' with join {1} for source {2}",
- attrName, attrNum, pSrc.Key);
- try
- {
- var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig);
- // Need feedback when this source is selected
- // Event handler, added below, will compare source changes with this sig dict
- SourceToFeedbackSigs.Add(pSrc, sigD.InputSig);
-
- // And respond to selection in Fusion
- sigD.OutputSig.SetSigFalseAction(() => (Room as IRunRouteAction).RunRouteAction(routeKey, Room.SourceListKey));
- }
- catch (Exception)
- {
- Debug.Console(2, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING", attrNum, attrName, pSrc.Key);
- }
- }
-
- ///
- ///
- ///
- void SetUpCommunitcationMonitors()
- {
- uint displayNum = 0;
- uint touchpanelNum = 0;
- uint xpanelNum = 0;
-
- // Attach to all room's devices with monitors.
- //foreach (var dev in DeviceManager.Devices)
- foreach (var dev in DeviceManager.GetDevices())
- {
- if (!(dev is ICommunicationMonitor))
- continue;
-
- string attrName = null;
- uint attrNum = 1;
-
- //var keyNum = ExtractNumberFromKey(dev.Key);
- //if (keyNum == -1)
- //{
- // Debug.Console(1, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes",
- // dev.Key);
- // continue;
- //}
- //uint attrNum = Convert.ToUInt32(keyNum);
-
- // Check for UI devices
- var uiDev = dev as IHasBasicTriListWithSmartObject;
- if (uiDev != null)
- {
- if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
- {
- attrNum = attrNum + touchpanelNum;
-
- if (attrNum > 10)
- continue;
- attrName = "Online - XPanel " + attrNum;
- attrNum += 160;
-
- touchpanelNum++;
- }
- else
- {
- attrNum = attrNum + xpanelNum;
-
- if (attrNum > 10)
- continue;
- attrName = "Online - Touch Panel " + attrNum;
- attrNum += 150;
-
- xpanelNum++;
- }
- }
-
- //else
- if (dev is DisplayBase)
- {
- attrNum = attrNum + displayNum;
- if (attrNum > 10)
- continue;
- attrName = "Online - Display " + attrNum;
- attrNum += 170;
-
- displayNum++;
- }
- //else if (dev is DvdDeviceBase)
- //{
- // if (attrNum > 5)
- // continue;
- // attrName = "Device Ok - DVD " + attrNum;
- // attrNum += 260;
- //}
- // add set top box
-
- // add Cresnet roll-up
-
- // add DM-devices roll-up
-
- if (attrName != null)
- {
- // Link comm status to sig and update
- var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly);
- var smd = dev as ICommunicationMonitor;
- sigD.InputSig.BoolValue = smd.CommunicationMonitor.Status == MonitorStatus.IsOk;
- smd.CommunicationMonitor.StatusChange += (o, a) =>
- { sigD.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; };
- Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", dev.Key, attrName);
- }
- }
- }
-
- protected virtual void SetUpDisplay()
- {
- try
- {
- //Setup Display Usage Monitoring
-
- var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
-
- // Consider updating this in multiple display systems
-
- foreach (DisplayBase display in displays)
- {
- display.UsageTracker = new UsageTracking(display);
- display.UsageTracker.UsageIsTracked = true;
- display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
- }
-
- var defaultDisplay = (Room as IHasDefaultDisplay).DefaultDisplay as DisplayBase;
- if (defaultDisplay == null)
- {
- Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
- return;
- }
-
- var dispPowerOnAction = new Action(b => { if (!b) defaultDisplay.PowerOn(); });
- var dispPowerOffAction = new Action(b => { if (!b) defaultDisplay.PowerOff(); });
-
- // Display to fusion room sigs
- FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
- FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
- if (defaultDisplay is IDisplayUsage)
- (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
-
-
-
- MapDisplayToRoomJoins(1, 158, defaultDisplay);
-
-
- var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
-
- //Check for existing asset in GUIDs collection
-
- var tempAsset = new FusionAsset();
-
- if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
- {
- tempAsset = FusionStaticAssets[deviceConfig.Uid];
- }
- else
- {
- // Create a new asset
- tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
- FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
- }
-
- var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
- dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
- dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
- // NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
- // Use extension methods
- dispAsset.TrySetMakeModel(defaultDisplay);
- dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
- }
-
- }
-
- ///
- /// Maps room attributes to a display at a specified index
- ///
- ///
- /// a
- protected virtual void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
- {
- string displayName = string.Format("Display {0} - ", displayIndex);
-
-
- if (display == (Room as IHasDefaultDisplay).DefaultDisplay)
- {
- // Display volume
- var defaultDisplayVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
- defaultDisplayVolume.OutputSig.UserObject = new Action(b => (display as IBasicVolumeWithFeedback).SetVolume(b));
- (display as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(defaultDisplayVolume.InputSig);
-
- // Power on
- var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
- defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
-
- // Power Off
- var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
- defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
-
- // Current Source
- var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
- defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) (Room as IRunRouteAction).RunRouteAction("roomOff", Room.SourceListKey); }); ;
- }
- }
-
- void SetUpError()
- {
- // Roll up ALL device errors
- ErrorMessageRollUp = new StatusMonitorCollection(this);
- foreach (var dev in DeviceManager.GetDevices())
- {
- var md = dev as ICommunicationMonitor;
- if (md != null)
- {
- ErrorMessageRollUp.AddMonitor(md.CommunicationMonitor);
- Debug.Console(2, this, "Adding '{0}' to room's overall error monitor", md.CommunicationMonitor.Parent.Key);
- }
- }
- ErrorMessageRollUp.Start();
- FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
- ErrorMessageRollUp.StatusChange += (o, a) =>
- {
- FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
- };
-
- }
-
- ///
- /// Sets up a local occupancy sensor, such as one attached to a Fusion Scheduling panel. The occupancy status of the room will be read from Fusion
- ///
- void SetUpLocalOccupancy()
- {
- RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
-
- FusionRoom.FusionAssetStateChange += new FusionAssetStateEventHandler(FusionRoom_FusionAssetStateChange);
-
- // Build Occupancy Asset?
- // Link sigs?
-
- //Room.SetRoomOccupancy(this as IOccupancyStatusProvider, 0);
-
-
- }
-
- void FusionRoom_FusionAssetStateChange(FusionBase device, FusionAssetStateEventArgs args)
- {
- if (args.EventId == FusionAssetEventId.RoomOccupiedReceivedEventId || args.EventId == FusionAssetEventId.RoomUnoccupiedReceivedEventId)
- RoomIsOccupiedFeedback.FireUpdate();
-
- }
-
- ///
- /// Sets up remote occupancy that will relay the occupancy status determined by local system devices to Fusion
- ///
- void SetUpRemoteOccupancy()
- {
-
- // Need to have the room occupancy object first and somehow determine the slot number of the Occupancy asset but will not be able to use the UID from config likely.
- // Consider defining an object just for Room Occupancy (either eAssetType.Occupancy Sensor (local) or eAssetType.RemoteOccupancySensor (from Fusion sched. panel)) and reserving slot 4 for that asset (statics would start at 5)
-
- //if (Room.OccupancyObj != null)
- //{
-
- var tempOccAsset = GUIDs.OccupancyAsset;
-
- if(tempOccAsset == null)
- {
- FusionOccSensor = new FusionOccupancySensorAsset(eAssetType.OccupancySensor);
- tempOccAsset = FusionOccSensor;
- }
-
- var occSensorAsset = FusionRoom.CreateOccupancySensorAsset(tempOccAsset.SlotNumber, tempOccAsset.Name, "Occupancy Sensor", tempOccAsset.InstanceId);
-
- occSensorAsset.RoomOccupied.AddSigToRVIFile = true;
-
- var occSensorShutdownMinutes = FusionRoom.CreateOffsetUshortSig(70, "Occ Shutdown - Minutes", eSigIoMask.InputOutputSig);
-
- // Tie to method on occupancy object
+ });
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Building Fusion System Controller: {0}", e);
+ }
+ }
+
+ ///
+ /// Used for extension classes to execute whatever steps are necessary before generating the RVI and GUID files
+ ///
+ protected virtual void ExecuteCustomSteps()
+ {
+
+ }
+
+ ///
+ /// Generates the guid file in NVRAM. If the file already exists it will be overwritten.
+ ///
+ /// path for the file
+ void GenerateGuidFile(string filePath)
+ {
+ if (string.IsNullOrEmpty(filePath))
+ {
+ Debug.Console(0, this, "Error writing guid file. No path specified.");
+ return;
+ }
+
+ CCriticalSection _fileLock = new CCriticalSection();
+
+ try
+ {
+ if (_fileLock == null || _fileLock.Disposed)
+ return;
+
+ _fileLock.Enter();
+
+ Debug.Console(1, this, "Writing GUIDs to file");
+
+ if (FusionOccSensor == null)
+ GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets);
+ else
+ GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, FusionStaticAssets, FusionOccSensor);
+
+ var JSON = JsonConvert.SerializeObject(GUIDs, Newtonsoft.Json.Formatting.Indented);
+
+ using (StreamWriter sw = new StreamWriter(filePath))
+ {
+ sw.Write(JSON);
+ sw.Flush();
+ }
+
+ Debug.Console(1, this, "Guids successfully written to file '{0}'", filePath);
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, this, "Error writing guid file: {0}", e);
+ }
+ finally
+ {
+ if (_fileLock != null && !_fileLock.Disposed)
+ _fileLock.Leave();
+ }
+ }
+
+ ///
+ /// Reads the guid file from NVRAM
+ ///
+ /// path for te file
+ void ReadGuidFile(string filePath)
+ {
+ if(string.IsNullOrEmpty(filePath))
+ {
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Error reading guid file. No path specified.");
+ return;
+ }
+
+ CCriticalSection _fileLock = new CCriticalSection();
+
+ try
+ {
+ if(_fileLock == null || _fileLock.Disposed)
+ return;
+
+ _fileLock.Enter();
+
+ if(File.Exists(filePath))
+ {
+ var JSON = File.ReadToEnd(filePath, Encoding.ASCII);
+
+ GUIDs = JsonConvert.DeserializeObject(JSON);
+
+ IpId = GUIDs.IpId;
+
+ FusionStaticAssets = GUIDs.StaticAssets;
+
+ }
+
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Fusion Guids successfully read from file: {0}", filePath);
+
+ Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1:x}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid);
+
+ foreach (var item in FusionStaticAssets)
+ {
+ Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, item.Value.SlotNumber, item.Value.InstanceId);
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Error reading guid file: {0}", e);
+ }
+ finally
+ {
+ if(_fileLock != null && !_fileLock.Disposed)
+ _fileLock.Leave();
+ }
+
+ }
+
+ protected virtual void CreateSymbolAndBasicSigs(uint ipId)
+ {
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
+
+ FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
+
+ FusionRoom.Register();
+
+ FusionRoom.FusionStateChange += new FusionStateEventHandler(FusionRoom_FusionStateChange);
+
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(FusionRoomSchedule_DeviceExtenderSigChange);
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange);
+ FusionRoom.OnlineStatusChange += new OnlineStatusChangeEventHandler(FusionRoom_OnlineStatusChange);
+
+ CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
+
+ // Room to fusion room
+ Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
+
+ // Moved to
+ CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
+ // Don't think we need to get current status of this as nothing should be alive yet.
+ (Room as IHasCurrentSourceInfoChange).CurrentSourceChange += new SourceInfoChangeHandler(Room_CurrentSourceInfoChange);
+
+
+ FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsRoomBase).PowerOnToDefaultOrLastSource);
+ FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as IRunRouteAction).RunRouteAction("roomOff", Room.SourceListKey));
+ // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
+ FusionRoom.ErrorMessage.InputSig.StringValue =
+ "3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;";
+
+ SetUpEthernetValues();
+
+ GetProcessorEthernetValues();
+
+ GetSystemInfo();
+
+ GetProcessorInfo();
+
+ CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
+ }
+
+ protected void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
+ {
+ if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp)
+ {
+ GetProcessorEthernetValues();
+ }
+ }
+
+ protected void GetSystemInfo()
+ {
+ //SystemName.InputSig.StringValue = Room.Name;
+ //Model.InputSig.StringValue = InitialParametersClass.ControllerPromptName;
+ //SerialNumber.InputSig.StringValue = InitialParametersClass.
+
+ string response = string.Empty;
+
+ var systemReboot = FusionRoom.CreateOffsetBoolSig(74, "Processor - Reboot", eSigIoMask.OutputSigOnly);
+ systemReboot.OutputSig.SetSigFalseAction(() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
+ }
+
+ protected void SetUpEthernetValues()
+ {
+ Ip1 = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - IP 1", eSigIoMask.InputSigOnly);
+ Ip2 = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - IP 2", eSigIoMask.InputSigOnly);
+ Gateway = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Gateway", eSigIoMask.InputSigOnly);
+ Hostname = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Hostname", eSigIoMask.InputSigOnly);
+ Domain = FusionRoom.CreateOffsetStringSig(54, "Info - Processor - Domain", eSigIoMask.InputSigOnly);
+ Dns1 = FusionRoom.CreateOffsetStringSig(55, "Info - Processor - DNS 1", eSigIoMask.InputSigOnly);
+ Dns2 = FusionRoom.CreateOffsetStringSig(56, "Info - Processor - DNS 2", eSigIoMask.InputSigOnly);
+ Mac1 = FusionRoom.CreateOffsetStringSig(57, "Info - Processor - MAC 1", eSigIoMask.InputSigOnly);
+ Mac2 = FusionRoom.CreateOffsetStringSig(58, "Info - Processor - MAC 2", eSigIoMask.InputSigOnly);
+ NetMask1 = FusionRoom.CreateOffsetStringSig(59, "Info - Processor - Net Mask 1", eSigIoMask.InputSigOnly);
+ NetMask2 = FusionRoom.CreateOffsetStringSig(60, "Info - Processor - Net Mask 2", eSigIoMask.InputSigOnly);
+ }
+
+ protected void GetProcessorEthernetValues()
+ {
+ Ip1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
+ Gateway.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0);
+ Hostname.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
+ Domain.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0);
+
+ var dnsServers = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, 0).Split(',');
+ Dns1.InputSig.StringValue = dnsServers[0];
+ if (dnsServers.Length > 1)
+ Dns2.InputSig.StringValue = dnsServers[1];
+
+ Mac1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
+ NetMask1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 0);
+
+ // Interface 1
+
+ if (InitialParametersClass.NumberOfEthernetInterfaces > 1) // Only get these values if the processor has more than 1 NIC
+ {
+ Ip2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 1);
+ Mac2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 1);
+ NetMask2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 1);
+ }
+ }
+
+ protected void GetProcessorInfo()
+ {
+
+ Firmware = FusionRoom.CreateOffsetStringSig(61, "Info - Processor - Firmware", eSigIoMask.InputSigOnly);
+
+ if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
+ {
+ for (int i = 0; i < Global.ControlSystem.NumProgramsSupported; i++)
+ {
+ var join = 62 + i;
+ var progNum = i + 1;
+ Program[i] = FusionRoom.CreateOffsetStringSig((uint)join, string.Format("Info - Processor - Program {0}", progNum), eSigIoMask.InputSigOnly);
+ }
+ }
+
+ Firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
+
+ }
+
+ protected void GetCustomProperties()
+ {
+ if (FusionRoom.IsOnline)
+ {
+ string fusionRoomCustomPropertiesRequest = @"RoomConfigurationRequest";
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigQuery.StringValue = fusionRoomCustomPropertiesRequest;
+ }
+ }
+
+ void GetTouchpanelInfo()
+ {
+ // TODO: Get IP and Project Name from TP
+ }
+
+ protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ if (args.DeviceOnLine)
+ {
+ CrestronEnvironment.Sleep(200);
+
+ // Send Push Notification Action request:
+
+ string requestID = "InitialPushRequest";
+
+
+ string actionRequest =
+ string.Format("\n{0}\n", requestID) +
+ "RegisterPushModel\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n" +
+ "\n";
+
+ Debug.Console(2, this, "Sending Fusion ActionRequest: \n{0}", actionRequest);
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
+
+ GetCustomProperties();
+
+ // Request current Fusion Server Time
+ RequestLocalDateTime(null);
+
+ // Setup timer to request time daily
+ if (DailyTimeRequestTimer != null && !DailyTimeRequestTimer.Disposed)
+ {
+ DailyTimeRequestTimer.Stop();
+ DailyTimeRequestTimer.Dispose();
+ }
+
+ DailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000);
+
+ DailyTimeRequestTimer.Reset(86400000, 86400000);
+ }
+
+ }
+
+ ///
+ /// Requests the local date and time from the Fusion Server
+ ///
+ ///
+ public void RequestLocalDateTime(object callbackObject)
+ {
+ string timeRequestID = "TimeRequest";
+
+ string timeRequest = string.Format("{0}", timeRequestID);
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest;
+ }
+
+ ///
+ /// Generates a room schedule request for this room for the next 24 hours.
+ ///
+ /// string identifying this request. Used with a corresponding ScheduleResponse value
+ public void RequestFullRoomSchedule(object callbackObject)
+ {
+ DateTime now = DateTime.Today;
+
+ string currentTime = now.ToString("s");
+
+ string requestTest =
+ string.Format("FullSchedleRequest{0}{1}24", RoomGuid, currentTime);
+
+ Debug.Console(2, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest);
+
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest;
+
+ if (IsRegisteredForSchedulePushNotifications)
+ PushNotificationTimer.Stop();
+ }
+
+ ///
+ /// Wrapper method to allow console commands to modify the current meeting end time
+ ///
+ /// meetingID extendTime
+ public void ModifyMeetingEndTimeConsoleHelper(string command)
+ {
+ string requestID;
+ string meetingID = null;
+ int extendMinutes = -1;
+
+ requestID = "ModifyMeetingTest12345";
+
+ try
+ {
+ var tokens = command.Split(' ');
+
+ meetingID = tokens[0];
+ extendMinutes = Int32.Parse(tokens[1]);
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing console command: {0}", e);
+ }
+
+ ModifyMeetingEndTime(requestID, extendMinutes);
+
+ }
+
+ ///
+ /// Ends or Extends the current meeting by the specified number of minutes.
+ ///
+ /// Number of minutes to extend the meeting. A value of 0 will end the meeting.
+ public void ModifyMeetingEndTime(string requestID, int extendMinutes)
+ {
+ if(CurrentMeeting == null)
+ {
+ Debug.Console(1, this, "No meeting in progress. Unable to modify end time.");
+ return;
+ }
+
+ if (extendMinutes > -1)
+ {
+ if(extendMinutes > 0)
+ {
+ var extendTime = CurrentMeeting.dtEnd - DateTime.Now;
+ double extendMinutesRaw = extendTime.TotalMinutes;
+
+ extendMinutes = extendMinutes + (int)Math.Round(extendMinutesRaw);
+ }
+
+
+ string requestTest = string.Format(
+ "{0}{1}MeetingChange"
+ , requestID, RoomGuid, CurrentMeeting.MeetingID, extendMinutes);
+
+ Debug.Console(1, this, "Sending MeetingChange Request: \n{0}", requestTest);
+
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest;
+ }
+ else
+ {
+ Debug.Console(1, this, "Invalid time specified");
+ }
+
+
+ }
+
+ ///
+ /// Creates and Ad Hoc meeting with a duration of 1 hour, or until the next meeting if in less than 1 hour.
+ ///
+ public void CreateAsHocMeeting(string command)
+ {
+ string requestID = "CreateAdHocMeeting";
+
+ DateTime now = DateTime.Now.AddMinutes(1);
+
+ now.AddSeconds(-now.Second);
+
+ // Assume 1 hour meeting if possible
+ DateTime dtEnd = now.AddHours(1);
+
+ // Check if room is available for 1 hour before next meeting
+ if (NextMeeting != null)
+ {
+ var roomAvailable = NextMeeting.dtEnd.Subtract(dtEnd);
+
+ if (roomAvailable.TotalMinutes < 60)
+ {
+ /// Room not available for full hour, book until next meeting starts
+ dtEnd = NextMeeting.dtEnd;
+ }
+ }
+
+ string createMeetingRequest =
+ "" +
+ string.Format("{0}", requestID) +
+ string.Format("{0}", RoomGuid) +
+ "" +
+ string.Format("{0}", now.ToString("s")) +
+ string.Format("{0}", dtEnd.ToString("s")) +
+ "AdHoc Meeting" +
+ "Room User" +
+ "Example Message" +
+ "" +
+ "";
+
+ Debug.Console(2, this, "Sending CreateMeeting Request: \n{0}", createMeetingRequest);
+
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = createMeetingRequest;
+
+ //Debug.Console(1, this, "Sending CreateMeeting Request: \n{0}", command);
+
+ //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = command;
+
+ }
+
+ ///
+ /// Event handler method for Device Extender sig changes
+ ///
+ ///
+ ///
+ protected void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
+ {
+ Debug.Console(2, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
+
+
+ if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse)
+ {
+ try
+ {
+ XmlDocument message = new XmlDocument();
+
+ message.LoadXml(args.Sig.StringValue);
+
+ var actionResponse = message["ActionResponse"];
+
+ if (actionResponse != null)
+ {
+ var requestID = actionResponse["RequestID"];
+
+ if (requestID.InnerText == "InitialPushRequest")
+ {
+ if (actionResponse["ActionID"].InnerText == "RegisterPushModel")
+ {
+ var parameters = actionResponse["Parameters"];
+
+ foreach (XmlElement parameter in parameters)
+ {
+ if (parameter.HasAttributes)
+ {
+ var attributes = parameter.Attributes;
+
+ if (attributes["ID"].Value == "Registered")
+ {
+ var isRegistered = Int32.Parse(attributes["Value"].Value);
+
+ if (isRegistered == 1)
+ {
+ IsRegisteredForSchedulePushNotifications = true;
+
+ if (PollTimer != null && !PollTimer.Disposed)
+ {
+ PollTimer.Stop();
+ PollTimer.Dispose();
+ }
+
+ PushNotificationTimer = new CTimer(RequestFullRoomSchedule, null, PushNotificationTimeout, PushNotificationTimeout);
+
+ PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
+ }
+ else if (isRegistered == 0)
+ {
+ IsRegisteredForSchedulePushNotifications = false;
+
+ if (PushNotificationTimer != null && !PushNotificationTimer.Disposed)
+ {
+ PushNotificationTimer.Stop();
+ PushNotificationTimer.Dispose();
+ }
+
+ PollTimer = new CTimer(RequestFullRoomSchedule, null, SchedulePollInterval, SchedulePollInterval);
+
+ PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing ActionQueryResponse: {0}", e);
+ }
+ }
+ else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQueryResponse)
+ {
+ try
+ {
+ XmlDocument message = new XmlDocument();
+
+ message.LoadXml(args.Sig.StringValue);
+
+ var localDateTimeResponse = message["LocalTimeResponse"];
+
+ if (localDateTimeResponse != null)
+ {
+ var localDateTime = localDateTimeResponse["LocalDateTime"];
+
+ if (localDateTime != null)
+ {
+ var tempLocalDateTime = localDateTime.InnerText;
+
+ DateTime currentTime = DateTime.Parse(tempLocalDateTime);
+
+ Debug.Console(1, this, "DateTime from Fusion Server: {0}", currentTime);
+
+ // Parse time and date from response and insert values
+ CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute, (ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day, (ushort)currentTime.Year);
+
+ Debug.Console(1, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing LocalDateTimeQueryResponse: {0}", e);
+ }
+ }
+ else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigResponse)
+ {
+ // Room info response with custom properties
+
+ string roomConfigResponseArgs = args.Sig.StringValue.Replace("&", "and");
+
+ Debug.Console(2, this, "Fusion Response: \n {0}", roomConfigResponseArgs);
+
+ try
+ {
+ XmlDocument roomConfigResponse = new XmlDocument();
+
+ roomConfigResponse.LoadXml(roomConfigResponseArgs);
+
+ var requestRoomConfiguration = roomConfigResponse["RoomConfigurationResponse"];
+
+ if (requestRoomConfiguration != null)
+ {
+ RoomInformation roomInformation = new RoomInformation();
+
+ foreach (XmlElement e in roomConfigResponse.FirstChild.ChildNodes)
+ {
+ if (e.Name == "RoomInformation")
+ {
+ XmlReader roomInfo = new XmlReader(e.OuterXml);
+
+ roomInformation = CrestronXMLSerialization.DeSerializeObject(roomInfo);
+ }
+ else if (e.Name == "CustomFields")
+ {
+ foreach (XmlElement el in e)
+ {
+ FusionCustomProperty customProperty = new FusionCustomProperty();
+
+ if (el.Name == "CustomField")
+ {
+ customProperty.ID = el.Attributes["ID"].Value;
+ }
+
+ foreach (XmlElement elm in el)
+ {
+ if (elm.Name == "CustomFieldName")
+ {
+ customProperty.CustomFieldName = elm.InnerText;
+ }
+ if (elm.Name == "CustomFieldType")
+ {
+ customProperty.CustomFieldType = elm.InnerText;
+ }
+ if (elm.Name == "CustomFieldValue")
+ {
+ customProperty.CustomFieldValue = elm.InnerText;
+ }
+ }
+
+ roomInformation.FusionCustomProperties.Add(customProperty);
+ }
+ }
+ }
+
+ var handler = RoomInfoChange;
+ if (handler != null)
+ handler(this, new EventArgs());
+
+ CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation);
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing Custom Properties response: {0}", e);
+ }
+ //PrintRoomInfo();
+ //getRoomInfoBusy = false;
+ //_DynFusion.API.EISC.BooleanInput[Constants.GetRoomInfo].BoolValue = getRoomInfoBusy;
+ }
+
+ }
+
+ ///
+ /// Event handler method for Device Extender sig changes
+ ///
+ ///
+ ///
+ protected void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
+ {
+ Debug.Console(2, this, "Scehdule Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
+
+
+ if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse)
+ {
+ try
+ {
+ ScheduleResponse scheduleResponse = new ScheduleResponse();
+
+ XmlDocument message = new XmlDocument();
+
+ message.LoadXml(args.Sig.StringValue);
+
+ var response = message["ScheduleResponse"];
+
+ if (response != null)
+ {
+ // Check for push notification
+ if (response["RequestID"].InnerText == "RVRequest")
+ {
+ var action = response["Action"];
+
+ if (action.OuterXml.IndexOf("RequestSchedule") > -1)
+ {
+ PushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout);
+ }
+ }
+ else // Not a push notification
+ {
+ CurrentSchedule = new RoomSchedule(); // Clear Current Schedule
+ CurrentMeeting = null; // Clear Current Meeting
+ NextMeeting = null; // Clear Next Meeting
+
+ bool isNextMeeting = false;
+
+ foreach (XmlElement element in message.FirstChild.ChildNodes)
+ {
+ if (element.Name == "RequestID")
+ {
+ scheduleResponse.RequestID = element.InnerText;
+ }
+ else if (element.Name == "RoomID")
+ {
+ scheduleResponse.RoomID = element.InnerText;
+ }
+ else if (element.Name == "RoomName")
+ {
+ scheduleResponse.RoomName = element.InnerText;
+ }
+ else if (element.Name == "Event")
+ {
+ Debug.Console(2, this, "Event Found:\n{0}", element.OuterXml);
+
+ XmlReader reader = new XmlReader(element.OuterXml);
+
+ Event tempEvent = new Event();
+
+ tempEvent = CrestronXMLSerialization.DeSerializeObject(reader);
+
+ scheduleResponse.Events.Add(tempEvent);
+
+ // Check is this is the current event
+ if (tempEvent.dtStart <= DateTime.Now && tempEvent.dtEnd >= DateTime.Now)
+ {
+ CurrentMeeting = tempEvent; // Set Current Meeting
+ isNextMeeting = true; // Flag that next element is next meeting
+ }
+
+ if (isNextMeeting)
+ {
+ NextMeeting = tempEvent; // Set Next Meeting
+ isNextMeeting = false;
+ }
+
+ CurrentSchedule.Meetings.Add(tempEvent);
+ }
+
+ }
+
+ PrintTodaysSchedule();
+
+ if (!IsRegisteredForSchedulePushNotifications)
+ PollTimer.Reset(SchedulePollInterval, SchedulePollInterval);
+
+ // Fire Schedule Change Event
+ var handler = ScheduleChange;
+
+ if (handler != null)
+ {
+ handler(this, new ScheduleChangeEventArgs() { Schedule = CurrentSchedule });
+ }
+
+ }
+ }
+
+
+
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e);
+ }
+ }
+ else if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateResponse)
+ {
+ Debug.Console(2, this, "Create Meeting Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue);
+ }
+
+ }
+
+ ///
+ /// Prints today's schedule to console for debugging
+ ///
+ void PrintTodaysSchedule()
+ {
+ if (Debug.Level > 1)
+ {
+ if (CurrentSchedule.Meetings.Count > 0)
+ {
+ Debug.Console(1, this, "Today's Schedule for '{0}'\n", Room.Name);
+
+ foreach (Event e in CurrentSchedule.Meetings)
+ {
+ Debug.Console(1, this, "Subject: {0}", e.Subject);
+ Debug.Console(1, this, "Organizer: {0}", e.Organizer);
+ Debug.Console(1, this, "MeetingID: {0}", e.MeetingID);
+ Debug.Console(1, this, "Start Time: {0}", e.dtStart);
+ Debug.Console(1, this, "End Time: {0}", e.dtEnd);
+ Debug.Console(1, this, "Duration: {0}\n", e.DurationInMinutes);
+ }
+ }
+ }
+ }
+
+ protected virtual void SetUpSources()
+ {
+ // Sources
+ var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsRoomBase).SourceListKey);
+ if (dict != null)
+ {
+ // NEW PROCESS:
+ // Make these lists and insert the fusion attributes by iterating these
+ var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
+ uint i = 1;
+ foreach (var kvp in setTopBoxes)
+ {
+ TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 5) // We only have five spots
+ break;
+ }
+
+ var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
+ i = 1;
+ foreach (var kvp in discPlayers)
+ {
+ TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 5) // We only have five spots
+ break;
+ }
+
+ var laptops = dict.Where(d => d.Value.SourceDevice is Devices.Laptop);
+ i = 1;
+ foreach (var kvp in laptops)
+ {
+ TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 10) // We only have ten spots???
+ break;
+ }
+
+ foreach (var kvp in dict)
+ {
+ var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
+
+ if (usageDevice != null)
+ {
+ usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
+ usageDevice.UsageTracker.UsageIsTracked = true;
+ usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
+ }
+ }
+
+ }
+ else
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
+ (Room as EssentialsRoomBase).SourceListKey, Room.Key);
+ }
+ }
+
+ ///
+ /// Collects usage data from source and sends to Fusion
+ ///
+ ///
+ ///
+ protected void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
+ {
+ var deviceTracker = sender as UsageTracking;
+
+ var configDevice = ConfigReader.ConfigObject.Devices.Where(d => d.Key.Equals(deviceTracker.Parent));
+
+ string group = ConfigReader.GetGroupForDeviceKey(deviceTracker.Parent.Key);
+
+ string currentMeetingId = "-";
+
+ if (CurrentMeeting != null)
+ currentMeetingId = CurrentMeeting.MeetingID;
+
+ //String Format: "USAGE||[Date YYYY-MM-DD]||[Time HH-mm-ss]||TIME||[Asset_Type]||[Asset_Name]||[Minutes_used]||[Asset_ID]||[Meeting_ID]"
+ // [Asset_ID] property does not appear to be used in Crestron SSI examples. They are sending "-" instead so that's what is replicated here
+ string deviceUsage = string.Format("USAGE||{0}||{1}||TIME||{2}||{3}||-||{4}||-||{5}||{6}||\r\n", e.UsageEndTime.ToString("yyyy-MM-dd"), e.UsageEndTime.ToString("HH:mm:ss"),
+ group, deviceTracker.Parent.Name, e.MinutesUsed, "-", currentMeetingId);
+
+ Debug.Console(1, this, "Device usage for: {0} ended at {1}. In use for {2} minutes", deviceTracker.Parent.Name, e.UsageEndTime, e.MinutesUsed);
+
+ FusionRoom.DeviceUsage.InputSig.StringValue = deviceUsage;
+
+ Debug.Console(1, this, "Device usage string: {0}", deviceUsage);
+ }
+
+
+ protected void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc)
+ {
+ Debug.Console(2, this, "Creating attribute '{0}' with join {1} for source {2}",
+ attrName, attrNum, pSrc.Key);
+ try
+ {
+ var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig);
+ // Need feedback when this source is selected
+ // Event handler, added below, will compare source changes with this sig dict
+ SourceToFeedbackSigs.Add(pSrc, sigD.InputSig);
+
+ // And respond to selection in Fusion
+ sigD.OutputSig.SetSigFalseAction(() => (Room as IRunRouteAction).RunRouteAction(routeKey, Room.SourceListKey));
+ }
+ catch (Exception)
+ {
+ Debug.Console(2, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING", attrNum, attrName, pSrc.Key);
+ }
+ }
+
+ ///
+ ///
+ ///
+ void SetUpCommunitcationMonitors()
+ {
+ uint displayNum = 0;
+ uint touchpanelNum = 0;
+ uint xpanelNum = 0;
+
+ // Attach to all room's devices with monitors.
+ //foreach (var dev in DeviceManager.Devices)
+ foreach (var dev in DeviceManager.GetDevices())
+ {
+ if (!(dev is ICommunicationMonitor))
+ continue;
+
+ string attrName = null;
+ uint attrNum = 1;
+
+ //var keyNum = ExtractNumberFromKey(dev.Key);
+ //if (keyNum == -1)
+ //{
+ // Debug.Console(1, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes",
+ // dev.Key);
+ // continue;
+ //}
+ //uint attrNum = Convert.ToUInt32(keyNum);
+
+ // Check for UI devices
+ var uiDev = dev as IHasBasicTriListWithSmartObject;
+ if (uiDev != null)
+ {
+ if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
+ {
+ attrNum = attrNum + touchpanelNum;
+
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - XPanel " + attrNum;
+ attrNum += 160;
+
+ touchpanelNum++;
+ }
+ else
+ {
+ attrNum = attrNum + xpanelNum;
+
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - Touch Panel " + attrNum;
+ attrNum += 150;
+
+ xpanelNum++;
+ }
+ }
+
+ //else
+ if (dev is DisplayBase)
+ {
+ attrNum = attrNum + displayNum;
+ if (attrNum > 10)
+ continue;
+ attrName = "Online - Display " + attrNum;
+ attrNum += 170;
+
+ displayNum++;
+ }
+ //else if (dev is DvdDeviceBase)
+ //{
+ // if (attrNum > 5)
+ // continue;
+ // attrName = "Device Ok - DVD " + attrNum;
+ // attrNum += 260;
+ //}
+ // add set top box
+
+ // add Cresnet roll-up
+
+ // add DM-devices roll-up
+
+ if (attrName != null)
+ {
+ // Link comm status to sig and update
+ var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly);
+ var smd = dev as ICommunicationMonitor;
+ sigD.InputSig.BoolValue = smd.CommunicationMonitor.Status == MonitorStatus.IsOk;
+ smd.CommunicationMonitor.StatusChange += (o, a) =>
+ { sigD.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; };
+ Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", dev.Key, attrName);
+ }
+ }
+ }
+
+ protected virtual void SetUpDisplay()
+ {
+ try
+ {
+ //Setup Display Usage Monitoring
+
+ var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
+
+ // Consider updating this in multiple display systems
+
+ foreach (DisplayBase display in displays)
+ {
+ display.UsageTracker = new UsageTracking(display);
+ display.UsageTracker.UsageIsTracked = true;
+ display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
+ }
+
+ var defaultDisplay = (Room as IHasDefaultDisplay).DefaultDisplay as DisplayBase;
+ if (defaultDisplay == null)
+ {
+ Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
+ return;
+ }
+
+ var dispPowerOnAction = new Action(b => { if (!b) defaultDisplay.PowerOn(); });
+ var dispPowerOffAction = new Action(b => { if (!b) defaultDisplay.PowerOff(); });
+
+ // Display to fusion room sigs
+ FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
+ FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
+
+ MapDisplayToRoomJoins(1, 158, defaultDisplay);
+
+
+ var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
+
+ //Check for existing asset in GUIDs collection
+
+ var tempAsset = new FusionAsset();
+
+ if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
+ {
+ tempAsset = FusionStaticAssets[deviceConfig.Uid];
+ }
+ else
+ {
+ // Create a new asset
+ tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
+ FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
+ }
+
+ var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
+ dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
+ dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
+
+ var defaultTwoWayDisplay = defaultDisplay as IHasPowerControlWithFeedback;
+ if (defaultTwoWayDisplay != null)
+ {
+ defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
+ if (defaultDisplay is IDisplayUsage)
+ (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
+
+ defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
+
+ }
+
+ // Use extension methods
+ dispAsset.TrySetMakeModel(defaultDisplay);
+ dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
+ }
+
+ }
+
+ ///
+ /// Maps room attributes to a display at a specified index
+ ///
+ ///
+ /// a
+ protected virtual void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
+ {
+ string displayName = string.Format("Display {0} - ", displayIndex);
+
+
+ if (display == (Room as IHasDefaultDisplay).DefaultDisplay)
+ {
+ // Display volume
+ var defaultDisplayVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
+ defaultDisplayVolume.OutputSig.UserObject = new Action(b => (display as IBasicVolumeWithFeedback).SetVolume(b));
+ (display as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(defaultDisplayVolume.InputSig);
+
+ // Power on
+ var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
+ defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
+
+ // Power Off
+ var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
+ defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
+
+
+ var defaultTwoWayDisplay = display as IHasPowerControlWithFeedback;
+ if (defaultTwoWayDisplay != null)
+ {
+ defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+ defaultTwoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(defaultDisplayPowerOff.InputSig);
+ }
+
+ // Current Source
+ var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
+ defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) (Room as IRunRouteAction).RunRouteAction("roomOff", Room.SourceListKey); }); ;
+ }
+ }
+
+ void SetUpError()
+ {
+ // Roll up ALL device errors
+ ErrorMessageRollUp = new StatusMonitorCollection(this);
+ foreach (var dev in DeviceManager.GetDevices())
+ {
+ var md = dev as ICommunicationMonitor;
+ if (md != null)
+ {
+ ErrorMessageRollUp.AddMonitor(md.CommunicationMonitor);
+ Debug.Console(2, this, "Adding '{0}' to room's overall error monitor", md.CommunicationMonitor.Parent.Key);
+ }
+ }
+ ErrorMessageRollUp.Start();
+ FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
+ ErrorMessageRollUp.StatusChange += (o, a) =>
+ {
+ FusionRoom.ErrorMessage.InputSig.StringValue = ErrorMessageRollUp.Message;
+ };
+
+ }
+
+ ///
+ /// Sets up a local occupancy sensor, such as one attached to a Fusion Scheduling panel. The occupancy status of the room will be read from Fusion
+ ///
+ void SetUpLocalOccupancy()
+ {
+ RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
+
+ FusionRoom.FusionAssetStateChange += new FusionAssetStateEventHandler(FusionRoom_FusionAssetStateChange);
+
+ // Build Occupancy Asset?
+ // Link sigs?
+
+ //Room.SetRoomOccupancy(this as IOccupancyStatusProvider, 0);
+
+
+ }
+
+ void FusionRoom_FusionAssetStateChange(FusionBase device, FusionAssetStateEventArgs args)
+ {
+ if (args.EventId == FusionAssetEventId.RoomOccupiedReceivedEventId || args.EventId == FusionAssetEventId.RoomUnoccupiedReceivedEventId)
+ RoomIsOccupiedFeedback.FireUpdate();
+
+ }
+
+ ///
+ /// Sets up remote occupancy that will relay the occupancy status determined by local system devices to Fusion
+ ///
+ void SetUpRemoteOccupancy()
+ {
+
+ // Need to have the room occupancy object first and somehow determine the slot number of the Occupancy asset but will not be able to use the UID from config likely.
+ // Consider defining an object just for Room Occupancy (either eAssetType.Occupancy Sensor (local) or eAssetType.RemoteOccupancySensor (from Fusion sched. panel)) and reserving slot 4 for that asset (statics would start at 5)
+
+ //if (Room.OccupancyObj != null)
+ //{
+
+ var tempOccAsset = GUIDs.OccupancyAsset;
+
+ if(tempOccAsset == null)
+ {
+ FusionOccSensor = new FusionOccupancySensorAsset(eAssetType.OccupancySensor);
+ tempOccAsset = FusionOccSensor;
+ }
+
+ var occSensorAsset = FusionRoom.CreateOccupancySensorAsset(tempOccAsset.SlotNumber, tempOccAsset.Name, "Occupancy Sensor", tempOccAsset.InstanceId);
+
+ occSensorAsset.RoomOccupied.AddSigToRVIFile = true;
+
+ var occSensorShutdownMinutes = FusionRoom.CreateOffsetUshortSig(70, "Occ Shutdown - Minutes", eSigIoMask.InputOutputSig);
+
+ // Tie to method on occupancy object
//occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b));
- RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
+ RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
Room.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig);
- Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
- RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
-
- //}
+ Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
+ RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
+
+ //}
}
void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e)
@@ -1392,222 +1403,222 @@ namespace PepperDash.Essentials.Core.Fusion
RoomOccupancyRemoteStringFeedback.FireUpdate();
}
- ///
- /// Helper to get the number from the end of a device's key string
- ///
- /// -1 if no number matched
- int ExtractNumberFromKey(string key)
- {
- var capture = System.Text.RegularExpressions.Regex.Match(key, @"\b(\d+)");
- if (!capture.Success)
- return -1;
- else return Convert.ToInt32(capture.Groups[1].Value);
- }
-
- ///
- /// Event handler for when room source changes
- ///
- protected void Room_CurrentSourceInfoChange(SourceListItem info, ChangeType type)
- {
- // Handle null. Nothing to do when switching from or to null
- if (info == null || info.SourceDevice == null)
- return;
-
- var dev = info.SourceDevice;
- if (type == ChangeType.WillChange)
- {
- if (SourceToFeedbackSigs.ContainsKey(dev))
- SourceToFeedbackSigs[dev].BoolValue = false;
- }
- else
- {
- if (SourceToFeedbackSigs.ContainsKey(dev))
- SourceToFeedbackSigs[dev].BoolValue = true;
- //var name = (room == null ? "" : room.Name);
- CurrentRoomSourceNameSig.InputSig.StringValue = info.SourceDevice.Name;
- }
- }
-
- protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args)
- {
-
- // The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
- // even though they all contain sigs.
-
- var sigData = (args.UserConfiguredSigDetail as BooleanSigDataFixedName);
- if (sigData != null)
- {
- var outSig = sigData.OutputSig;
- if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.BoolValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.UShortValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.StringValue);
- return;
- }
-
- var attrData = (args.UserConfiguredSigDetail as BooleanSigData);
- if (attrData != null)
- {
- var outSig = attrData.OutputSig;
- if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.BoolValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.UShortValue);
- else if (outSig.UserObject is Action)
- (outSig.UserObject as Action).Invoke(outSig.StringValue);
- return;
- }
-
- }
- }
-
-
- public static class FusionRoomExtensions
- {
- ///
- /// Creates and returns a fusion attribute. The join number will match the established Simpl
- /// standard of 50+, and will generate a 50+ join in the RVI. It calls
- /// FusionRoom.AddSig with join number - 49
- ///
- /// The new attribute
- public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
- {
- if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
- number -= 49;
- fr.AddSig(eSigType.Bool, number, name, mask);
- return fr.UserDefinedBooleanSigDetails[number];
- }
-
- ///
- /// Creates and returns a fusion attribute. The join number will match the established Simpl
- /// standard of 50+, and will generate a 50+ join in the RVI. It calls
- /// FusionRoom.AddSig with join number - 49
- ///
- /// The new attribute
- public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
- {
- if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
- number -= 49;
- fr.AddSig(eSigType.UShort, number, name, mask);
- return fr.UserDefinedUShortSigDetails[number];
- }
-
- ///
- /// Creates and returns a fusion attribute. The join number will match the established Simpl
- /// standard of 50+, and will generate a 50+ join in the RVI. It calls
- /// FusionRoom.AddSig with join number - 49
- ///
- /// The new attribute
- public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
- {
- if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
- number -= 49;
- fr.AddSig(eSigType.String, number, name, mask);
- return fr.UserDefinedStringSigDetails[number];
- }
-
- ///
- /// Creates and returns a static asset
- ///
- /// the new asset
- public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
- {
- Debug.Console(0, "Adding Fusion Static Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
-
- fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId);
- return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset;
- }
-
- public static FusionOccupancySensor CreateOccupancySensorAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
- {
- Debug.Console(0, "Adding Fusion Occupancy Sensor Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
-
- fr.AddAsset(eAssetType.OccupancySensor, number, name, type, instanceId);
- return fr.UserConfigurableAssetDetails[number].Asset as FusionOccupancySensor;
- }
- }
-
- //************************************************************************************************
- ///
- /// Extensions to enhance Fusion room, asset and signal creation.
- ///
- public static class FusionStaticAssetExtensions
- {
- ///
- /// Tries to set a Fusion asset with the make and model of a device.
- /// If the provided Device is IMakeModel, will set the corresponding parameters on the fusion static asset.
- /// Otherwise, does nothing.
- ///
- public static void TrySetMakeModel(this FusionStaticAsset asset, Device device)
- {
- var mm = device as IMakeModel;
- if (mm != null)
- {
- asset.ParamMake.Value = mm.DeviceMake;
- asset.ParamModel.Value = mm.DeviceModel;
- }
- }
-
- ///
- /// Tries to attach the AssetError input on a Fusion asset to a Device's
- /// CommunicationMonitor.StatusChange event. Does nothing if the device is not
- /// IStatusMonitor
- ///
- ///
- ///
- public static void TryLinkAssetErrorToCommunication(this FusionStaticAsset asset, Device device)
- {
- if (device is ICommunicationMonitor)
- {
- var monitor = (device as ICommunicationMonitor).CommunicationMonitor;
- monitor.StatusChange += (o, a) =>
- {
- // Link connected and error inputs on asset
- asset.Connected.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
- asset.AssetError.InputSig.StringValue = a.Status.ToString();
- };
- // set current value
- asset.Connected.InputSig.BoolValue = monitor.Status == MonitorStatus.IsOk;
- asset.AssetError.InputSig.StringValue = monitor.Status.ToString();
- }
- }
- }
-
- public class RoomInformation
- {
- public string ID { get; set; }
- public string Name { get; set; }
- public string Location { get; set; }
- public string Description { get; set; }
- public string TimeZone { get; set; }
- public string WebcamURL { get; set; }
- public string BacklogMsg { get; set; }
- public string SubErrorMsg { get; set; }
- public string EmailInfo { get; set; }
- public List FusionCustomProperties { get; set; }
-
- public RoomInformation()
- {
- FusionCustomProperties = new List();
- }
- }
- public class FusionCustomProperty
- {
- public string ID { get; set; }
- public string CustomFieldName { get; set; }
- public string CustomFieldType { get; set; }
- public string CustomFieldValue { get; set; }
-
- public FusionCustomProperty()
- {
-
- }
-
- public FusionCustomProperty(string id)
- {
- ID = id;
- }
- }
+ ///
+ /// Helper to get the number from the end of a device's key string
+ ///
+ /// -1 if no number matched
+ int ExtractNumberFromKey(string key)
+ {
+ var capture = System.Text.RegularExpressions.Regex.Match(key, @"\b(\d+)");
+ if (!capture.Success)
+ return -1;
+ else return Convert.ToInt32(capture.Groups[1].Value);
+ }
+
+ ///
+ /// Event handler for when room source changes
+ ///
+ protected void Room_CurrentSourceInfoChange(SourceListItem info, ChangeType type)
+ {
+ // Handle null. Nothing to do when switching from or to null
+ if (info == null || info.SourceDevice == null)
+ return;
+
+ var dev = info.SourceDevice;
+ if (type == ChangeType.WillChange)
+ {
+ if (SourceToFeedbackSigs.ContainsKey(dev))
+ SourceToFeedbackSigs[dev].BoolValue = false;
+ }
+ else
+ {
+ if (SourceToFeedbackSigs.ContainsKey(dev))
+ SourceToFeedbackSigs[dev].BoolValue = true;
+ //var name = (room == null ? "" : room.Name);
+ CurrentRoomSourceNameSig.InputSig.StringValue = info.SourceDevice.Name;
+ }
+ }
+
+ protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args)
+ {
+
+ // The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
+ // even though they all contain sigs.
+
+ var sigData = (args.UserConfiguredSigDetail as BooleanSigDataFixedName);
+ if (sigData != null)
+ {
+ var outSig = sigData.OutputSig;
+ if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.BoolValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.UShortValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.StringValue);
+ return;
+ }
+
+ var attrData = (args.UserConfiguredSigDetail as BooleanSigData);
+ if (attrData != null)
+ {
+ var outSig = attrData.OutputSig;
+ if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.BoolValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.UShortValue);
+ else if (outSig.UserObject is Action)
+ (outSig.UserObject as Action).Invoke(outSig.StringValue);
+ return;
+ }
+
+ }
+ }
+
+
+ public static class FusionRoomExtensions
+ {
+ ///
+ /// Creates and returns a fusion attribute. The join number will match the established Simpl
+ /// standard of 50+, and will generate a 50+ join in the RVI. It calls
+ /// FusionRoom.AddSig with join number - 49
+ ///
+ /// The new attribute
+ public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
+ {
+ if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
+ number -= 49;
+ fr.AddSig(eSigType.Bool, number, name, mask);
+ return fr.UserDefinedBooleanSigDetails[number];
+ }
+
+ ///
+ /// Creates and returns a fusion attribute. The join number will match the established Simpl
+ /// standard of 50+, and will generate a 50+ join in the RVI. It calls
+ /// FusionRoom.AddSig with join number - 49
+ ///
+ /// The new attribute
+ public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
+ {
+ if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
+ number -= 49;
+ fr.AddSig(eSigType.UShort, number, name, mask);
+ return fr.UserDefinedUShortSigDetails[number];
+ }
+
+ ///
+ /// Creates and returns a fusion attribute. The join number will match the established Simpl
+ /// standard of 50+, and will generate a 50+ join in the RVI. It calls
+ /// FusionRoom.AddSig with join number - 49
+ ///
+ /// The new attribute
+ public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
+ {
+ if (number < 50) throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
+ number -= 49;
+ fr.AddSig(eSigType.String, number, name, mask);
+ return fr.UserDefinedStringSigDetails[number];
+ }
+
+ ///
+ /// Creates and returns a static asset
+ ///
+ /// the new asset
+ public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
+ {
+ Debug.Console(0, "Adding Fusion Static Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
+
+ fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId);
+ return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset;
+ }
+
+ public static FusionOccupancySensor CreateOccupancySensorAsset(this FusionRoom fr, uint number, string name, string type, string instanceId)
+ {
+ Debug.Console(0, "Adding Fusion Occupancy Sensor Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId);
+
+ fr.AddAsset(eAssetType.OccupancySensor, number, name, type, instanceId);
+ return fr.UserConfigurableAssetDetails[number].Asset as FusionOccupancySensor;
+ }
+ }
+
+ //************************************************************************************************
+ ///
+ /// Extensions to enhance Fusion room, asset and signal creation.
+ ///
+ public static class FusionStaticAssetExtensions
+ {
+ ///
+ /// Tries to set a Fusion asset with the make and model of a device.
+ /// If the provided Device is IMakeModel, will set the corresponding parameters on the fusion static asset.
+ /// Otherwise, does nothing.
+ ///
+ public static void TrySetMakeModel(this FusionStaticAsset asset, Device device)
+ {
+ var mm = device as IMakeModel;
+ if (mm != null)
+ {
+ asset.ParamMake.Value = mm.DeviceMake;
+ asset.ParamModel.Value = mm.DeviceModel;
+ }
+ }
+
+ ///
+ /// Tries to attach the AssetError input on a Fusion asset to a Device's
+ /// CommunicationMonitor.StatusChange event. Does nothing if the device is not
+ /// IStatusMonitor
+ ///
+ ///
+ ///
+ public static void TryLinkAssetErrorToCommunication(this FusionStaticAsset asset, Device device)
+ {
+ if (device is ICommunicationMonitor)
+ {
+ var monitor = (device as ICommunicationMonitor).CommunicationMonitor;
+ monitor.StatusChange += (o, a) =>
+ {
+ // Link connected and error inputs on asset
+ asset.Connected.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
+ asset.AssetError.InputSig.StringValue = a.Status.ToString();
+ };
+ // set current value
+ asset.Connected.InputSig.BoolValue = monitor.Status == MonitorStatus.IsOk;
+ asset.AssetError.InputSig.StringValue = monitor.Status.ToString();
+ }
+ }
+ }
+
+ public class RoomInformation
+ {
+ public string ID { get; set; }
+ public string Name { get; set; }
+ public string Location { get; set; }
+ public string Description { get; set; }
+ public string TimeZone { get; set; }
+ public string WebcamURL { get; set; }
+ public string BacklogMsg { get; set; }
+ public string SubErrorMsg { get; set; }
+ public string EmailInfo { get; set; }
+ public List FusionCustomProperties { get; set; }
+
+ public RoomInformation()
+ {
+ FusionCustomProperties = new List();
+ }
+ }
+ public class FusionCustomProperty
+ {
+ public string ID { get; set; }
+ public string CustomFieldName { get; set; }
+ public string CustomFieldType { get; set; }
+ public string CustomFieldValue { get; set; }
+
+ public FusionCustomProperty()
+ {
+
+ }
+
+ public FusionCustomProperty(string id)
+ {
+ ID = id;
+ }
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs
index ece2c65f..0f15a02d 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Microphone Privacy/MicrophonePrivacyController.cs
@@ -88,8 +88,12 @@ namespace PepperDash.Essentials.Core.Privacy
else
Debug.Console(0, this, "Unable to add Red LED device");
+ DeviceManager.AllDevicesActivated += (o, a) =>
+ {
+ CheckPrivacyMode();
+ };
+
AddPostActivationAction(() => {
- CheckPrivacyMode();
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange;
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
});
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
index 2b45030c..6d4def73 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
@@ -83,7 +83,7 @@
..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll
-
+
False
..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll
@@ -183,6 +183,9 @@
+
+
+
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec
index d5bb4a57..5db86afc 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.nuspec
@@ -14,7 +14,7 @@
crestron 3series 4series
-
+
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs
index 4cf36470..0043e3b4 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs
@@ -1,58 +1,58 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using Crestron.SimplSharp.Scheduler;
-
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Config;
-using PepperDash.Essentials.Core.Devices;
-using PepperDash.Essentials.Core.DeviceTypeInterfaces;
-
-namespace PepperDash.Essentials.Core
-{
- ///
- ///
- ///
- public abstract class EssentialsRoomBase : ReconfigurableDevice
- {
- ///
- ///
- ///
- public BoolFeedback OnFeedback { get; private set; }
-
- ///
- /// Fires when the RoomOccupancy object is set
- ///
- public event EventHandler RoomOccupancyIsSet;
-
- public BoolFeedback IsWarmingUpFeedback { get; private set; }
- public BoolFeedback IsCoolingDownFeedback { get; private set; }
-
- public IOccupancyStatusProvider RoomOccupancy { get; private set; }
-
- public bool OccupancyStatusProviderIsRemote { get; private set; }
-
- protected abstract Func IsWarmingFeedbackFunc { get; }
- protected abstract Func IsCoolingFeedbackFunc { get; }
-
- ///
- /// Indicates if this room is Mobile Control Enabled
- ///
- public bool IsMobileControlEnabled { get; private set; }
-
- ///
- /// The bridge for this room if Mobile Control is enabled
- ///
- public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
-
- ///
- /// The config name of the source list
- ///
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.Scheduler;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Devices;
+using PepperDash.Essentials.Core.DeviceTypeInterfaces;
+
+namespace PepperDash.Essentials.Core
+{
+ ///
+ ///
+ ///
+ public abstract class EssentialsRoomBase : ReconfigurableDevice
+ {
+ ///
+ ///
+ ///
+ public BoolFeedback OnFeedback { get; private set; }
+
+ ///
+ /// Fires when the RoomOccupancy object is set
+ ///
+ public event EventHandler RoomOccupancyIsSet;
+
+ public BoolFeedback IsWarmingUpFeedback { get; private set; }
+ public BoolFeedback IsCoolingDownFeedback { get; private set; }
+
+ public IOccupancyStatusProvider RoomOccupancy { get; private set; }
+
+ public bool OccupancyStatusProviderIsRemote { get; private set; }
+
+ protected abstract Func IsWarmingFeedbackFunc { get; }
+ protected abstract Func IsCoolingFeedbackFunc { get; }
+
+ ///
+ /// Indicates if this room is Mobile Control Enabled
+ ///
+ public bool IsMobileControlEnabled { get; private set; }
+
+ ///
+ /// The bridge for this room if Mobile Control is enabled
+ ///
+ public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
+
+ ///
+ /// The config name of the source list
+ ///
///
- protected string _SourceListKey;
+ protected string _SourceListKey;
public virtual string SourceListKey {
get
{
@@ -63,306 +63,306 @@ namespace PepperDash.Essentials.Core
_SourceListKey = value;
}
- }
-
- ///
- /// Timer used for informing the UIs of a shutdown
- ///
- public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
-
- ///
- ///
- ///
- public int ShutdownPromptSeconds { get; set; }
- public int ShutdownVacancySeconds { get; set; }
- public eShutdownType ShutdownType { get; private set; }
-
- public EssentialsRoomEmergencyBase Emergency { get; set; }
-
- public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
-
- public string LogoUrlLightBkgnd { get; set; }
-
- public string LogoUrlDarkBkgnd { get; set; }
-
- protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
-
- public eVacancyMode VacancyMode { get; private set; }
-
- ///
- /// Seconds after vacancy prompt is displayed until shutdown
- ///
- protected int RoomVacancyShutdownSeconds;
-
- ///
- /// Seconds after vacancy detected until prompt is displayed
- ///
- protected int RoomVacancyShutdownPromptSeconds;
-
- ///
- ///
- ///
- protected abstract Func OnFeedbackFunc { get; }
-
- protected Dictionary SavedVolumeLevels = new Dictionary();
-
- ///
- /// When volume control devices change, should we zero the one that we are leaving?
- ///
- public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
-
-
- public EssentialsRoomBase(DeviceConfig config)
- : base(config)
- {
- // Setup the ShutdownPromptTimer
- ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
- ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
- {
- if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
- ShutdownType = eShutdownType.None;
- };
- ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
-
- ShutdownPromptSeconds = 60;
- ShutdownVacancySeconds = 120;
-
- ShutdownType = eShutdownType.None;
-
- RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
- //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
- //{
- // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
- // ShutdownType = ShutdownType.Vacancy;
- //};
- RoomVacancyShutdownTimer.HasFinished += new EventHandler(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
-
- RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
- RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
- VacancyMode = eVacancyMode.None;
-
- OnFeedback = new BoolFeedback(OnFeedbackFunc);
-
- IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
- IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
-
- AddPostActivationAction(() =>
- {
- if (RoomOccupancy != null)
- OnRoomOccupancyIsSet();
- });
- }
-
- public override bool CustomActivate()
- {
- SetUpMobileControl();
-
- return base.CustomActivate();
- }
-
- ///
- /// If mobile control is enabled, sets the appropriate properties
- ///
- void SetUpMobileControl()
- {
- var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key);
- var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey);
- if (mcBridge == null)
- {
- Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room.");
- IsMobileControlEnabled = false;
- return;
- }
- else
- {
- MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
- Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
- IsMobileControlEnabled = true;
- }
- }
-
- void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
- {
- switch (VacancyMode)
- {
- case eVacancyMode.None:
- StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
- break;
- case eVacancyMode.InInitialVacancy:
- StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
- break;
- case eVacancyMode.InShutdownWarning:
- {
- StartShutdown(eShutdownType.Vacancy);
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
- break;
- }
- default:
- break;
- }
- }
-
- ///
- ///
- ///
- ///
- public void StartShutdown(eShutdownType type)
- {
- // Check for shutdowns running. Manual should override other shutdowns
-
- if (type == eShutdownType.Manual)
- ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
- else if (type == eShutdownType.Vacancy)
- ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
- ShutdownType = type;
- ShutdownPromptTimer.Start();
-
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
- }
-
- public void StartRoomVacancyTimer(eVacancyMode mode)
- {
- if (mode == eVacancyMode.None)
- RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
- else if (mode == eVacancyMode.InInitialVacancy)
- RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
- else if (mode == eVacancyMode.InShutdownWarning)
- RoomVacancyShutdownTimer.SecondsToCount = 60;
- VacancyMode = mode;
- RoomVacancyShutdownTimer.Start();
-
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
- }
-
- ///
- /// Resets the vacancy mode and shutsdwon the room
- ///
- public void Shutdown()
- {
- VacancyMode = eVacancyMode.None;
- EndShutdown();
- }
-
- ///
- /// This method is for the derived class to define it's specific shutdown
- /// requirements but should not be called directly. It is called by Shutdown()
- ///
- protected abstract void EndShutdown();
-
-
- ///
- /// Override this to implement a default volume level(s) method
- ///
- public abstract void SetDefaultLevels();
-
- ///
- /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
- ///
- ///
- public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
- {
- if (statusProvider == null)
- {
- Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
- return;
- }
-
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes);
-
- // If status provider is fusion, set flag to remote
- if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
- OccupancyStatusProviderIsRemote = true;
-
- if(timeoutMinutes > 0)
- RoomVacancyShutdownSeconds = timeoutMinutes * 60;
-
- Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
-
- RoomOccupancy = statusProvider;
-
- RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
- RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
-
- OnRoomOccupancyIsSet();
- }
-
- void OnRoomOccupancyIsSet()
- {
- var handler = RoomOccupancyIsSet;
- if (handler != null)
- handler(this, new EventArgs());
- }
-
- ///
- /// To allow base class to power room on to last source
- ///
- public abstract void PowerOnToDefaultOrLastSource();
-
- ///
- /// To allow base class to power room on to default source
- ///
- ///
- public abstract bool RunDefaultPresentRoute();
-
- void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
- {
- if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
- {
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected");
- // Trigger the timer when the room is vacant
- StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
- }
- else
- {
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected");
- // Reset the timer when the room is occupied
- RoomVacancyShutdownTimer.Cancel();
- }
- }
-
- ///
- /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
- ///
- ///
- public abstract void RoomVacatedForTimeoutPeriod(object o);
- }
-
- ///
- /// To describe the various ways a room may be shutting down
- ///
- public enum eShutdownType
- {
- None = 0,
- External,
- Manual,
- Vacancy
- }
-
- public enum eVacancyMode
- {
- None = 0,
- InInitialVacancy,
- InShutdownWarning
- }
-
- ///
- ///
- ///
- public enum eWarmingCoolingMode
- {
- None,
- Warming,
- Cooling
- }
-
- public abstract class EssentialsRoomEmergencyBase : IKeyed
- {
- public string Key { get; private set; }
-
- public EssentialsRoomEmergencyBase(string key)
- {
- Key = key;
- }
- }
+ }
+
+ ///
+ /// Timer used for informing the UIs of a shutdown
+ ///
+ public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
+
+ ///
+ ///
+ ///
+ public int ShutdownPromptSeconds { get; set; }
+ public int ShutdownVacancySeconds { get; set; }
+ public eShutdownType ShutdownType { get; private set; }
+
+ public EssentialsRoomEmergencyBase Emergency { get; set; }
+
+ public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
+
+ public string LogoUrlLightBkgnd { get; set; }
+
+ public string LogoUrlDarkBkgnd { get; set; }
+
+ protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
+
+ public eVacancyMode VacancyMode { get; private set; }
+
+ ///
+ /// Seconds after vacancy prompt is displayed until shutdown
+ ///
+ protected int RoomVacancyShutdownSeconds;
+
+ ///
+ /// Seconds after vacancy detected until prompt is displayed
+ ///
+ protected int RoomVacancyShutdownPromptSeconds;
+
+ ///
+ ///
+ ///
+ protected abstract Func OnFeedbackFunc { get; }
+
+ protected Dictionary SavedVolumeLevels = new Dictionary();
+
+ ///
+ /// When volume control devices change, should we zero the one that we are leaving?
+ ///
+ public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
+
+
+ public EssentialsRoomBase(DeviceConfig config)
+ : base(config)
+ {
+ // Setup the ShutdownPromptTimer
+ ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
+ ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
+ {
+ if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
+ ShutdownType = eShutdownType.None;
+ };
+ ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
+
+ ShutdownPromptSeconds = 60;
+ ShutdownVacancySeconds = 120;
+
+ ShutdownType = eShutdownType.None;
+
+ RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
+ //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
+ //{
+ // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
+ // ShutdownType = ShutdownType.Vacancy;
+ //};
+ RoomVacancyShutdownTimer.HasFinished += new EventHandler(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
+
+ RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
+ RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
+ VacancyMode = eVacancyMode.None;
+
+ OnFeedback = new BoolFeedback(OnFeedbackFunc);
+
+ IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
+ IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
+
+ AddPostActivationAction(() =>
+ {
+ if (RoomOccupancy != null)
+ OnRoomOccupancyIsSet();
+ });
+ }
+
+ public override bool CustomActivate()
+ {
+ SetUpMobileControl();
+
+ return base.CustomActivate();
+ }
+
+ ///
+ /// If mobile control is enabled, sets the appropriate properties
+ ///
+ void SetUpMobileControl()
+ {
+ var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key);
+ var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey);
+ if (mcBridge == null)
+ {
+ Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room.");
+ IsMobileControlEnabled = false;
+ return;
+ }
+ else
+ {
+ MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
+ Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
+ IsMobileControlEnabled = true;
+ }
+ }
+
+ void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
+ {
+ switch (VacancyMode)
+ {
+ case eVacancyMode.None:
+ StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
+ break;
+ case eVacancyMode.InInitialVacancy:
+ StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
+ break;
+ case eVacancyMode.InShutdownWarning:
+ {
+ StartShutdown(eShutdownType.Vacancy);
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void StartShutdown(eShutdownType type)
+ {
+ // Check for shutdowns running. Manual should override other shutdowns
+
+ if (type == eShutdownType.Manual)
+ ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
+ else if (type == eShutdownType.Vacancy)
+ ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
+ ShutdownType = type;
+ ShutdownPromptTimer.Start();
+
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
+ }
+
+ public void StartRoomVacancyTimer(eVacancyMode mode)
+ {
+ if (mode == eVacancyMode.None)
+ RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
+ else if (mode == eVacancyMode.InInitialVacancy)
+ RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
+ else if (mode == eVacancyMode.InShutdownWarning)
+ RoomVacancyShutdownTimer.SecondsToCount = 60;
+ VacancyMode = mode;
+ RoomVacancyShutdownTimer.Start();
+
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
+ }
+
+ ///
+ /// Resets the vacancy mode and shutsdwon the room
+ ///
+ public void Shutdown()
+ {
+ VacancyMode = eVacancyMode.None;
+ EndShutdown();
+ }
+
+ ///
+ /// This method is for the derived class to define it's specific shutdown
+ /// requirements but should not be called directly. It is called by Shutdown()
+ ///
+ protected abstract void EndShutdown();
+
+
+ ///
+ /// Override this to implement a default volume level(s) method
+ ///
+ public abstract void SetDefaultLevels();
+
+ ///
+ /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
+ ///
+ ///
+ public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
+ {
+ if (statusProvider == null)
+ {
+ Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
+ return;
+ }
+
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes);
+
+ // If status provider is fusion, set flag to remote
+ if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
+ OccupancyStatusProviderIsRemote = true;
+
+ if(timeoutMinutes > 0)
+ RoomVacancyShutdownSeconds = timeoutMinutes * 60;
+
+ Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
+
+ RoomOccupancy = statusProvider;
+
+ RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
+ RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
+
+ OnRoomOccupancyIsSet();
+ }
+
+ void OnRoomOccupancyIsSet()
+ {
+ var handler = RoomOccupancyIsSet;
+ if (handler != null)
+ handler(this, new EventArgs());
+ }
+
+ ///
+ /// To allow base class to power room on to last source
+ ///
+ public abstract void PowerOnToDefaultOrLastSource();
+
+ ///
+ /// To allow base class to power room on to default source
+ ///
+ ///
+ public abstract bool RunDefaultPresentRoute();
+
+ void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
+ {
+ if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
+ {
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected");
+ // Trigger the timer when the room is vacant
+ StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
+ }
+ else
+ {
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected");
+ // Reset the timer when the room is occupied
+ RoomVacancyShutdownTimer.Cancel();
+ }
+ }
+
+ ///
+ /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
+ ///
+ ///
+ public abstract void RoomVacatedForTimeoutPeriod(object o);
+ }
+
+ ///
+ /// To describe the various ways a room may be shutting down
+ ///
+ public enum eShutdownType
+ {
+ None = 0,
+ External,
+ Manual,
+ Vacancy
+ }
+
+ public enum eVacancyMode
+ {
+ None = 0,
+ InInitialVacancy,
+ InShutdownWarning
+ }
+
+ ///
+ ///
+ ///
+ public enum eWarmingCoolingMode
+ {
+ None,
+ Warming,
+ Cooling
+ }
+
+ public abstract class EssentialsRoomEmergencyBase : IKeyed
+ {
+ public string Key { get; private set; }
+
+ public EssentialsRoomEmergencyBase(string key)
+ {
+ Key = key;
+ }
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs
index 6c8d520b..c7f2e533 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs
@@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core
///
/// For fixed-source endpoint devices
///
- [Obsolete]
+ [Obsolete("Please switch to IRoutingSink")]
public interface IRoutingSinkNoSwitching : IRoutingSink
{
@@ -111,10 +111,87 @@ namespace PepperDash.Essentials.Core
IntFeedback AudioVideoSourceNumericFeedback { get; }
}
- ///
+
+ ///
+ /// Defines an IRmcRouting with a feedback event
+ ///
+ public interface ITxRoutingWithFeedback : ITxRouting
+ {
+ }
+
+ ///
+ /// Defines an IRmcRouting with a feedback event
+ ///
+ public interface IRmcRoutingWithFeedback : IRmcRouting
+ {
+ }
+
+ ///
/// Defines an IRoutingOutputs devices as being a source - the start of the chain
///
public interface IRoutingSource : IRoutingOutputs
{
}
+
+ ///
+ /// Defines an event structure for reporting output route data
+ ///
+ public interface IRoutingFeedback : IKeyName
+ {
+ event EventHandler NumericSwitchChange;
+ //void OnSwitchChange(RoutingNumericEventArgs e);
+ }
+
+ ///
+ /// Defines an IRoutingNumeric with a feedback event
+ ///
+ public interface IRoutingNumericWithFeedback : IRoutingNumeric, IRoutingFeedback
+ {
+ }
+
+ ///
+ /// Defines an IRouting with a feedback event
+ ///
+ public interface IRoutingWithFeedback : IRouting, IRoutingFeedback
+ {
+
+ }
+
+ public class RoutingNumericEventArgs : EventArgs
+ {
+
+ public uint? Output { get; set; }
+ public uint? Input { get; set; }
+
+ public eRoutingSignalType SigType { get; set; }
+ public RoutingInputPort InputPort { get; set; }
+ public RoutingOutputPort OutputPort { get; set; }
+
+ public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType)
+ {
+ }
+
+ public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort,
+ eRoutingSignalType sigType)
+ : this(null, null, outputPort, inputPort, sigType)
+ {
+ }
+
+ public RoutingNumericEventArgs()
+ : this(null, null, null, null, 0)
+ {
+
+ }
+
+ public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort,
+ RoutingInputPort inputPort, eRoutingSignalType sigType)
+ {
+ OutputPort = outputPort;
+ InputPort = inputPort;
+
+ Output = output;
+ Input = input;
+ SigType = sigType;
+ }
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs b/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs
index 709aa500..ce2204fe 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs
@@ -17,7 +17,7 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.AirMedia
{
[Description("Wrapper class for an AM-200 or AM-300")]
- public class AirMediaController : CrestronGenericBridgeableBaseDevice, IRoutingNumeric, IIROutputPorts, IComPorts
+ public class AirMediaController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IIROutputPorts, IComPorts
{
public AmX00 AirMedia { get; private set; }
@@ -29,6 +29,10 @@ namespace PepperDash.Essentials.DM.AirMedia
public RoutingPortCollection OutputPorts { get; private set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
public BoolFeedback IsInSessionFeedback { get; private set; }
public IntFeedback ErrorFeedback { get; private set; }
public IntFeedback NumberOfUsersConnectedFeedback { get; set; }
@@ -43,6 +47,7 @@ namespace PepperDash.Essentials.DM.AirMedia
public AirMediaController(string key, string name, AmX00 device, DeviceConfig dc, AirMediaPropertiesConfig props)
: base(key, name, device)
{
+
AirMedia = device;
DeviceConfig = dc;
@@ -53,21 +58,36 @@ namespace PepperDash.Essentials.DM.AirMedia
OutputPorts = new RoutingPortCollection();
InputPorts.Add(new RoutingInputPort(DmPortName.Osd, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.None, new Action(SelectPinPointUxLandingPage), this));
+ eRoutingPortConnectionType.None, new Action(SelectPinPointUxLandingPage), this)
+ {
+ FeedbackMatchObject = 0
+ });
InputPorts.Add(new RoutingInputPort(DmPortName.AirMediaIn, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.Streaming, new Action(SelectAirMedia), this));
+ eRoutingPortConnectionType.Streaming, new Action(SelectAirMedia), this)
+ {
+ FeedbackMatchObject = 1
+ });
InputPorts.Add(new RoutingInputPort(DmPortName.HdmiIn, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.Hdmi, new Action(SelectHdmiIn), this));
+ eRoutingPortConnectionType.Hdmi, new Action(SelectHdmiIn), this)
+ {
+ FeedbackMatchObject = 2
+ });
InputPorts.Add(new RoutingInputPort(DmPortName.AirBoardIn, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.None, new Action(SelectAirboardIn), this));
+ eRoutingPortConnectionType.None, new Action(SelectAirboardIn), this)
+ {
+ FeedbackMatchObject = 4
+ });
if (AirMedia is Am300)
{
InputPorts.Add(new RoutingInputPort(DmPortName.DmIn, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.DmCat, new Action(SelectDmIn), this));
+ eRoutingPortConnectionType.DmCat, new Action(SelectDmIn), this)
+ {
+ FeedbackMatchObject = 3
+ });
}
OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo,
@@ -153,6 +173,17 @@ namespace PepperDash.Essentials.DM.AirMedia
SerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.SerialNumberFeedback.JoinNumber]);
}
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
+
void AirMedia_AirMediaChange(object sender, Crestron.SimplSharpPro.DeviceSupport.GenericEventArgs args)
{
if (args.EventId == AirMediaInputSlot.AirMediaStatusFeedbackEventId)
@@ -172,12 +203,20 @@ namespace PepperDash.Essentials.DM.AirMedia
void DisplayControl_DisplayControlChange(object sender, Crestron.SimplSharpPro.DeviceSupport.GenericEventArgs args)
{
if (args.EventId == AmX00.VideoOutFeedbackEventId)
+ {
VideoOutFeedback.FireUpdate();
+
+ var localInputPort =
+ InputPorts.FirstOrDefault(p => (int) p.FeedbackMatchObject == VideoOutFeedback.UShortValue);
+
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoOutFeedback.UShortValue, OutputPorts.First(),
+ localInputPort, eRoutingSignalType.AudioVideo));
+ }
else if (args.EventId == AmX00.EnableAutomaticRoutingFeedbackEventId)
AutomaticInputRoutingEnabledFeedback.FireUpdate();
}
- void HdmiIn_StreamChange(Crestron.SimplSharpPro.DeviceSupport.Stream stream, Crestron.SimplSharpPro.DeviceSupport.StreamEventArgs args)
+ void HdmiIn_StreamChange(Stream stream, Crestron.SimplSharpPro.DeviceSupport.StreamEventArgs args)
{
if (args.EventId == DMInputEventIds.SourceSyncEventId)
HdmiVideoSyncDetectedFeedback.FireUpdate();
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmBladeChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmBladeChassisController.cs
index 1ac15263..abeba8d8 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmBladeChassisController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmBladeChassisController.cs
@@ -21,12 +21,15 @@ 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, IRoutingNumeric
+ public class DmBladeChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback
{
public DMChassisPropertiesConfig PropertiesConfig { get; set; }
public Switch Chassis { get; private set; }
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
// Feedbacks for EssentialDM
public Dictionary VideoOutputFeedbacks { get; private set; }
public Dictionary AudioOutputFeedbacks { get; private set; }
@@ -287,6 +290,15 @@ namespace PepperDash.Essentials.DM {
}
}
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
void AddHdmiInBladePorts(uint number, ICec cecPort) {
@@ -377,7 +389,10 @@ namespace PepperDash.Essentials.DM {
void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType) {
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
- var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
+ var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
+ {
+ FeedbackMatchObject = Chassis.Inputs[cardNum]
+ };
InputPorts.Add(inputPort);
}
@@ -385,19 +400,20 @@ namespace PepperDash.Essentials.DM {
///
/// Adds InputPort and sets Port as ICec object
///
- void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, ICec cecPort) {
+ private void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType,
+ eRoutingPortConnectionType portType, ICec cecPort)
+ {
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
- var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
+ var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
+ {
+ FeedbackMatchObject = Chassis.Inputs[cardNum]
+ };
- if (inputPort != null) {
- if (cecPort != null)
- inputPort.Port = cecPort;
+ if (cecPort != null)
+ inputPort.Port = cecPort;
- InputPorts.Add(inputPort);
- }
- else
- Debug.Console(2, this, "inputPort is null");
+ InputPorts.Add(inputPort);
}
@@ -407,7 +423,10 @@ namespace PepperDash.Essentials.DM {
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) {
var portKey = string.Format("{0}--{1}", cardName, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
- OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this));
+ OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)
+ {
+ FeedbackMatchObject = Chassis.Outputs[(uint)selector]
+ });
}
@@ -458,54 +477,84 @@ namespace PepperDash.Essentials.DM {
}
}
}
+
///
///
- void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
+ private void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
var output = args.Number;
- switch (args.EventId) {
- case DMOutputEventIds.VolumeEventId: {
- if (VolumeControls.ContainsKey(output)) {
- VolumeControls[args.Number].VolumeEventFromChassis();
- }
- break;
+ switch (args.EventId)
+ {
+ case DMOutputEventIds.VolumeEventId:
+ {
+ if (VolumeControls.ContainsKey(output))
+ {
+ VolumeControls[args.Number].VolumeEventFromChassis();
}
- case DMOutputEventIds.EndpointOnlineEventId: {
- Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}", args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
- if(Chassis.Outputs[output].Endpoint != null)
- Debug.Console(2, this, "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}", args.Number, Chassis.Outputs[output].Endpoint.IsOnline);
+ break;
+ }
+ case DMOutputEventIds.EndpointOnlineEventId:
+ {
+ Debug.Console(2, this,
+ "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}",
+ args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
+ if (Chassis.Outputs[output].Endpoint != null)
+ Debug.Console(2, this,
+ "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}",
+ args.Number, Chassis.Outputs[output].Endpoint.IsOnline);
- OutputEndpointOnlineFeedbacks[output].FireUpdate();
- break;
- }
- case DMOutputEventIds.OnlineFeedbackEventId: {
- Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
- OutputEndpointOnlineFeedbacks[output].FireUpdate();
- break;
- }
- case DMOutputEventIds.VideoOutEventId: {
- if (Chassis.Outputs[output].VideoOutFeedback != null) {
- Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output);
- }
- if (VideoOutputFeedbacks.ContainsKey(output)) {
- VideoOutputFeedbacks[output].FireUpdate();
+ OutputEndpointOnlineFeedbacks[output].FireUpdate();
+ break;
+ }
+ case DMOutputEventIds.OnlineFeedbackEventId:
+ {
+ Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}",
+ args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
+ OutputEndpointOnlineFeedbacks[output].FireUpdate();
+ break;
+ }
+ case DMOutputEventIds.VideoOutEventId:
+ {
+
+ var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.Outputs[output].VideoOutFeedback.Number;
+
+ Debug.Console(2, this, "DMSwitchAudioVideo:{0} Routed Input:{1} Output:{2}'", this.Name,
+ inputNumber, output);
+
+ if (VideoOutputFeedbacks.ContainsKey(output))
+ {
+ var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].VideoOutFeedback);
+ var localOutputPort =
+ OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == Chassis.Outputs[output]);
+
+
+ VideoOutputFeedbacks[output].FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(output,
+ inputNumber,
+ localOutputPort,
+ localInputPort,
+ eRoutingSignalType.AudioVideo));
- }
- if (OutputVideoRouteNameFeedbacks.ContainsKey(output)) {
- OutputVideoRouteNameFeedbacks[output].FireUpdate();
- }
- break;
}
- case DMOutputEventIds.OutputNameEventId: {
- Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
- OutputNameFeedbacks[output].FireUpdate();
- break;
- }
- default: {
- Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", args.Number, args.EventId);
- break;
+ if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
+ {
+ OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
+ break;
+ }
+ case DMOutputEventIds.OutputNameEventId:
+ {
+ Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
+ OutputNameFeedbacks[output].FireUpdate();
+ break;
+ }
+ default:
+ {
+ Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}",
+ args.Number, args.EventId);
+ break;
+ }
}
}
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs
index 1e376950..09c7988a 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmChassisController.cs
@@ -20,12 +20,15 @@ namespace PepperDash.Essentials.DM
/// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions
///
///
- [Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")]
- public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumeric
+ [Description("Wrapper class for all DM-MD chassis variants from 8x8 to 32x32")]
+ public class DmChassisController : CrestronGenericBridgeableBaseDevice, IDmSwitch, IRoutingNumericWithFeedback
{
public DMChassisPropertiesConfig PropertiesConfig { get; set; }
- public Switch Chassis { get; private set; }
+ public Switch Chassis { get; private set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
// Feedbacks for EssentialDM
public Dictionary VideoOutputFeedbacks { get; private set; }
@@ -187,7 +190,8 @@ namespace PepperDash.Essentials.DM
///
public DmChassisController(string key, string name, DmMDMnxn chassis)
: base(key, name, chassis)
- {
+ {
+
Chassis = chassis;
InputPorts = new RoutingPortCollection();
OutputPorts = new RoutingPortCollection();
@@ -737,7 +741,10 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
- var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
+ var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
+ {
+ FeedbackMatchObject = Chassis.Inputs[cardNum]
+ };
InputPorts.Add(inputPort);
}
@@ -749,12 +756,15 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
- var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
+ var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
+ {
+ FeedbackMatchObject = Chassis.Inputs[cardNum]
+ }; ;
if (cecPort != null)
inputPort.Port = cecPort;
- InputPorts.Add(inputPort);
+ InputPorts.Add(inputPort);
}
///
@@ -763,8 +773,16 @@ namespace PepperDash.Essentials.DM
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector)
{
var portKey = string.Format("{0}--{1}", cardName, portName);
- Debug.Console(2, this, "Adding output port '{0}'", portKey);
- OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this));
+ Debug.Console(2, this, "Adding output port '{0}'", portKey);
+
+ var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
+
+ if (portName.IndexOf("Loop", StringComparison.InvariantCultureIgnoreCase) < 0)
+ {
+ outputPort.FeedbackMatchObject = Chassis.Outputs[(uint) selector];
+ }
+
+ OutputPorts.Add(outputPort);
}
///
@@ -773,13 +791,17 @@ namespace PepperDash.Essentials.DM
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector, ICec cecPort)
{
var portKey = string.Format("{0}--{1}", cardName, portName);
- Debug.Console(2, this, "Adding output port '{0}'", portKey);
- var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
-
+ Debug.Console(2, this, "Adding output port '{0}'", portKey);
+ var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
+
+ if (portName.IndexOf("Loop", StringComparison.InvariantCultureIgnoreCase) < 0)
+ {
+ outputPort.FeedbackMatchObject = Chassis.Outputs[(uint)selector];
+ }
if (cecPort != null)
outputPort.Port = cecPort;
- OutputPorts.Add(outputPort);
+ OutputPorts.Add(outputPort);
}
///
@@ -905,6 +927,17 @@ namespace PepperDash.Essentials.DM
{
Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Chassis_DMInputChange: {0}", ex);
}
+ }
+
+ ///
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
}
///
@@ -938,30 +971,59 @@ namespace PepperDash.Essentials.DM
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
- case DMOutputEventIds.VideoOutEventId:
+ case DMOutputEventIds.VideoOutEventId:
{
- if (Chassis.Outputs[output].VideoOutFeedback != null)
- Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].VideoOutFeedback.Number, output);
-
- if (VideoOutputFeedbacks.ContainsKey(output))
- VideoOutputFeedbacks[output].FireUpdate();
-
+
+ var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.
+ Outputs[output].VideoOutFeedback.Number;
+
+ Debug.Console(2, this, "DMSwitchVideo:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output);
+
+ if (VideoOutputFeedbacks.ContainsKey(output))
+ {
+ var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].VideoOutFeedback);
+ var localOutputPort =
+ OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == Chassis.Outputs[output]);
+
+
+ VideoOutputFeedbacks[output].FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(output,
+ inputNumber,
+ localOutputPort,
+ localInputPort,
+ eRoutingSignalType.Video));
+ }
+
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
OutputVideoRouteNameFeedbacks[output].FireUpdate();
break;
}
- case DMOutputEventIds.AudioOutEventId:
- {
- if (Chassis.Outputs[output].AudioOutFeedback != null)
- Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, Chassis.Outputs[output].AudioOutFeedback.Number, output);
-
- if (AudioOutputFeedbacks.ContainsKey(output))
- AudioOutputFeedbacks[output].FireUpdate();
-
- if (OutputAudioRouteNameFeedbacks.ContainsKey(output))
- OutputAudioRouteNameFeedbacks[output].FireUpdate();
-
+ case DMOutputEventIds.AudioOutEventId:
+ {
+ var inputNumber = Chassis.Outputs[output].AudioOutFeedback == null ? 0 : Chassis.
+ Outputs[output].AudioOutFeedback.Number;
+
+ Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name, inputNumber, output);
+
+ if (AudioOutputFeedbacks.ContainsKey(output))
+ {
+ var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].AudioOutFeedback);
+ var localOutputPort =
+ OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == Chassis.Outputs[output]);
+
+
+ AudioOutputFeedbacks[output].FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(output,
+ inputNumber,
+ localOutputPort,
+ localInputPort,
+ eRoutingSignalType.Audio));
+ }
+
+ if (OutputAudioRouteNameFeedbacks.ContainsKey(output))
+ OutputAudioRouteNameFeedbacks[output].FireUpdate();
+
break;
}
case DMOutputEventIds.OutputNameEventId:
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs
index 051ef88e..34d1cd60 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/DmpsRoutingController.cs
@@ -18,12 +18,15 @@ using PepperDash.Essentials.DM.Config;
using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.DM
-{
- public class DmpsRoutingController : EssentialsBridgeableDevice, IRoutingNumeric, IHasFeedback
+{
+ public class DmpsRoutingController : EssentialsBridgeableDevice, IRoutingNumericWithFeedback, IHasFeedback
{
public CrestronControlSystem Dmps { get; set; }
public ISystemControl SystemControl { get; private set; }
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
// Feedbacks for EssentialDM
public Dictionary VideoOutputFeedbacks { get; private set; }
public Dictionary AudioOutputFeedbacks { get; private set; }
@@ -56,11 +59,23 @@ namespace PepperDash.Essentials.DM
///
public string NoRouteText = "";
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
+
public static DmpsRoutingController GetDmpsRoutingController(string key, string name,
DmpsRoutingPropertiesConfig properties)
{
try
{
+
ISystemControl systemControl = null;
systemControl = Global.ControlSystem.SystemControl as ISystemControl;
@@ -118,8 +133,8 @@ namespace PepperDash.Essentials.DM
OutputEndpointOnlineFeedbacks = new Dictionary();
Debug.Console(1, this, "{0} Switcher Inputs Present.", Dmps.SwitcherInputs.Count);
- Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count);
-
+ Debug.Console(1, this, "{0} Switcher Outputs Present.", Dmps.SwitcherOutputs.Count);
+
Debug.Console(1, this, "{0} Inputs in ControlSystem", Dmps.NumberOfSwitcherInputs);
Debug.Console(1, this, "{0} Outputs in ControlSystem", Dmps.NumberOfSwitcherOutputs);
@@ -140,57 +155,57 @@ namespace PepperDash.Essentials.DM
Dmps.DMOutputChange += Dmps_DMOutputChange;
return base.CustomActivate();
- }
-
- private void SetOutputNames()
- {
- if (OutputNames == null)
- {
- return;
- }
-
- foreach (var kvp in OutputNames)
- {
- var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput);
- if (output != null && output.Name.Type != eSigType.NA)
- {
- output.Name.StringValue = kvp.Value;
- }
- }
- }
-
- private void SetInputNames()
- {
- if (InputNames == null)
- {
- return;
- }
- foreach (var kvp in InputNames)
- {
- var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput);
- if (input != null && input.Name.Type != eSigType.NA)
- {
- input.Name.StringValue = kvp.Value;
- }
- }
- }
-
+ }
+
+ private void SetOutputNames()
+ {
+ if (OutputNames == null)
+ {
+ return;
+ }
+
+ foreach (var kvp in OutputNames)
+ {
+ var output = (Dmps.SwitcherOutputs[kvp.Key] as DMOutput);
+ if (output != null && output.Name.Type != eSigType.NA)
+ {
+ output.Name.StringValue = kvp.Value;
+ }
+ }
+ }
+
+ private void SetInputNames()
+ {
+ if (InputNames == null)
+ {
+ return;
+ }
+ foreach (var kvp in InputNames)
+ {
+ var input = (Dmps.SwitcherInputs[kvp.Key] as DMInput);
+ if (input != null && input.Name.Type != eSigType.NA)
+ {
+ input.Name.StringValue = kvp.Value;
+ }
+ }
+ }
+
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
- {
+ {
var joinMap = new DmpsRoutingControllerJoinMap(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.");
+ 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"));
@@ -199,203 +214,203 @@ namespace PepperDash.Essentials.DM
LinkInputsToApi(trilist, joinMap);
LinkOutputsToApi(trilist, joinMap);
- }
-
- private void LinkOutputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
- {
- for (uint i = 1; i <= Dmps.SwitcherOutputs.Count; i++)
- {
- Debug.Console(2, this, "Linking Output Card {0}", i);
-
- var ioSlot = i;
- var ioSlotJoin = ioSlot - 1;
-
- // Control
- trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin,
- o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
- trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin,
- o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
-
- trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s =>
- {
- var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput;
-
- //Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot);
-
- if (outputCard == null)
- {
- return;
- }
- //Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
-
- if (outputCard is Card.Dmps3CodecOutput || outputCard.NameFeedback == null)
- {
- return;
- }
- if (string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
- {
- return;
- }
- //Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
-
- if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
- {
- outputCard.Name.StringValue = s;
- }
- });
-
- // Feedback
- if (VideoOutputFeedbacks[ioSlot] != null)
- {
- VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
- }
- if (AudioOutputFeedbacks[ioSlot] != null)
- {
- AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
- }
- if (OutputNameFeedbacks[ioSlot] != null)
- {
- OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
- }
- if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
- {
- OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(
- trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]);
- }
- if (OutputAudioRouteNameFeedbacks[ioSlot] != null)
- {
- OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(
- trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]);
- }
- if (OutputEndpointOnlineFeedbacks[ioSlot] != null)
- {
- OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
- trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]);
- }
- }
- }
-
- private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
- {
- for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++)
- {
- Debug.Console(2, this, "Linking Input Card {0}", i);
-
- var ioSlot = i;
- var ioSlotJoin = ioSlot - 1;
-
- if (VideoInputSyncFeedbacks[ioSlot] != null)
- {
- VideoInputSyncFeedbacks[ioSlot].LinkInputSig(
- trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
- }
-
- if (InputNameFeedbacks[ioSlot] != null)
- {
- InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
- }
-
- trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s =>
- {
- var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput;
-
- if (inputCard == null)
- {
- return;
- }
-
- if (inputCard.NameFeedback == null || string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) ||
- inputCard.NameFeedback.StringValue == s)
- {
- return;
- }
-
- if (inputCard.Name != null)
- {
- inputCard.Name.StringValue = s;
- }
- });
-
-
- if (InputEndpointOnlineFeedbacks[ioSlot] != null)
- {
- InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
- trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
- }
- }
- }
-
-
+ }
+
+ private void LinkOutputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
+ {
+ for (uint i = 1; i <= Dmps.SwitcherOutputs.Count; i++)
+ {
+ Debug.Console(2, this, "Linking Output Card {0}", i);
+
+ var ioSlot = i;
+ var ioSlotJoin = ioSlot - 1;
+
+ // Control
+ trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin,
+ o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video));
+ trilist.SetUShortSigAction(joinMap.OutputAudio.JoinNumber + ioSlotJoin,
+ o => ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio));
+
+ trilist.SetStringSigAction(joinMap.OutputNames.JoinNumber + ioSlotJoin, s =>
+ {
+ var outputCard = Dmps.SwitcherOutputs[ioSlot] as DMOutput;
+
+ //Debug.Console(2, dmpsRouter, "Output Name String Sig Action for Output Card {0}", ioSlot);
+
+ if (outputCard == null)
+ {
+ return;
+ }
+ //Debug.Console(2, dmpsRouter, "Card Type: {0}", outputCard.CardInputOutputType);
+
+ if (outputCard is Card.Dmps3CodecOutput || outputCard.NameFeedback == null)
+ {
+ return;
+ }
+ if (string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
+ {
+ return;
+ }
+ //Debug.Console(2, dmpsRouter, "NameFeedabck: {0}", outputCard.NameFeedback.StringValue);
+
+ if (outputCard.NameFeedback.StringValue != s && outputCard.Name != null)
+ {
+ outputCard.Name.StringValue = s;
+ }
+ });
+
+ // Feedback
+ if (VideoOutputFeedbacks[ioSlot] != null)
+ {
+ VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo.JoinNumber + ioSlotJoin]);
+ }
+ if (AudioOutputFeedbacks[ioSlot] != null)
+ {
+ AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio.JoinNumber + ioSlotJoin]);
+ }
+ if (OutputNameFeedbacks[ioSlot] != null)
+ {
+ OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
+ }
+ if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
+ {
+ OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(
+ trilist.StringInput[joinMap.OutputCurrentVideoInputNames.JoinNumber + ioSlotJoin]);
+ }
+ if (OutputAudioRouteNameFeedbacks[ioSlot] != null)
+ {
+ OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(
+ trilist.StringInput[joinMap.OutputCurrentAudioInputNames.JoinNumber + ioSlotJoin]);
+ }
+ if (OutputEndpointOnlineFeedbacks[ioSlot] != null)
+ {
+ OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
+ trilist.BooleanInput[joinMap.OutputEndpointOnline.JoinNumber + ioSlotJoin]);
+ }
+ }
+ }
+
+ private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
+ {
+ for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++)
+ {
+ Debug.Console(2, this, "Linking Input Card {0}", i);
+
+ var ioSlot = i;
+ var ioSlotJoin = ioSlot - 1;
+
+ if (VideoInputSyncFeedbacks[ioSlot] != null)
+ {
+ VideoInputSyncFeedbacks[ioSlot].LinkInputSig(
+ trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
+ }
+
+ if (InputNameFeedbacks[ioSlot] != null)
+ {
+ InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
+ }
+
+ trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s =>
+ {
+ var inputCard = Dmps.SwitcherInputs[ioSlot] as DMInput;
+
+ if (inputCard == null)
+ {
+ return;
+ }
+
+ if (inputCard.NameFeedback == null || string.IsNullOrEmpty(inputCard.NameFeedback.StringValue) ||
+ inputCard.NameFeedback.StringValue == s)
+ {
+ return;
+ }
+
+ if (inputCard.Name != null)
+ {
+ inputCard.Name.StringValue = s;
+ }
+ });
+
+
+ if (InputEndpointOnlineFeedbacks[ioSlot] != null)
+ {
+ InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
+ trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
+ }
+ }
+ }
+
+
///
/// Iterate the SwitcherOutputs collection to setup feedbacks and add routing ports
///
void SetupOutputCards()
{
- foreach (var card in Dmps.SwitcherOutputs)
- {
+ foreach (var card in Dmps.SwitcherOutputs)
+ {
Debug.Console(1, this, "Output Card Type: {0}", card.CardInputOutputType);
- var outputCard = card as DMOutput;
-
- if (outputCard == null)
- {
- Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType);
- continue;
- }
-
+ var outputCard = card as DMOutput;
+
+ if (outputCard == null)
+ {
+ Debug.Console(1, this, "Output card {0} is not a DMOutput", card.CardInputOutputType);
+ continue;
+ }
+
Debug.Console(1, this, "Adding Output Card Number {0} Type: {1}", outputCard.Number, outputCard.CardInputOutputType.ToString());
VideoOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
{
- if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
- return 0;
+ if (outputCard.VideoOutFeedback != null) { return (ushort)outputCard.VideoOutFeedback.Number; }
+ return 0;
;
});
AudioOutputFeedbacks[outputCard.Number] = new IntFeedback(() =>
- {
- try
- {
- if (outputCard.AudioOutFeedback != null)
- {
- return (ushort) outputCard.AudioOutFeedback.Number;
- }
- return 0;
- }
- catch (NotSupportedException)
- {
- return (ushort) outputCard.AudioOutSourceFeedback;
- }
+ {
+ try
+ {
+ if (outputCard.AudioOutFeedback != null)
+ {
+ return (ushort) outputCard.AudioOutFeedback.Number;
+ }
+ return 0;
+ }
+ catch (NotSupportedException)
+ {
+ return (ushort) outputCard.AudioOutSourceFeedback;
+ }
});
- OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
- {
+ OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
+ {
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
return outputCard.NameFeedback.StringValue;
- }
- return "";
+ }
+ return "";
});
- OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
- {
+ OutputVideoRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
+ {
if (outputCard.VideoOutFeedback != null && outputCard.VideoOutFeedback.NameFeedback != null)
{
return outputCard.VideoOutFeedback.NameFeedback.StringValue;
- }
- return NoRouteText;
+ }
+ return NoRouteText;
});
- OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
- {
+ OutputAudioRouteNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
+ {
if (outputCard.AudioOutFeedback != null && outputCard.AudioOutFeedback.NameFeedback != null)
{
return outputCard.AudioOutFeedback.NameFeedback.StringValue;
- }
- return NoRouteText;
+ }
+ return NoRouteText;
});
OutputEndpointOnlineFeedbacks[outputCard.Number] = new BoolFeedback(() => outputCard.EndpointOnlineFeedback);
- AddOutputCard(outputCard.Number, outputCard);
+ AddOutputCard(outputCard.Number, outputCard);
}
}
@@ -513,11 +528,16 @@ namespace PepperDash.Essentials.DM
///
/// Adds InputPort
///
- void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType)
+ private void AddInputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType,
+ eRoutingPortConnectionType portType)
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
- var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
+ var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
+ {
+ FeedbackMatchObject = Dmps.SwitcherInputs[cardNum]
+ };
+ ;
InputPorts.Add(inputPort);
}
@@ -529,7 +549,11 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("inputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding input port '{0}'", portKey);
- var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this);
+ var inputPort = new RoutingInputPort(portKey, sigType, portType, cardNum, this)
+ {
+ FeedbackMatchObject = Dmps.SwitcherInputs[cardNum]
+ };
+ ;
if (cecPort != null)
inputPort.Port = cecPort;
@@ -537,6 +561,7 @@ namespace PepperDash.Essentials.DM
InputPorts.Add(inputPort);
}
+
///
/// Builds the appropriate ports and calls the appropriate add port method
///
@@ -550,23 +575,23 @@ namespace PepperDash.Essentials.DM
var cecPort = hdmiOutputCard.HdmiOutputPort;
- AddHdmiOutputPort(number, cecPort);
+ AddHdmiOutputPort(number, cecPort);
}
- else if (outputCard is Card.Dmps3HdmiOutputBackend)
- {
- var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend;
-
- var cecPort = hdmiOutputCard.HdmiOutputPort;
-
- AddHdmiOutputPort(number, cecPort);
+ else if (outputCard is Card.Dmps3HdmiOutputBackend)
+ {
+ var hdmiOutputCard = outputCard as Card.Dmps3HdmiOutputBackend;
+
+ var cecPort = hdmiOutputCard.HdmiOutputPort;
+
+ AddHdmiOutputPort(number, cecPort);
}
else if (outputCard is Card.Dmps3DmOutput)
- {
- AddDmOutputPort(number);
+ {
+ AddDmOutputPort(number);
}
- else if (outputCard is Card.Dmps3DmOutputBackend)
- {
- AddDmOutputPort(number);
+ else if (outputCard is Card.Dmps3DmOutputBackend)
+ {
+ AddDmOutputPort(number);
}
else if (outputCard is Card.Dmps3ProgramOutput)
{
@@ -574,51 +599,51 @@ namespace PepperDash.Essentials.DM
var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
- DeviceManager.AddDevice(programOutput);
+ DeviceManager.AddDevice(programOutput);
}
- else if (outputCard is Card.Dmps3AuxOutput)
- {
- switch (outputCard.CardInputOutputType)
- {
- case eCardInputOutputType.Dmps3Aux1Output:
+ else if (outputCard is Card.Dmps3AuxOutput)
+ {
+ switch (outputCard.CardInputOutputType)
+ {
+ case eCardInputOutputType.Dmps3Aux1Output:
{
AddAudioOnlyOutputPort(number, "Aux1");
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(aux1Output);
- }
- break;
- case eCardInputOutputType.Dmps3Aux2Output:
+ }
+ break;
+ case eCardInputOutputType.Dmps3Aux2Output:
{
AddAudioOnlyOutputPort(number, "Aux2");
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase);
DeviceManager.AddDevice(aux2Output);
- }
- break;
- }
- }
- else if (outputCard is Card.Dmps3CodecOutput)
- {
- switch (number)
- {
- case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1:
- case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1:
- case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1:
- AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString());
- break;
- case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2:
- case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2:
- case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2:
- AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString());
- break;
- }
- }
+ }
+ break;
+ }
+ }
+ else if (outputCard is Card.Dmps3CodecOutput)
+ {
+ switch (number)
+ {
+ case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec1:
+ case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec1:
+ case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec1:
+ AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec1.ToString());
+ break;
+ case (uint)CrestronControlSystem.eDmps34K350COutputs.Codec2:
+ case (uint)CrestronControlSystem.eDmps34K250COutputs.Codec2:
+ case (uint)CrestronControlSystem.eDmps3300cAecOutputs.Codec2:
+ AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps300cOutputs.Codec2.ToString());
+ break;
+ }
+ }
else if (outputCard is Card.Dmps3DialerOutput)
{
- AddAudioOnlyOutputPort(number, "Dialer");
+ AddAudioOnlyOutputPort(number, "Dialer");
}
else if (outputCard is Card.Dmps3DigitalMixOutput)
{
@@ -629,11 +654,11 @@ namespace PepperDash.Essentials.DM
if (number == (uint)CrestronControlSystem.eDmps34K250COutputs.Mix2
|| number == (uint)CrestronControlSystem.eDmps34K300COutputs.Mix2
|| number == (uint)CrestronControlSystem.eDmps34K350COutputs.Mix2)
- AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
+ AddAudioOnlyOutputPort(number, CrestronControlSystem.eDmps34K250COutputs.Mix2.ToString());
}
else if (outputCard is Card.Dmps3AecOutput)
{
- AddAudioOnlyOutputPort(number, "Aec");
+ AddAudioOnlyOutputPort(number, "Aec");
}
else
{
@@ -676,7 +701,10 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("outputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
- OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this));
+ OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)
+ {
+ FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum]
+ });
}
///
@@ -686,7 +714,10 @@ namespace PepperDash.Essentials.DM
{
var portKey = string.Format("outputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
- var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this);
+ var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this)
+ {
+ FeedbackMatchObject = Dmps.SwitcherOutputs[cardNum]
+ };
if (cecPort != null)
outputPort.Port = cecPort;
@@ -762,31 +793,31 @@ namespace PepperDash.Essentials.DM
}
}
else if (args.EventId == DMOutputEventIds.AudioOutEventId)
- {
- try
- {
- if (outputCard != null && outputCard.AudioOutFeedback != null)
- {
- Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name,
- outputCard.AudioOutFeedback.Number, output);
- }
- if (AudioOutputFeedbacks.ContainsKey(output))
- {
- AudioOutputFeedbacks[output].FireUpdate();
- }
- }
- catch (NotSupportedException)
- {
- if (outputCard != null)
- {
- Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name,
- outputCard.AudioOutSourceFeedback, output);
- }
- if (AudioOutputFeedbacks.ContainsKey(output))
- {
- AudioOutputFeedbacks[output].FireUpdate();
- }
- }
+ {
+ try
+ {
+ if (outputCard != null && outputCard.AudioOutFeedback != null)
+ {
+ Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", this.Name,
+ outputCard.AudioOutFeedback.Number, output);
+ }
+ if (AudioOutputFeedbacks.ContainsKey(output))
+ {
+ AudioOutputFeedbacks[output].FireUpdate();
+ }
+ }
+ catch (NotSupportedException)
+ {
+ if (outputCard != null)
+ {
+ Debug.Console(2, this, "DMSwitchAudio:{0} Routed Input:{1} Output:{2}'", Name,
+ outputCard.AudioOutSourceFeedback, output);
+ }
+ if (AudioOutputFeedbacks.ContainsKey(output))
+ {
+ AudioOutputFeedbacks[output].FireUpdate();
+ }
+ }
}
else if (args.EventId == DMOutputEventIds.OutputNameEventId
&& OutputNameFeedbacks.ContainsKey(output))
@@ -818,94 +849,94 @@ namespace PepperDash.Essentials.DM
Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType);
var input = Convert.ToUInt32(inputSelector); // Cast can sometimes fail
- var output = Convert.ToUInt32(outputSelector);
-
- var sigTypeIsUsbOrVideo = ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) ||
- ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) ||
- ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput);
-
- if ((input <= Dmps.NumberOfSwitcherInputs && output <= Dmps.NumberOfSwitcherOutputs &&
- sigTypeIsUsbOrVideo) ||
- (input <= Dmps.NumberOfSwitcherInputs + 5 && output <= Dmps.NumberOfSwitcherOutputs &&
- (sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
- {
- // Check to see if there's an off timer waiting on this and if so, cancel
- var key = new PortNumberType(output, sigType);
- if (input == 0)
- {
- StartOffTimer(key);
- }
- else if (key.Number > 0)
- {
- if (RouteOffTimers.ContainsKey(key))
- {
- Debug.Console(2, this, "{0} cancelling route off due to new source", output);
- RouteOffTimers[key].Stop();
- RouteOffTimers.Remove(key);
- }
- }
-
-
- DMOutput dmOutputCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput;
-
- //if (inCard != null)
- //{
- // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES
- if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
- {
- DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
- //SystemControl.VideoEnter.BoolValue = true;
- if (dmOutputCard != null)
- dmOutputCard.VideoOut = dmInputCard;
- }
-
- if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
- {
- DMInput dmInputCard = null;
- if (input <= Dmps.NumberOfSwitcherInputs)
- {
- dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
- }
-
- if (dmOutputCard != null)
- try
- {
- dmOutputCard.AudioOut = dmInputCard;
- }
- catch (NotSupportedException)
- {
- Debug.Console(1, this, "Routing input {0} audio to output {1}",
- (eDmps34KAudioOutSource) input, (CrestronControlSystem.eDmps34K350COutputs) output);
-
- dmOutputCard.AudioOutSource = (eDmps34KAudioOutSource) input;
- }
- }
-
- if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
- {
- DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
- if (dmOutputCard != null)
- dmOutputCard.USBRoutedTo = dmInputCard;
- }
-
- if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
- {
- DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
- if (dmInputCard != null)
- dmInputCard.USBRoutedTo = dmOutputCard;
- }
- //}
- //else
- //{
- // Debug.Console(1, this, "Unable to execute route from input {0} to output {1}. Input card not available", inputSelector, outputSelector);
- //}
-
- }
- else
- {
- Debug.Console(1, this, "Unable to execute route from input {0} to output {1}", inputSelector,
- outputSelector);
- }
+ var output = Convert.ToUInt32(outputSelector);
+
+ var sigTypeIsUsbOrVideo = ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) ||
+ ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput) ||
+ ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput);
+
+ if ((input <= Dmps.NumberOfSwitcherInputs && output <= Dmps.NumberOfSwitcherOutputs &&
+ sigTypeIsUsbOrVideo) ||
+ (input <= Dmps.NumberOfSwitcherInputs + 5 && output <= Dmps.NumberOfSwitcherOutputs &&
+ (sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio))
+ {
+ // Check to see if there's an off timer waiting on this and if so, cancel
+ var key = new PortNumberType(output, sigType);
+ if (input == 0)
+ {
+ StartOffTimer(key);
+ }
+ else if (key.Number > 0)
+ {
+ if (RouteOffTimers.ContainsKey(key))
+ {
+ Debug.Console(2, this, "{0} cancelling route off due to new source", output);
+ RouteOffTimers[key].Stop();
+ RouteOffTimers.Remove(key);
+ }
+ }
+
+
+ DMOutput dmOutputCard = output == 0 ? null : Dmps.SwitcherOutputs[output] as DMOutput;
+
+ //if (inCard != null)
+ //{
+ // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES
+ if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
+ {
+ DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
+ //SystemControl.VideoEnter.BoolValue = true;
+ if (dmOutputCard != null)
+ dmOutputCard.VideoOut = dmInputCard;
+ }
+
+ if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
+ {
+ DMInput dmInputCard = null;
+ if (input <= Dmps.NumberOfSwitcherInputs)
+ {
+ dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
+ }
+
+ if (dmOutputCard != null)
+ try
+ {
+ dmOutputCard.AudioOut = dmInputCard;
+ }
+ catch (NotSupportedException)
+ {
+ Debug.Console(1, this, "Routing input {0} audio to output {1}",
+ (eDmps34KAudioOutSource) input, (CrestronControlSystem.eDmps34K350COutputs) output);
+
+ dmOutputCard.AudioOutSource = (eDmps34KAudioOutSource) input;
+ }
+ }
+
+ if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
+ {
+ DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
+ if (dmOutputCard != null)
+ dmOutputCard.USBRoutedTo = dmInputCard;
+ }
+
+ if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
+ {
+ DMInput dmInputCard = input == 0 ? null : Dmps.SwitcherInputs[input] as DMInput;
+ if (dmInputCard != null)
+ dmInputCard.USBRoutedTo = dmOutputCard;
+ }
+ //}
+ //else
+ //{
+ // Debug.Console(1, this, "Unable to execute route from input {0} to output {1}. Input card not available", inputSelector, outputSelector);
+ //}
+
+ }
+ else
+ {
+ Debug.Console(1, this, "Unable to execute route from input {0} to output {1}", inputSelector,
+ outputSelector);
+ }
}
catch (Exception e)
{
@@ -913,15 +944,15 @@ namespace PepperDash.Essentials.DM
}
}
- #endregion
-
- #region IRoutingNumeric Members
-
- public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType)
- {
- ExecuteSwitch(inputSelector, outputSelector, sigType);
- }
-
- #endregion
+ #endregion
+
+ #region IRoutingNumeric Members
+
+ public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType sigType)
+ {
+ ExecuteSwitch(inputSelector, outputSelector, sigType);
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs
index 1e33069a..b766ac3c 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEBridgeableController.cs
@@ -16,11 +16,14 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.Chassis
{
[Description("Wrapper class for all HdMdNxM4E switchers")]
- public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingInputsOutputs, IRoutingNumeric, IHasFeedback
+ public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{
private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1;
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
public Dictionary InputNames { get; set; }
public Dictionary OutputNames { get; set; }
@@ -70,26 +73,34 @@ namespace PepperDash.Essentials.DM.Chassis
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
- var inputName = InputNames[i];
- _Chassis.Inputs[i].Name.StringValue = inputName;
+ var index = i;
+ var inputName = InputNames[index];
+ _Chassis.Inputs[index].Name.StringValue = inputName;
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.Hdmi, i, this));
- VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[i].VideoDetectedFeedback.BoolValue));
- InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[i].Name.StringValue));
- InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[i].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
+ eRoutingPortConnectionType.Hdmi, index, this)
+ {
+ FeedbackMatchObject = _Chassis.HdmiInputs[index]
+ });
+ VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue));
+ InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue));
+ InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
- var outputName = OutputNames[i];
+ var index = i;
+ var outputName = OutputNames[index];
_Chassis.Outputs[i].Name.StringValue = outputName;
OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.Hdmi, i, this));
- VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[i].VideoOutFeedback.Number));
- OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[i].Name.StringValue));
- OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[i].VideoOutFeedback.NameFeedback.StringValue));
+ eRoutingPortConnectionType.Hdmi, index, this)
+ {
+ FeedbackMatchObject = _Chassis.HdmiOutputs[index]
+ });
+ VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number));
+ OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue));
+ OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
_Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange);
@@ -102,6 +113,16 @@ namespace PepperDash.Essentials.DM.Chassis
#region Methods
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
public void EnableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
@@ -328,44 +349,45 @@ namespace PepperDash.Essentials.DM.Chassis
void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args)
{
- if (args.DeviceOnLine)
+ if (!args.DeviceOnLine) return;
+ for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
- for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
- {
- _Chassis.Inputs[i].Name.StringValue = InputNames[i];
- }
- for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
- {
- _Chassis.Outputs[i].Name.StringValue = OutputNames[i];
- }
-
- foreach (var feedback in Feedbacks)
- {
- feedback.FireUpdate();
- }
+ _Chassis.Inputs[i].Name.StringValue = InputNames[i];
+ }
+ for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
+ {
+ _Chassis.Outputs[i].Name.StringValue = OutputNames[i];
+ }
+
+ foreach (var feedback in Feedbacks)
+ {
+ feedback.FireUpdate();
}
-
}
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
- if (args.EventId == DMOutputEventIds.VideoOutEventId)
+ if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
+
+ for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++)
{
- foreach (var item in VideoOutputRouteFeedbacks)
- {
- item.FireUpdate();
- }
+ var index = i;
+ var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback);
+ var localOutputPort =
+ OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]);
+
+
+ VideoOutputRouteFeedbacks[i].FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo));
}
}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
- if (args.EventId == DMInputEventIds.VideoDetectedEventId)
+ if (args.EventId != DMInputEventIds.VideoDetectedEventId) return;
+ foreach (var item in VideoInputSyncFeedbacks)
{
- foreach (var item in VideoInputSyncFeedbacks)
- {
- item.FireUpdate();
- }
+ item.FireUpdate();
}
}
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/DGEs/Dge100Controller.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/DGEs/Dge100Controller.cs
index dd07f696..d7996554 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/DGEs/Dge100Controller.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/DGEs/Dge100Controller.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
+using System.Linq;
+using System.Net.Sockets;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
@@ -14,15 +15,19 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
-using Crestron.SimplSharpPro.DeviceSupport;
-
+using Crestron.SimplSharpPro.DeviceSupport;
+using PepperDash.Essentials.Core.DeviceInfo;
+
namespace PepperDash.Essentials.DM.Endpoints.DGEs
{
[Description("Wrapper class for DGE-100")]
- public class Dge100Controller : CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IHasBasicTriListWithSmartObject, ICec
+ public class Dge100Controller : CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IHasBasicTriListWithSmartObject, ICec, IDeviceInfoProvider
{
+ private const int CtpPort = 41795;
private readonly Dge100 _dge;
+ private readonly TsxCcsUcCodec100EthernetReservedSigs _dgeEthernetInfo;
+
public BasicTriListWithSmartObject Panel { get { return _dge; } }
private DeviceConfig _dc;
@@ -32,7 +37,14 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs
public Dge100Controller(string key, string name, Dge100 device, DeviceConfig dc, CrestronTouchpanelPropertiesConfig props)
:base(key, name, device)
{
- _dge = device;
+ _dge = device;
+ _dgeEthernetInfo = _dge.ExtenderEthernetReservedSigs;
+ _dgeEthernetInfo.DeviceExtenderSigChange += (extender, args) => UpdateDeviceInfo();
+ _dgeEthernetInfo.Use();
+
+ DeviceInfo = new DeviceInfo();
+
+ _dge.OnlineStatusChange += (currentDevice, args) => { if (args.DeviceOnLine) UpdateDeviceInfo(); };
_dc = dc;
@@ -69,8 +81,86 @@ namespace PepperDash.Essentials.DM.Endpoints.DGEs
#region ICec Members
public Cec StreamCec { get { return _dge.HdmiOut.StreamCec; } }
- #endregion
-
+ #endregion
+
+ #region Implementation of IDeviceInfoProvider
+
+ public DeviceInfo DeviceInfo { get; private set; }
+
+ public event DeviceInfoChangeHandler DeviceInfoChanged;
+
+ public void UpdateDeviceInfo()
+ {
+ DeviceInfo.IpAddress = _dgeEthernetInfo.IpAddressFeedback.StringValue;
+ DeviceInfo.MacAddress = _dgeEthernetInfo.MacAddressFeedback.StringValue;
+
+ GetFirmwareAndSerialInfo();
+
+ OnDeviceInfoChange();
+ }
+
+ private void GetFirmwareAndSerialInfo()
+ {
+ if (String.IsNullOrEmpty(_dgeEthernetInfo.IpAddressFeedback.StringValue))
+ {
+ Debug.Console(1, this, "IP Address information not yet received. No device is online");
+ return;
+ }
+
+ var tcpClient = new GenericTcpIpClient("", _dgeEthernetInfo.IpAddressFeedback.StringValue, CtpPort, 1024){AutoReconnect = false};
+
+ var gather = new CommunicationGather(tcpClient, "\r\n\r\n");
+
+ tcpClient.ConnectionChange += (sender, args) =>
+ {
+ if (!args.Client.IsConnected)
+ {
+ return;
+ }
+
+ args.Client.SendText("ver\r\n");
+ };
+
+ gather.LineReceived += (sender, args) =>
+ {
+ if (args.Text.ToLower().Contains("host"))
+ {
+ DeviceInfo.HostName = args.Text.Split(';')[1].Trim();
+
+ tcpClient.Disconnect();
+ return;
+ }
+
+ //ignore console prompt
+ if (args.Text.ToLower().Contains(">"))
+ {
+ return;
+ }
+
+ if (!args.Text.ToLower().Contains("dge"))
+ {
+ return;
+ }
+
+ DeviceInfo.SerialNumber = args.Text.Split('[')[1].Split(' ')[4].Replace("#", "");
+ DeviceInfo.FirmwareVersion = args.Text.Split('[')[1].Split(' ')[1];
+
+ tcpClient.SendText("host\r\n");
+ };
+
+ tcpClient.Connect();
+ }
+
+ private void OnDeviceInfoChange()
+ {
+ var handler = DeviceInfoChanged;
+
+ if (handler == null) return;
+
+ handler(this, new DeviceInfoEventArgs(DeviceInfo));
+ }
+
+ #endregion
}
public class Dge100ControllerFactory : EssentialsDeviceFactory
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs
index f0238936..21663e78 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4kZScalerCController.cs
@@ -13,7 +13,7 @@ using PepperDash.Core;
namespace PepperDash.Essentials.DM
{
[Description("Wrapper Class for DM-RMC-4K-Z-SCALER-C")]
- public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRouting,
+ public class DmRmc4kZScalerCController : DmRmcControllerBase, IRmcRoutingWithFeedback,
IIROutputPorts, IComPorts, ICec
{
private readonly DmRmc4kzScalerC _rmc;
@@ -31,14 +31,34 @@ namespace PepperDash.Essentials.DM
public RoutingPortCollection OutputPorts { get; private set; }
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ 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);
+ eRoutingPortConnectionType.DmCat, 0, this)
+ {
+ FeedbackMatchObject = 1
+ };
HdmiIn = new RoutingInputPort(DmPortName.HdmiIn, eRoutingSignalType.AudioVideo,
- eRoutingPortConnectionType.Hdmi, 0, this);
+ eRoutingPortConnectionType.Hdmi, 0, this)
+ {
+ FeedbackMatchObject = 2
+ };
HdmiOut = new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, null, this);
@@ -55,12 +75,20 @@ namespace PepperDash.Essentials.DM
_rmc.HdmiOutput.OutputStreamChange += HdmiOutput_OutputStreamChange;
_rmc.HdmiOutput.ConnectedDevice.DeviceInformationChange += ConnectedDevice_DeviceInformationChange;
+ _rmc.OnlineStatusChange += _rmc_OnlineStatusChange;
+
// Set Ports for CEC
HdmiOut.Port = _rmc.HdmiOutput;
AudioVideoSourceNumericFeedback = new IntFeedback(() => (ushort)(_rmc.SelectedSourceFeedback));
}
+ private void _rmc_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ AudioVideoSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioVideoSourceNumericFeedback.UShortValue, eRoutingSignalType.AudioVideo));
+ }
+
void HdmiOutput_OutputStreamChange(EndpointOutputStream outputStream, EndpointOutputStreamEventArgs args)
{
if (args.EventId == EndpointOutputStreamEventIds.HorizontalResolutionFeedbackEventId || args.EventId == EndpointOutputStreamEventIds.VerticalResolutionFeedbackEventId ||
@@ -71,7 +99,12 @@ namespace PepperDash.Essentials.DM
if (args.EventId == EndpointOutputStreamEventIds.SelectedSourceFeedbackEventId)
{
+ var localInputPort =
+ InputPorts.FirstOrDefault(p => (int)p.FeedbackMatchObject == AudioVideoSourceNumericFeedback.UShortValue);
+
+
AudioVideoSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioVideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputPort, eRoutingSignalType.AudioVideo));
}
}
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs
index 7cc913e2..83c386bc 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs
@@ -8,14 +8,16 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
+using PepperDash.Essentials.Core.DeviceInfo;
using PepperDash.Essentials.DM.Config;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM
{
[Description("Wrapper class for all DM-RMC variants")]
- public abstract class DmRmcControllerBase : CrestronGenericBridgeableBaseDevice
+ 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.
public StringFeedback VideoOutputResolutionFeedback { get; protected set; }
@@ -32,6 +34,10 @@ namespace PepperDash.Essentials.DM
PreventRegistration = _rmc.DMOutput != null;
AddToFeedbackList(VideoOutputResolutionFeedback, EdidManufacturerFeedback, EdidSerialNumberFeedback, EdidNameFeedback, EdidPreferredTimingFeedback);
+
+ DeviceInfo = new DeviceInfo();
+
+ _rmc.OnlineStatusChange += (currentDevice, args) => { if (args.DeviceOnLine) UpdateDeviceInfo(); };
}
protected void LinkDmRmcToApi(DmRmcControllerBase rmc, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
@@ -79,7 +85,106 @@ namespace PepperDash.Essentials.DM
trilist.SetUShortSigAction(joinMap.AudioVideoSource.JoinNumber, a => routing.ExecuteNumericSwitch(a, 1, eRoutingSignalType.AudioVideo));
}
- }
+
+ #region Implementation of IDeviceInfoProvider
+
+ public DeviceInfo DeviceInfo { get; private set; }
+ public event DeviceInfoChangeHandler DeviceInfoChanged;
+
+ public void UpdateDeviceInfo()
+ {
+ Debug.Console(1, this, "Updating Device Info");
+
+ if (_rmc.ConnectedIpList.Count == 0)
+ {
+ Debug.Console(1, this, "IP Address information not yet received. No device is online");
+ return;
+ }
+
+ DeviceInfo.IpAddress = _rmc.ConnectedIpList[0].DeviceIpAddress;
+
+ foreach (var ip in _rmc.ConnectedIpList)
+ {
+ Debug.Console(0, this, "Connected IP Address: {0}", ip.DeviceIpAddress);
+ }
+
+ GetFirmwareAndSerialInfo();
+
+ OnDeviceInfoChange();
+ }
+
+ private void GetFirmwareAndSerialInfo()
+ {
+ var tcpClient = new GenericTcpIpClient(String.Format("{0}-devInfoSocket", Key), _rmc.ConnectedIpList[0].DeviceIpAddress, CtpPort, 1024)
+ {
+ AutoReconnect = false,
+ };
+
+ var gather = new CommunicationGather(tcpClient, "\r\n\r\n");
+
+ tcpClient.ConnectionChange += (sender, args) =>
+ {
+ if (!args.Client.IsConnected)
+ {
+ OnDeviceInfoChange();
+ return;
+ }
+
+ args.Client.SendText("ver\r\n");
+ };
+
+ gather.LineReceived += (sender, args) =>
+ {
+ //ignore console prompt
+ if (args.Text.ToLower().Contains(">"))
+ {
+ return;
+ }
+
+
+ if (args.Text.ToLower().Contains("host"))
+ {
+ DeviceInfo.HostName = args.Text.Split(':')[1].Trim();
+
+ tcpClient.SendText("maca\r\n");
+
+ return;
+ }
+
+ if (args.Text.ToLower().Contains("mac"))
+ {
+ DeviceInfo.MacAddress = args.Text.Split(':')[1].Trim().Replace(" ", ":");
+
+ tcpClient.Disconnect();
+
+ return;
+ }
+
+ if (!args.Text.ToLower().Contains("rmc"))
+ {
+ return;
+ }
+
+ DeviceInfo.SerialNumber = args.Text.Split('[')[1].Split(' ')[4].Replace("#", "");
+ DeviceInfo.FirmwareVersion = args.Text.Split('[')[1].Split(' ')[1];
+
+ tcpClient.SendText("host\r\n");
+ };
+
+ tcpClient.Connect();
+ }
+
+ private void OnDeviceInfoChange()
+ {
+ var handler = DeviceInfoChanged;
+
+ if (handler == null) return;
+
+ handler(this, new DeviceInfoEventArgs(DeviceInfo));
+ }
+
+ #endregion
+ }
public abstract class DmHdBaseTControllerBase : CrestronGenericBaseDevice
{
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs
index fd0cf2c1..c638ecb6 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx200Controller.cs
@@ -1,4 +1,5 @@
-using System;
+using System;
+using System.Linq;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
@@ -17,7 +18,7 @@ namespace PepperDash.Essentials.DM
/// Controller class for all DM-TX-201C/S/F transmitters
///
[Description("Wrapper class for DM-TX-200-C")]
- public class DmTx200Controller : DmTxControllerBase, ITxRouting, IHasFreeRun, IVgaBrightnessContrastControls
+ public class DmTx200Controller : DmTxControllerBase, ITxRoutingWithFeedback, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx200C2G Tx { get; private set; }
@@ -35,7 +36,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
- public IntFeedback VgaContrastFeedback { get; protected set; }
+ public IntFeedback VgaContrastFeedback { get; protected set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
///
/// Helps get the "real" inputs, including when in Auto
@@ -85,14 +100,22 @@ namespace PepperDash.Essentials.DM
public DmTx200Controller(string key, string name, DmTx200C2G tx)
: base(key, name, tx)
{
- Tx = tx;
-
- HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, DmTx200Base.eSourceSelection.Digital, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
- VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
- eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
- VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
+ Tx = tx;
+
+ HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
+ eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi,
+ DmTx200Base.eSourceSelection.Digital, this,
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
+ {
+ FeedbackMatchObject = DmTx200Base.eSourceSelection.Digital
+ };
+
+ VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
+ eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
+ VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
+ {
+ FeedbackMatchObject = DmTx200Base.eSourceSelection.Analog
+ };
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -195,12 +218,19 @@ namespace PepperDash.Essentials.DM
}
}
- void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
- {
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection) p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection) p.Selector == Tx.AudioSourceFeedback);
+
+
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
- AudioSourceNumericFeedback.FireUpdate();
-
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
}
public override bool CustomActivate()
@@ -303,14 +333,18 @@ namespace PepperDash.Essentials.DM
switch (id)
{
- case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
- ActiveVideoInputFeedback.FireUpdate();
+ ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
- case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
- AudioSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
}
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs
index a8fd2b46..623391dc 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201CController.cs
@@ -4,6 +4,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
+using System.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -14,8 +15,8 @@ namespace PepperDash.Essentials.DM
///
/// Controller class for all DM-TX-201C/S/F transmitters
///
- [Description("Wrapper class for DM-TX-201-C")]
- public class DmTx201CController : DmTxControllerBase, ITxRouting, IHasFreeRun, IVgaBrightnessContrastControls
+ [Description("Wrapper class for DM-TX-201-C")]
+ public class DmTx201CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx201C Tx { get; private set; }
@@ -34,7 +35,20 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
- public IntFeedback VgaContrastFeedback { get; protected set; }
+ public IntFeedback VgaContrastFeedback { get; protected set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
///
/// Helps get the "real" inputs, including when in Auto
@@ -89,14 +103,22 @@ namespace PepperDash.Essentials.DM
public DmTx201CController(string key, string name, DmTx201C tx)
: base(key, name, tx)
{
- Tx = tx;
-
- HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, DmTx200Base.eSourceSelection.Digital, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
- VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
- eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
- VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
+ Tx = tx;
+
+ HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
+ eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi,
+ DmTx200Base.eSourceSelection.Digital, this,
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
+ {
+ FeedbackMatchObject = DmTx200Base.eSourceSelection.Digital
+ };
+
+ VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
+ eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
+ VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
+ {
+ FeedbackMatchObject = DmTx200Base.eSourceSelection.Analog
+ };
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -190,16 +212,23 @@ namespace PepperDash.Essentials.DM
VgaContrastFeedback.FireUpdate();
break;
}
- }
-
- void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
- {
- ActiveVideoInputFeedback.FireUpdate();
- VideoSourceNumericFeedback.FireUpdate();
- AudioSourceNumericFeedback.FireUpdate();
-
}
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
+
+
+ ActiveVideoInputFeedback.FireUpdate();
+ VideoSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
+
private void VgaInputOnInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
switch (args.EventId)
@@ -312,23 +341,26 @@ namespace PepperDash.Essentials.DM
}
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
- {
- var id = args.EventId;
+ {
+ var id = args.EventId;
Debug.Console(2, this, "EventId {0}", args.EventId);
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
- ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
- ActiveVideoInputFeedback.FireUpdate();
+ ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
- }
+ }
}
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs
index 3b6ff16b..7c4b0d34 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx201SController.cs
@@ -4,6 +4,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using Crestron.SimplSharpPro.DM.Endpoints;
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
+using System.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -15,7 +16,7 @@ namespace PepperDash.Essentials.DM
/// Controller class for all DM-TX-201S/F transmitters
///
[Description("Wrapper class for DM-TX-201-S/F")]
- public class DmTx201SController : DmTxControllerBase, ITxRouting, IHasFreeRun, IVgaBrightnessContrastControls
+ public class DmTx201SController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx201S Tx { get; private set; }
@@ -36,6 +37,21 @@ namespace PepperDash.Essentials.DM
public IntFeedback VgaBrightnessFeedback { get; protected set; }
public IntFeedback VgaContrastFeedback { get; protected set; }
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
+
///
/// Helps get the "real" inputs, including when in Auto
///
@@ -92,11 +108,19 @@ namespace PepperDash.Essentials.DM
Tx = tx;
HdmiInput = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, DmTx200Base.eSourceSelection.Digital, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
+ eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi,
+ DmTx200Base.eSourceSelection.Digital, this,
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
+ {
+ FeedbackMatchObject = DmTx200Base.eSourceSelection.Digital
+ };
+
VgaInput = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, DmTx200Base.eSourceSelection.Analog, this,
- VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
+ VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
+ {
+ FeedbackMatchObject = DmTx200Base.eSourceSelection.Analog
+ };
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -194,11 +218,18 @@ namespace PepperDash.Essentials.DM
void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
+
+
ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
AudioSourceNumericFeedback.FireUpdate();
-
- }
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
private void VgaInputOnInputStreamChange(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
@@ -319,17 +350,20 @@ namespace PepperDash.Essentials.DM
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
- ActiveVideoInputFeedback.FireUpdate();
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (DmTx200Base.eSourceSelection)p.Selector == Tx.AudioSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
- }
+ }
void InputStreamChangeEvent(EndpointInputStream inputStream, EndpointInputStreamEventArgs args)
{
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs
index 3938706d..f40da022 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx401CController.cs
@@ -20,7 +20,7 @@ namespace PepperDash.Essentials.DM
using eVst = DmTx401C.eSourceSelection;
[Description("Wrapper class for DM-TX-401-C")]
- public class DmTx401CController : DmTxControllerBase, ITxRouting, IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls
+ public class DmTx401CController : DmTxControllerBase, ITxRoutingWithFeedback, IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx401C Tx { get; private set; }
@@ -41,7 +41,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
- public IntFeedback VgaContrastFeedback { get; protected set; }
+ public IntFeedback VgaContrastFeedback { get; protected set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
///
/// Helps get the "real" inputs, including when in Auto
@@ -104,20 +118,33 @@ namespace PepperDash.Essentials.DM
HdmiIn = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.HDMI, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput));
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInput))
+ {
+ FeedbackMatchObject = eVst.HDMI
+ };
DisplayPortIn = new RoutingInputPortWithVideoStatuses(DmPortName.DisplayPortIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.DisplayPort, this,
- VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput));
+ VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput))
+ {
+ FeedbackMatchObject = eVst.DisplayPort
+ };
VgaIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Vga, eVst.VGA, this,
- VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
+ VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
+ {
+ FeedbackMatchObject = eVst.VGA
+ };
CompositeIn = new RoutingInputPortWithVideoStatuses(DmPortName.CompositeIn,
eRoutingSignalType.Video, eRoutingPortConnectionType.Composite, eVst.Composite, this,
- VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput));
+ VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
+ {
+ FeedbackMatchObject = eVst.Composite
+ };
Tx.HdmiInput.InputStreamChange += HdmiInputStreamChangeEvent;
Tx.DisplayPortInput.InputStreamChange += DisplayPortInputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
+ Tx.OnlineStatusChange += Tx_OnlineStatusChange;
Tx.VgaInput.InputStreamChange += VgaInputOnInputStreamChange;
tx.VgaInput.VideoControls.ControlChange += VideoControls_ControlChange;
@@ -286,6 +313,20 @@ namespace PepperDash.Essentials.DM
Tx.AudioSource = (eVst)inputSelector;
}
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.AudioSourceFeedback);
+
+ ActiveVideoInputFeedback.FireUpdate();
+ VideoSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
+
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
@@ -294,16 +335,20 @@ namespace PepperDash.Essentials.DM
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
- }
+ }
void VideoControls_ControlChange(object sender, GenericEventArgs args)
{
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs
index 42b42629..729744b9 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k202CController.cs
@@ -20,8 +20,8 @@ namespace PepperDash.Essentials.DM
using eVst = Crestron.SimplSharpPro.DeviceSupport.eX02VideoSourceType;
using eAst = Crestron.SimplSharpPro.DeviceSupport.eX02AudioSourceType;
- [Description("Wrapper class for DM-TX-4K-202-C")]
- public class DmTx4k202CController : DmTxControllerBase, ITxRouting, IHasFeedback,
+ [Description("Wrapper class for DM-TX-4K-202-C")]
+ public class DmTx4k202CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback,
IIROutputPorts, IComPorts
{
public DmTx4k202C Tx { get; private set; }
@@ -37,7 +37,21 @@ namespace PepperDash.Essentials.DM
public IntFeedback HdmiIn1HdcpCapabilityFeedback { get; protected set; }
public IntFeedback HdmiIn2HdcpCapabilityFeedback { get; protected set; }
public BoolFeedback Hdmi1VideoSyncFeedback { get; protected set; }
- public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
+ public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
//public override ushort HdcpSupportCapability { get; protected set; }
@@ -80,106 +94,121 @@ namespace PepperDash.Essentials.DM
{
return new RoutingPortCollection { DmOut, HdmiLoopOut };
}
- }
- public DmTx4k202CController(string key, string name, DmTx4k202C tx)
- : base(key, name, tx)
- {
- Tx = tx;
-
- HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
- HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]));
- ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
- () => ActualActiveVideoInput.ToString());
-
-
-
- Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
- Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
-
- Tx.BaseEvent += Tx_BaseEvent;
-
- VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
-
- AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.AudioSourceFeedback);
-
- HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability", () => (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);
-
- HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
-
- Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
-
- Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool)tx.HdmiInputs[2].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),
-
- HdcpStateFeedbackFunc = () =>
- {
- if (ActualActiveVideoInput == eVst.Hdmi1)
- return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
- if (ActualActiveVideoInput == eVst.Hdmi2)
- return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
- return "";
- },
-
- VideoResolutionFeedbackFunc = () =>
- {
- if (ActualActiveVideoInput == eVst.Hdmi1)
- return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
- if (ActualActiveVideoInput == eVst.Hdmi2)
- return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
- return "";
- },
- VideoSyncFeedbackFunc = () =>
- (ActualActiveVideoInput == eVst.Hdmi1
- && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
- || (ActualActiveVideoInput == eVst.Hdmi2
- && tx.HdmiInputs[2].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);
-
-
- AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
- AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
- AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
- AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback, HdmiIn2HdcpCapabilityFeedback,
- Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
-
- // Set Ports for CEC
- HdmiIn1.Port = Tx.HdmiInputs[1];
- HdmiIn2.Port = Tx.HdmiInputs[2];
- HdmiLoopOut.Port = Tx.HdmiOutput;
- DmOut.Port = Tx.DmOutput;
- }
-
-
-
+ }
+
+ public DmTx4k202CController(string key, string name, DmTx4k202C tx)
+ : base(key, name, tx)
+ {
+ Tx = tx;
+
+ 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,
+ eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
+ {
+ FeedbackMatchObject = eVst.Hdmi2
+ };
+
+ ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
+ () => ActualActiveVideoInput.ToString());
+
+
+
+ Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
+ Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
+
+ Tx.BaseEvent += Tx_BaseEvent;
+
+ Tx.OnlineStatusChange += Tx_OnlineStatusChange;
+
+ VideoSourceNumericFeedback = new IntFeedback(() => (int) Tx.VideoSourceFeedback);
+
+ AudioSourceNumericFeedback = new IntFeedback(() => (int) Tx.AudioSourceFeedback);
+
+ HdmiIn1HdcpCapabilityFeedback = new IntFeedback("HdmiIn1HdcpCapability",
+ () => (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);
+
+ HdcpSupportCapability = eHdcpCapabilityType.Hdcp2_2Support;
+
+ Hdmi1VideoSyncFeedback = new BoolFeedback(() => (bool) tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue);
+
+ Hdmi2VideoSyncFeedback = new BoolFeedback(() => (bool) tx.HdmiInputs[2].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),
+
+ HdcpStateFeedbackFunc = () =>
+ {
+ if (ActualActiveVideoInput == eVst.Hdmi1)
+ return tx.HdmiInputs[1].VideoAttributes.HdcpStateFeedback.ToString();
+ if (ActualActiveVideoInput == eVst.Hdmi2)
+ return tx.HdmiInputs[2].VideoAttributes.HdcpStateFeedback.ToString();
+ return "";
+ },
+
+ VideoResolutionFeedbackFunc = () =>
+ {
+ if (ActualActiveVideoInput == eVst.Hdmi1)
+ return tx.HdmiInputs[1].VideoAttributes.GetVideoResolutionString();
+ if (ActualActiveVideoInput == eVst.Hdmi2)
+ return tx.HdmiInputs[2].VideoAttributes.GetVideoResolutionString();
+ return "";
+ },
+ VideoSyncFeedbackFunc = () =>
+ (ActualActiveVideoInput == eVst.Hdmi1
+ && tx.HdmiInputs[1].SyncDetectedFeedback.BoolValue)
+ || (ActualActiveVideoInput == eVst.Hdmi2
+ && tx.HdmiInputs[2].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);
+
+
+ AddToFeedbackList(ActiveVideoInputFeedback, VideoSourceNumericFeedback, AudioSourceNumericFeedback,
+ AnyVideoInput.VideoStatus.HasVideoStatusFeedback, AnyVideoInput.VideoStatus.HdcpActiveFeedback,
+ AnyVideoInput.VideoStatus.HdcpStateFeedback, AnyVideoInput.VideoStatus.VideoResolutionFeedback,
+ AnyVideoInput.VideoStatus.VideoSyncFeedback, HdmiIn1HdcpCapabilityFeedback,
+ HdmiIn2HdcpCapabilityFeedback,
+ Hdmi1VideoSyncFeedback, Hdmi2VideoSyncFeedback);
+
+ // Set Ports for CEC
+ HdmiIn1.Port = Tx.HdmiInputs[1];
+ HdmiIn2.Port = Tx.HdmiInputs[2];
+ HdmiLoopOut.Port = Tx.HdmiOutput;
+ DmOut.Port = Tx.DmOutput;
+ }
+
+
+
public override bool CustomActivate()
{
// Link up all of these damned events to the various RoutingPorts via a helper handler
@@ -294,26 +323,43 @@ namespace PepperDash.Essentials.DM
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
- }
-
- void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
- {
- var id = args.EventId;
- Debug.Console(2, this, "EventId {0}", args.EventId);
-
- switch (id)
- {
- case EndpointTransmitterBase.VideoSourceFeedbackEventId:
- Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
- ActiveVideoInputFeedback.FireUpdate();
- VideoSourceNumericFeedback.FireUpdate();
- ActiveVideoInputFeedback.FireUpdate();
- break;
- case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
- AudioSourceNumericFeedback.FireUpdate();
- break;
- }
+ }
+
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+
+ ActiveVideoInputFeedback.FireUpdate();
+ VideoSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
+
+ void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
+ {
+ var id = args.EventId;
+ Debug.Console(2, this, "EventId {0}", args.EventId);
+
+ switch (id)
+ {
+ case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
+ VideoSourceNumericFeedback.FireUpdate();
+ ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ break;
+ case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
+ break;
+ }
}
///
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs
index dd91b0cc..3e716f60 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4k302CController.cs
@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.DM
using eAst = Crestron.SimplSharpPro.DeviceSupport.eX02AudioSourceType;
[Description("Wrapper class for DM-TX-4K-302-C")]
- public class DmTx4k302CController : DmTxControllerBase, ITxRouting, IHasFeedback,
+ public class DmTx4k302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback,
IIROutputPorts, IComPorts, IHasFreeRun, IVgaBrightnessContrastControls
{
public DmTx4k302C Tx { get; private set; }
@@ -44,7 +44,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback FreeRunEnabledFeedback { get; protected set; }
public IntFeedback VgaBrightnessFeedback { get; protected set; }
- public IntFeedback VgaContrastFeedback { get; protected set; }
+ public IntFeedback VgaContrastFeedback { get; protected set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
///
/// Helps get the "real" inputs, including when in Auto
@@ -95,13 +109,24 @@ namespace PepperDash.Essentials.DM
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
+ 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));
+ VideoStatusHelper.GetVgaInputStatusFuncs(tx.VgaInput))
+ {
+ FeedbackMatchObject = eVst.Vga
+ };
+
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -110,6 +135,8 @@ namespace PepperDash.Essentials.DM
Tx.VgaInput.InputStreamChange += VgaInputOnInputStreamChange;
Tx.BaseEvent += Tx_BaseEvent;
+ Tx.OnlineStatusChange += Tx_OnlineStatusChange;
+
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.AudioSourceFeedback);
@@ -387,23 +414,42 @@ namespace PepperDash.Essentials.DM
break;
}
}
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+
+ ActiveVideoInputFeedback.FireUpdate();
+ VideoSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
{
var id = args.EventId;
+ Debug.Console(2, this, "EventId {0}", args.EventId);
+
switch (id)
{
case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
VideoSourceNumericFeedback.FireUpdate();
ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
break;
case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
break;
}
- }
+ }
///
/// Relays the input stream change to the appropriate RoutingInputPort.
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs
index 47c383ff..da1685cc 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz202CController.cs
@@ -1,4 +1,6 @@
using Crestron.SimplSharpPro;
+using System;
+using System.Linq;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
@@ -12,9 +14,9 @@ using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
using eVst = eX02VideoSourceType;
- using eAst = eX02AudioSourceType;
-
- public class DmTx4kz202CController : DmTxControllerBase, ITxRouting,
+ using eAst = eX02AudioSourceType;
+
+ public class DmTx4kz202CController : DmTxControllerBase, ITxRoutingWithFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz202C Tx { get; private set; }
@@ -33,7 +35,21 @@ namespace PepperDash.Essentials.DM
public BoolFeedback Hdmi2VideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
- //public override ushort HdcpSupportCapability { get; protected set; }
+ //public override ushort HdcpSupportCapability { get; protected set; }
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
+
+
///
/// Helps get the "real" inputs, including when in Auto
@@ -73,14 +89,21 @@ namespace PepperDash.Essentials.DM
public DmTx4kz202CController(string key, string name, DmTx4kz202C tx)
: base(key, name, tx)
{
- Tx = tx;
-
- HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
- HdmiIn2 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn2,
- eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]));
+ Tx = tx;
+
+ 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,
+ eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi2, this,
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
+ {
+ FeedbackMatchObject = eVst.Hdmi2
+ };
+
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -89,6 +112,7 @@ namespace PepperDash.Essentials.DM
Tx.HdmiInputs[1].InputStreamChange += InputStreamChangeEvent;
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.BaseEvent += Tx_BaseEvent;
+ Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
@@ -282,27 +306,44 @@ namespace PepperDash.Essentials.DM
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
- }
-
- void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
- {
- var id = args.EventId;
- Debug.Console(2, this, "EventId {0}", args.EventId);
-
- switch (id)
- {
- case EndpointTransmitterBase.VideoSourceFeedbackEventId:
- Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
- ActiveVideoInputFeedback.FireUpdate();
- VideoSourceNumericFeedback.FireUpdate();
- AudioSourceNumericFeedback.FireUpdate();
- ActiveVideoInputFeedback.FireUpdate();
- break;
- case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- Debug.Console(2, this, " Audio Source : {0}", Tx.AudioSourceFeedback);
- AudioSourceNumericFeedback.FireUpdate();
- break;
- }
+ }
+
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+
+ ActiveVideoInputFeedback.FireUpdate();
+ VideoSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
+
+
+ void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
+ {
+ var id = args.EventId;
+ Debug.Console(2, this, "EventId {0}", args.EventId);
+
+ switch (id)
+ {
+ case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
+ VideoSourceNumericFeedback.FireUpdate();
+ ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ break;
+ case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
+ break;
+ }
}
///
diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs
index aba7e83c..1e44396c 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs
+++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Transmitters/DmTx4kz302CController.cs
@@ -1,4 +1,6 @@
using Crestron.SimplSharpPro;
+using System;
+using System.Linq;
//using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
@@ -15,8 +17,8 @@ namespace PepperDash.Essentials.DM
using eAst = eX02AudioSourceType;
- [Description("Wrapper class for DM-TX-4K-Z-302-C")]
- public class DmTx4kz302CController : DmTxControllerBase, ITxRouting, IHasFeedback,
+ [Description("Wrapper class for DM-TX-4K-Z-302-C")]
+ public class DmTx4kz302CController : DmTxControllerBase, ITxRoutingWithFeedback, IHasFeedback,
IIROutputPorts, IComPorts
{
public DmTx4kz302C Tx { get; private set; }
@@ -37,7 +39,20 @@ namespace PepperDash.Essentials.DM
public BoolFeedback DisplayPortVideoSyncFeedback { get; protected set; }
//public override IntFeedback HdcpSupportAllFeedback { get; protected set; }
- //public override ushort HdcpSupportCapability { get; protected set; }
+ //public override ushort HdcpSupportCapability { get; protected set; }
+
+ //IroutingNumericEvent
+ public event EventHandler NumericSwitchChange;
+
+ ///
+ /// Raise an event when the status of a switch object changes.
+ ///
+ /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType
+ private void OnSwitchChange(RoutingNumericEventArgs e)
+ {
+ var newEvent = NumericSwitchChange;
+ if (newEvent != null) newEvent(this, e);
+ }
///
/// Helps get the "real" inputs, including when in Auto
@@ -83,13 +98,22 @@ namespace PepperDash.Essentials.DM
HdmiIn1 = new RoutingInputPortWithVideoStatuses(DmPortName.HdmiIn1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, eVst.Hdmi1, this,
- VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[1]));
+ 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]));
- DisplayPortIn = new RoutingInputPortWithVideoStatuses(DmPortName.VgaIn,
+ VideoStatusHelper.GetHdmiInputStatusFuncs(tx.HdmiInputs[2]))
+ {
+ FeedbackMatchObject = eVst.Hdmi2
+ };
+ DisplayPortIn = new RoutingInputPortWithVideoStatuses(DmPortName.DisplayPortIn,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DisplayPort, eVst.DisplayPort, this,
- VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput));
+ VideoStatusHelper.GetDisplayPortInputStatusFuncs(tx.DisplayPortInput))
+ {
+ FeedbackMatchObject = eVst.DisplayPort
+ };
ActiveVideoInputFeedback = new StringFeedback("ActiveVideoInput",
() => ActualActiveVideoInput.ToString());
@@ -97,6 +121,7 @@ namespace PepperDash.Essentials.DM
Tx.HdmiInputs[2].InputStreamChange += InputStreamChangeEvent;
Tx.DisplayPortInput.InputStreamChange += DisplayPortInputStreamChange;
Tx.BaseEvent += Tx_BaseEvent;
+ Tx.OnlineStatusChange += Tx_OnlineStatusChange;
VideoSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
AudioSourceNumericFeedback = new IntFeedback(() => (int)Tx.VideoSourceFeedback);
@@ -293,23 +318,44 @@ namespace PepperDash.Essentials.DM
if (inputStream == Tx.HdmiInputs[2]) Hdmi2VideoSyncFeedback.FireUpdate();
break;
}
- }
-
- void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
- {
- var id = args.EventId;
- switch (id)
- {
- case EndpointTransmitterBase.VideoSourceFeedbackEventId:
- Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
- VideoSourceNumericFeedback.FireUpdate();
- ActiveVideoInputFeedback.FireUpdate();
- break;
- case EndpointTransmitterBase.AudioSourceFeedbackEventId:
- Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
- AudioSourceNumericFeedback.FireUpdate();
- break;
- }
+ }
+
+ void Tx_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
+ {
+ var localVideoInputPort =
+ InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ var localAudioInputPort =
+ InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+
+ ActiveVideoInputFeedback.FireUpdate();
+ VideoSourceNumericFeedback.FireUpdate();
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localAudioInputPort, eRoutingSignalType.Audio));
+ }
+
+
+ void Tx_BaseEvent(GenericBase device, BaseEventArgs args)
+ {
+ var id = args.EventId;
+ Debug.Console(2, this, "EventId {0}", args.EventId);
+
+ switch (id)
+ {
+ case EndpointTransmitterBase.VideoSourceFeedbackEventId:
+ var localVideoInputPort = InputPorts.FirstOrDefault(p => (eVst)p.Selector == Tx.VideoSourceFeedback);
+ Debug.Console(2, this, " Video Source: {0}", Tx.VideoSourceFeedback);
+ VideoSourceNumericFeedback.FireUpdate();
+ ActiveVideoInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, VideoSourceNumericFeedback.UShortValue, OutputPorts.First(), localVideoInputPort, eRoutingSignalType.Video));
+ break;
+ case EndpointTransmitterBase.AudioSourceFeedbackEventId:
+ var localInputAudioPort = InputPorts.FirstOrDefault(p => (eAst)p.Selector == Tx.AudioSourceFeedback);
+ Debug.Console(2, this, " Audio Source: {0}", Tx.AudioSourceFeedback);
+ AudioSourceNumericFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(1, AudioSourceNumericFeedback.UShortValue, OutputPorts.First(), localInputAudioPort, eRoutingSignalType.Audio));
+ break;
+ }
}
///
diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj
index 7d6b7bde..69045ea5 100644
--- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj
+++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj
@@ -59,7 +59,7 @@
..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll
-
+
False
..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs
index 35d696c7..8b42cd82 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraBase.cs
@@ -181,14 +181,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
});
}
- if (cameraDevice is IPower)
+ var powerCamera = cameraDevice as IHasPowerControl;
+ if (powerCamera != null)
{
- var powerCamera = cameraDevice as IPower;
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => powerCamera.PowerOn());
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => powerCamera.PowerOff());
- powerCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
- powerCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
+ var powerFbCamera = powerCamera as IHasPowerControlWithFeedback;
+ if (powerFbCamera != null)
+ {
+ powerFbCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
+ powerFbCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
+ }
}
if (cameraDevice is ICommunicationMonitor)
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs
index 89b6002a..c0a0442c 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs
@@ -92,8 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraPanControl : IHasCameraControls
{
- // void PanLeft(bool pressRelease);
- // void PanRight(bool pressRelease);
void PanLeft();
void PanRight();
void PanStop();
@@ -104,8 +102,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraTiltControl : IHasCameraControls
{
- // void TiltDown(bool pressRelease);
- // void TildUp(bool pressRelease);
void TiltDown();
void TiltUp();
void TiltStop();
@@ -116,8 +112,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraZoomControl : IHasCameraControls
{
- // void ZoomIn(bool pressRelease);
- // void ZoomOut(bool pressRelease);
void ZoomIn();
void ZoomOut();
void ZoomStop();
@@ -135,6 +129,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
void TriggerAutoFocus();
}
+ public interface IHasAutoFocusMode
+ {
+ void SetFocusModeAuto();
+ void SetFocusModeManual();
+ void ToggleFocusMode();
+ }
+
public interface IHasCameraAutoMode : IHasCameraControls
{
void CameraAutoModeOn();
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs
index 4393229c..fb8ae79c 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs
@@ -12,29 +12,86 @@ using PepperDash.Essentials.Devices.Common.Codec;
using System.Text.RegularExpressions;
using Crestron.SimplSharp.Reflection;
+using Newtonsoft.Json;
+
namespace PepperDash.Essentials.Devices.Common.Cameras
{
- public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IPower, IBridgeAdvanced
+ public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
{
+ CameraViscaPropertiesConfig PropertiesConfig;
+
public IBasicCommunication Communication { get; private set; }
- public CommunicationGather PortGather { get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
- public byte PanSpeed = 0x10;
- public byte TiltSpeed = 0x10;
+ ///
+ /// Used to store the actions to parse inquiry responses as the inquiries are sent
+ ///
+ private CrestronQueue> InquiryResponseQueue;
+
+ ///
+ /// Camera ID (Default 1)
+ ///
+ public byte ID = 0x01;
+ public byte ResponseID;
+
+
+ public byte PanSpeedSlow = 0x10;
+ public byte TiltSpeedSlow = 0x10;
+
+ public byte PanSpeedFast = 0x13;
+ public byte TiltSpeedFast = 0x13;
+
private bool IsMoving;
private bool IsZooming;
- public bool PowerIsOn { get; private set; }
+
+ bool _powerIsOn;
+ public bool PowerIsOn
+ {
+ get
+ {
+ return _powerIsOn;
+ }
+ private set
+ {
+ if (value != _powerIsOn)
+ {
+ _powerIsOn = value;
+ PowerIsOnFeedback.FireUpdate();
+ CameraIsOffFeedback.FireUpdate();
+ }
+ }
+ }
+
+ const byte ZoomInCmd = 0x02;
+ const byte ZoomOutCmd = 0x03;
+ const byte ZoomStopCmd = 0x00;
+
+ ///
+ /// Used to determine when to move the camera at a faster speed if a direction is held
+ ///
+ CTimer SpeedTimer;
+ // TODO: Implment speed timer for PTZ controls
+
+ long FastSpeedHoldTimeMs = 2000;
byte[] IncomingBuffer = new byte[] { };
public BoolFeedback PowerIsOnFeedback { get; private set; }
- public CameraVisca(string key, string name, IBasicCommunication comm, CameraPropertiesConfig props) :
+ public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) :
base(key, name)
{
+ InquiryResponseQueue = new CrestronQueue>(15);
+
Presets = props.Presets;
+ PropertiesConfig = props;
+
+ ID = (byte)(props.Id + 0x80);
+ ResponseID = (byte)((props.Id * 0x10) + 0x80);
+
+ SetupCameraSpeeds();
+
OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true));
// Default to all capabilties
@@ -51,11 +108,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
// This instance uses RS-232 control
}
- PortGather = new CommunicationGather(Communication, "\xFF");
-
Communication.BytesReceived += new EventHandler(Communication_BytesReceived);
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
+ CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; });
if (props.CommunicationMonitorProperties != null)
{
@@ -66,9 +122,38 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
}
DeviceManager.AddDevice(CommunicationMonitor);
-
-
}
+
+
+ ///
+ /// Sets up camera speed values based on config
+ ///
+ void SetupCameraSpeeds()
+ {
+ if (PropertiesConfig.FastSpeedHoldTimeMs > 0)
+ {
+ FastSpeedHoldTimeMs = PropertiesConfig.FastSpeedHoldTimeMs;
+ }
+
+ if (PropertiesConfig.PanSpeedSlow > 0)
+ {
+ PanSpeedSlow = (byte)PropertiesConfig.PanSpeedSlow;
+ }
+ if (PropertiesConfig.PanSpeedFast > 0)
+ {
+ PanSpeedFast = (byte)PropertiesConfig.PanSpeedFast;
+ }
+
+ if (PropertiesConfig.TiltSpeedSlow > 0)
+ {
+ TiltSpeedSlow = (byte)PropertiesConfig.TiltSpeedSlow;
+ }
+ if (PropertiesConfig.TiltSpeedFast > 0)
+ {
+ TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast;
+ }
+ }
+
public override bool CustomActivate()
{
Communication.Connect();
@@ -110,40 +195,245 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Communication.SendBytes(b);
}
+
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{
- // This is probably not thread-safe buffering
- // Append the incoming bytes with whatever is in the buffer
- var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
- IncomingBuffer.CopyTo(newBytes, 0);
- e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
- if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
- Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
- }
+ var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
+ try
+ {
+ // This is probably not thread-safe buffering
+ // Append the incoming bytes with whatever is in the buffer
+ IncomingBuffer.CopyTo(newBytes, 0);
+ e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
+ if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
+ Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
- private void SendPanTiltCommand (byte[] cmd)
+ byte[] message = new byte[] { };
+
+ // Search for the delimiter 0xFF character
+ for (int i = 0; i < newBytes.Length; i++)
+ {
+ if (newBytes[i] == 0xFF)
+ {
+ // i will be the index of the delmiter character
+ message = newBytes.Take(i).ToArray();
+ // Skip over what we just took and save the rest for next time
+ newBytes = newBytes.Skip(i).ToArray();
+ }
+ }
+
+ if (message.Length > 0)
+ {
+ // Check for matching ID
+ if (message[0] != ResponseID)
+ {
+ return;
+ }
+
+ switch (message[1])
+ {
+ case 0x40:
+ {
+ // ACK received
+ Debug.Console(2, this, "ACK Received");
+ break;
+ }
+ case 0x50:
+ {
+
+ if (message[2] == 0xFF)
+ {
+ // Completion received
+ Debug.Console(2, this, "Completion Received");
+ }
+ else
+ {
+ // Inquiry response received. Dequeue the next response handler and invoke it
+ if (InquiryResponseQueue.Count > 0)
+ {
+ var inquiryAction = InquiryResponseQueue.Dequeue();
+
+ inquiryAction.Invoke(message.Skip(2).ToArray());
+ }
+ else
+ {
+ Debug.Console(2, this, "Response Queue is empty. Nothing to dequeue.");
+ }
+ }
+
+ break;
+ }
+ case 0x60:
+ {
+ // Error message
+
+ switch (message[2])
+ {
+ case 0x01:
+ {
+ // Message Length Error
+ Debug.Console(2, this, "Error from device: Message Length Error");
+ break;
+ }
+ case 0x02:
+ {
+ // Syntax Error
+ Debug.Console(2, this, "Error from device: Syntax Error");
+ break;
+ }
+ case 0x03:
+ {
+ // Command Buffer Full
+ Debug.Console(2, this, "Error from device: Command Buffer Full");
+ break;
+ }
+ case 0x04:
+ {
+ // Command Cancelled
+ Debug.Console(2, this, "Error from device: Command Cancelled");
+ break;
+ }
+ case 0x05:
+ {
+ // No Socket
+ Debug.Console(2, this, "Error from device: No Socket");
+ break;
+ }
+ case 0x41:
+ {
+ // Command not executable
+ Debug.Console(2, this, "Error from device: Command not executable");
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (message == new byte[] { ResponseID, 0x50, 0x02, 0xFF })
+ {
+ PowerIsOn = true;
+ }
+ else if (message == new byte[] { ResponseID, 0x50, 0x03, 0xFF })
+ {
+ PowerIsOn = false;
+ }
+
+ }
+
+ }
+ catch (Exception err)
+ {
+ Debug.Console(2, this, "Error parsing feedback: {0}", err);
+ }
+ finally
+ {
+ // Save whatever partial message is here
+ IncomingBuffer = newBytes;
+ }
+ }
+
+ ///
+ /// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed.
+ ///
+ ///
+ ///
+ private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled)
{
- var temp = new Byte[] { 0x81, 0x01, 0x06, 0x01, PanSpeed, TiltSpeed };
- int length = temp.Length + cmd.Length + 1;
-
- byte[] sum = new byte[length];
- temp.CopyTo(sum, 0);
- cmd.CopyTo(sum, temp.Length);
- sum[length - 1] = 0xFF;
- SendBytes(sum);
+ SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled));
+
+ if (!fastSpeedEnabled)
+ {
+ if (SpeedTimer != null)
+ {
+ StopSpeedTimer();
+ }
+
+ // Start the timer to send fast speed if still moving after FastSpeedHoldTime elapses
+ SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs);
+ }
+
}
+ private void StopSpeedTimer()
+ {
+ if (SpeedTimer != null)
+ {
+ SpeedTimer.Stop();
+ SpeedTimer.Dispose();
+ SpeedTimer = null;
+ }
+ }
+
+ ///
+ /// Generates the pan/tilt command with either slow or fast speed
+ ///
+ ///
+ ///
+ ///
+ private byte[] GetPanTiltCommand(byte[] cmd, bool fastSpeed)
+ {
+ byte panSpeed;
+ byte tiltSpeed;
+
+ if (!fastSpeed)
+ {
+ panSpeed = PanSpeedSlow;
+ tiltSpeed = TiltSpeedSlow;
+ }
+ else
+ {
+ panSpeed = PanSpeedFast;
+ tiltSpeed = TiltSpeedFast;
+ }
+
+ var temp = new byte[] { ID, 0x01, 0x06, 0x01, panSpeed, tiltSpeed };
+ int length = temp.Length + cmd.Length + 1;
+
+ byte[] sum = new byte[length];
+ temp.CopyTo(sum, 0);
+ cmd.CopyTo(sum, temp.Length);
+ sum[length - 1] = 0xFF;
+
+ return sum;
+ }
+
+
+ void SendPowerQuery()
+ {
+ SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF });
+ InquiryResponseQueue.Enqueue(HandlePowerResponse);
+ }
+
public void PowerOn()
{
-
- SendBytes(new Byte[] { 0x81, 0x01, 0x04, 0x00, 0x02, 0xFF });
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF });
+ SendPowerQuery();
}
+ void HandlePowerResponse(byte[] response)
+ {
+ switch (response[0])
+ {
+ case 0x02:
+ {
+ PowerIsOn = true;
+ break;
+ }
+ case 0x03:
+ {
+ PowerIsOn = false;
+ break;
+ }
+ }
+ }
+
public void PowerOff()
{
- SendBytes(new Byte[] {0x81, 0x01, 0x04, 0x00, 0x03, 0xFF});
- }
+ SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF});
+ SendPowerQuery();
+ }
public void PowerToggle()
{
@@ -155,12 +445,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void PanLeft()
{
- SendPanTiltCommand(new byte[] {0x01, 0x03});
+ SendPanTiltCommand(new byte[] {0x01, 0x03}, false);
IsMoving = true;
}
public void PanRight()
{
- SendPanTiltCommand(new byte[] { 0x02, 0x03 });
+ SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
IsMoving = true;
}
public void PanStop()
@@ -169,12 +459,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
public void TiltDown()
{
- SendPanTiltCommand(new byte[] { 0x03, 0x02 });
+ SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
IsMoving = true;
}
public void TiltUp()
{
- SendPanTiltCommand(new byte[] { 0x03, 0x01 });
+ SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
IsMoving = true;
}
public void TiltStop()
@@ -184,16 +474,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
private void SendZoomCommand (byte cmd)
{
- SendBytes(new byte[] {0x81, 0x01, 0x04, 0x07, cmd, 0xFF} );
+ SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} );
}
+
+
public void ZoomIn()
{
- SendZoomCommand(0x02);
+ SendZoomCommand(ZoomInCmd);
IsZooming = true;
}
public void ZoomOut()
{
- SendZoomCommand(0x03);
+ SendZoomCommand(ZoomOutCmd);
IsZooming = true;
}
public void ZoomStop()
@@ -205,26 +497,28 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
if (IsZooming)
{
- SendZoomCommand(0x00);
+ SendZoomCommand(ZoomStopCmd);
IsZooming = false;
}
else
{
- SendPanTiltCommand(new byte[] {0x03, 0x03});
+ StopSpeedTimer();
+ SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
IsMoving = false;
}
}
public void PositionHome()
{
- throw new NotImplementedException();
+ SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF });
}
public void RecallPreset(int presetNumber)
{
- SendBytes(new byte[] {0x81, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
+ SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
}
public void SavePreset(int presetNumber)
{
- SendBytes(new byte[] { 0x81, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
}
#region IHasCameraPresets Members
@@ -244,6 +538,90 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
#endregion
+
+ #region IHasCameraFocusControl Members
+
+ public void FocusNear()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x03, 0xFF });
+ }
+
+ public void FocusFar()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x02, 0xFF });
+ }
+
+ public void FocusStop()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x00, 0xFF });
+ }
+
+ public void TriggerAutoFocus()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x18, 0x01, 0xFF });
+ SendAutoFocusQuery();
+ }
+
+ #endregion
+
+ #region IHasAutoFocus Members
+
+ public void SetFocusModeAuto()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x02, 0xFF });
+ SendAutoFocusQuery();
+ }
+
+ public void SetFocusModeManual()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x03, 0xFF });
+ SendAutoFocusQuery();
+ }
+
+ public void ToggleFocusMode()
+ {
+ SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x10, 0xFF });
+ SendAutoFocusQuery();
+ }
+
+ #endregion
+
+ void SendAutoFocusQuery()
+ {
+ SendBytes(new byte[] { ID, 0x09, 0x04, 0x38, 0xFF });
+ InquiryResponseQueue.Enqueue(HandleAutoFocusResponse);
+ }
+
+ void HandleAutoFocusResponse(byte[] response)
+ {
+ switch (response[0])
+ {
+ case 0x02:
+ {
+ // Auto Mode
+ PowerIsOn = true;
+ break;
+ }
+ case 0x03:
+ {
+ // Manual Mode
+ PowerIsOn = false;
+ break;
+ }
+ }
+ }
+
+ #region IHasCameraOff Members
+
+ public BoolFeedback CameraIsOffFeedback { get; private set; }
+
+
+ public void CameraOff()
+ {
+ PowerOff();
+ }
+
+ #endregion
}
public class CameraViscaFactory : EssentialsDeviceFactory
@@ -257,10 +635,51 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
Debug.Console(1, "Factory Attempting to create new CameraVisca Device");
var comm = CommFactory.CreateCommForDevice(dc);
- var props = Newtonsoft.Json.JsonConvert.DeserializeObject(
+ var props = Newtonsoft.Json.JsonConvert.DeserializeObject(
dc.Properties.ToString());
return new Cameras.CameraVisca(dc.Key, dc.Name, comm, props);
}
}
+
+ public class CameraViscaPropertiesConfig : CameraPropertiesConfig
+ {
+ ///
+ /// Control ID of the camera (1-7)
+ ///
+ [JsonProperty("id")]
+ public uint Id { get; set; }
+
+ ///
+ /// Slow Pan speed (0-18)
+ ///
+ [JsonProperty("panSpeedSlow")]
+ public uint PanSpeedSlow { get; set; }
+
+ ///
+ /// Fast Pan speed (0-18)
+ ///
+ [JsonProperty("panSpeedFast")]
+ public uint PanSpeedFast { get; set; }
+
+ ///
+ /// Slow tilt speed (0-18)
+ ///
+ [JsonProperty("tiltSpeedSlow")]
+ public uint TiltSpeedSlow { get; set; }
+
+ ///
+ /// Fast tilt speed (0-18)
+ ///
+ [JsonProperty("tiltSpeedFast")]
+ public uint TiltSpeedFast { get; set; }
+
+ ///
+ /// Time a button must be held before fast speed is engaged (Milliseconds)
+ ///
+ [JsonProperty("fastSpeedHoldTimeMs")]
+ public uint FastSpeedHoldTimeMs { get; set; }
+
+ }
+
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs
index d86f628e..f8ef33ee 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/IHasExternalSourceSwitching.cs
@@ -11,9 +11,11 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public interface IHasExternalSourceSwitching
{
bool ExternalSourceListEnabled { get; }
+ string ExternalSourceInputPort { get; }
void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type);
void SetExternalSourceState(string key, eExternalSourceMode mode);
void ClearExternalSources();
+ void SetSelectedSource(string key);
Action RunRouteAction { set;}
}
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/ComTcpDisplayBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/ComTcpDisplayBase.cs
index da92df1f..84547c1b 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/ComTcpDisplayBase.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/ComTcpDisplayBase.cs
@@ -10,26 +10,28 @@ using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Displays
{
- public abstract class ComTcpDisplayBase : DisplayBase, IPower
+ [Obsolete("Please use TwoWayDisplayBase instead")]
+ public abstract class ComTcpDisplayBase : TwoWayDisplayBase
{
- ///
- /// Sets the communication method for this - swaps out event handlers and output handlers
- ///
- public IBasicCommunication CommunicationMethod
- {
- get { return _CommunicationMethod; }
- set
- {
- if (_CommunicationMethod != null)
- _CommunicationMethod.BytesReceived -= this.CommunicationMethod_BytesReceived;
- // Outputs???
- _CommunicationMethod = value;
- if (_CommunicationMethod != null)
- _CommunicationMethod.BytesReceived += this.CommunicationMethod_BytesReceived;
- // Outputs?
- }
- }
- IBasicCommunication _CommunicationMethod;
+
+ /////
+ ///// Sets the communication method for this - swaps out event handlers and output handlers
+ /////
+ //public IBasicCommunication CommunicationMethod
+ //{
+ // get { return _CommunicationMethod; }
+ // set
+ // {
+ // if (_CommunicationMethod != null)
+ // _CommunicationMethod.BytesReceived -= this.CommunicationMethod_BytesReceived;
+ // // Outputs???
+ // _CommunicationMethod = value;
+ // if (_CommunicationMethod != null)
+ // _CommunicationMethod.BytesReceived += this.CommunicationMethod_BytesReceived;
+ // // Outputs?
+ // }
+ //}
+ //IBasicCommunication _CommunicationMethod;
public ComTcpDisplayBase(string key, string name)
: base(key, name)
@@ -38,6 +40,6 @@ namespace PepperDash.Essentials.Devices.Displays
}
- protected abstract void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args);
+ //protected abstract void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args);
}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NecPaSeriesProjector.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NecPaSeriesProjector.cs
index 86c8ddaa..86752bff 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NecPaSeriesProjector.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/NecPaSeriesProjector.cs
@@ -11,217 +11,222 @@ using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Devices.Displays
{
- public class NecPaSeriesProjector : ComTcpDisplayBase, IBridgeAdvanced
- {
- public readonly IntFeedback Lamp1RemainingPercent;
- int _Lamp1RemainingPercent;
- public readonly IntFeedback Lamp2RemainingPercent;
- int _Lamp2RemainingPercent;
- protected override Func PowerIsOnFeedbackFunc
- {
- get { return () => _PowerIsOn; }
- }
- bool _PowerIsOn;
+ //public class NecPaSeriesProjector : TwoWayDisplayBase, IBridgeAdvanced
+ //{
+ // public readonly IntFeedback Lamp1RemainingPercent;
+ // int _Lamp1RemainingPercent;
+ // public readonly IntFeedback Lamp2RemainingPercent;
+ // int _Lamp2RemainingPercent;
- protected override Func IsCoolingDownFeedbackFunc
- {
- get { return () => false; }
- }
+ // RoutingInputPort _CurrentInputPort;
- protected override Func IsWarmingUpFeedbackFunc
- {
- get { return () => false; }
- }
+ // protected override Func CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } }
+
+ // protected override Func PowerIsOnFeedbackFunc
+ // {
+ // get { return () => _PowerIsOn; }
+ // }
+ // bool _PowerIsOn;
- public override void PowerToggle()
- {
- throw new NotImplementedException();
- }
+ // protected override Func IsCoolingDownFeedbackFunc
+ // {
+ // get { return () => false; }
+ // }
- public override void ExecuteSwitch(object selector)
- {
- throw new NotImplementedException();
- }
+ // protected override Func IsWarmingUpFeedbackFunc
+ // {
+ // get { return () => false; }
+ // }
- Dictionary InputMap;
+ // public override void PowerToggle()
+ // {
+ // throw new NotImplementedException();
+ // }
- ///
- /// Constructor
- ///
- public NecPaSeriesProjector(string key, string name)
- : base(key, name)
- {
- Lamp1RemainingPercent = new IntFeedback("Lamp1RemainingPercent", () => _Lamp1RemainingPercent);
- Lamp2RemainingPercent = new IntFeedback("Lamp2RemainingPercent", () => _Lamp2RemainingPercent);
+ // public override void ExecuteSwitch(object selector)
+ // {
+ // throw new NotImplementedException();
+ // }
- InputMap = new Dictionary(StringComparer.OrdinalIgnoreCase)
- {
- { "computer1", "\x02\x03\x00\x00\x02\x01\x01\x09" },
- { "computer2", "\x02\x03\x00\x00\x02\x01\x02\x0a" },
- { "computer3", "\x02\x03\x00\x00\x02\x01\x03\x0b" },
- { "hdmi", "\x02\x03\x00\x00\x02\x01\x1a\x22" },
- { "dp", "\x02\x03\x00\x00\x02\x01\x1b\x23" },
- { "video", "\x02\x03\x00\x00\x02\x01\x06\x0e" },
- { "viewer", "\x02\x03\x00\x00\x02\x01\x1f\x27" },
- { "network", "\x02\x03\x00\x00\x02\x01\x20\x28" },
- };
- }
+ // Dictionary InputMap;
- void IsConnected_OutputChange(object sender, EventArgs e)
- {
+ // ///
+ // /// Constructor
+ // ///
+ // public NecPaSeriesProjector(string key, string name)
+ // : base(key, name)
+ // {
+ // Lamp1RemainingPercent = new IntFeedback("Lamp1RemainingPercent", () => _Lamp1RemainingPercent);
+ // Lamp2RemainingPercent = new IntFeedback("Lamp2RemainingPercent", () => _Lamp2RemainingPercent);
- }
+ // InputMap = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ // {
+ // { "computer1", "\x02\x03\x00\x00\x02\x01\x01\x09" },
+ // { "computer2", "\x02\x03\x00\x00\x02\x01\x02\x0a" },
+ // { "computer3", "\x02\x03\x00\x00\x02\x01\x03\x0b" },
+ // { "hdmi", "\x02\x03\x00\x00\x02\x01\x1a\x22" },
+ // { "dp", "\x02\x03\x00\x00\x02\x01\x1b\x23" },
+ // { "video", "\x02\x03\x00\x00\x02\x01\x06\x0e" },
+ // { "viewer", "\x02\x03\x00\x00\x02\x01\x1f\x27" },
+ // { "network", "\x02\x03\x00\x00\x02\x01\x20\x28" },
+ // };
+ // }
- public void SetEnable(bool state)
- {
- var tcp = CommunicationMethod as GenericTcpIpClient;
- if (tcp != null)
- {
- tcp.Connect();
- }
- }
+ // void IsConnected_OutputChange(object sender, EventArgs e)
+ // {
- public override void PowerOn()
- {
- SendText("\x02\x00\x00\x00\x00\x02");
- }
+ // }
- public override void PowerOff()
- {
- SendText("\x02\x01\x00\x00\x00\x03");
- }
+ // public void SetEnable(bool state)
+ // {
+ // var tcp = CommunicationMethod as GenericTcpIpClient;
+ // if (tcp != null)
+ // {
+ // tcp.Connect();
+ // }
+ // }
- public void PictureMuteOn()
- {
- SendText("\x02\x10\x00\x00\x00\x12");
- }
+ // public override void PowerOn()
+ // {
+ // SendText("\x02\x00\x00\x00\x00\x02");
+ // }
- public void PictureMuteOff()
- {
- SendText("\x02\x11\x00\x00\x00\x13");
- }
+ // public override void PowerOff()
+ // {
+ // SendText("\x02\x01\x00\x00\x00\x03");
+ // }
- public void GetRunningStatus()
- {
- SendText("\x00\x85\x00\x00\x01\x01\x87");
- }
+ // public void PictureMuteOn()
+ // {
+ // SendText("\x02\x10\x00\x00\x00\x12");
+ // }
- public void GetLampRemaining(int lampNum)
- {
- if (!_PowerIsOn) return;
+ // public void PictureMuteOff()
+ // {
+ // SendText("\x02\x11\x00\x00\x00\x13");
+ // }
- var bytes = new byte[]{0x03,0x96,0x00,0x00,0x02,0x00,0x04};
- if (lampNum == 2)
- bytes[5] = 0x01;
- SendBytes(AppendChecksum(bytes));
- }
+ // public void GetRunningStatus()
+ // {
+ // SendText("\x00\x85\x00\x00\x01\x01\x87");
+ // }
- public void SelectInput(string inputKey)
- {
- if (InputMap.ContainsKey(inputKey))
- SendText(InputMap[inputKey]);
- }
+ // public void GetLampRemaining(int lampNum)
+ // {
+ // if (!_PowerIsOn) return;
- void SendText(string text)
- {
- if (CommunicationMethod != null)
- CommunicationMethod.SendText(text);
- }
+ // var bytes = new byte[]{0x03,0x96,0x00,0x00,0x02,0x00,0x04};
+ // if (lampNum == 2)
+ // bytes[5] = 0x01;
+ // SendBytes(AppendChecksum(bytes));
+ // }
- void SendBytes(byte[] bytes)
- {
- if (CommunicationMethod != null)
- CommunicationMethod.SendBytes(bytes);
- }
+ // public void SelectInput(string inputKey)
+ // {
+ // if (InputMap.ContainsKey(inputKey))
+ // SendText(InputMap[inputKey]);
+ // }
- byte[] AppendChecksum(byte[] bytes)
- {
- byte sum = unchecked((byte)bytes.Sum(x => (int)x));
- var retVal = new byte[bytes.Length + 1];
- bytes.CopyTo(retVal, 0);
- retVal[retVal.Length - 1] = sum;
- return retVal;
- }
+ // void SendText(string text)
+ // {
+ // if (CommunicationMethod != null)
+ // CommunicationMethod.SendText(text);
+ // }
- protected override void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args)
- {
- var bytes = args.Bytes;
- ParseBytes(args.Bytes);
- }
+ // void SendBytes(byte[] bytes)
+ // {
+ // if (CommunicationMethod != null)
+ // CommunicationMethod.SendBytes(bytes);
+ // }
- void ParseBytes(byte[] bytes)
- {
- if (bytes[0] == 0x22)
- {
- // Power on
- if (bytes[1] == 0x00)
- {
- _PowerIsOn = true;
- PowerIsOnFeedback.FireUpdate();
- }
- // Power off
- else if (bytes[1] == 0x01)
- {
- _PowerIsOn = false;
- PowerIsOnFeedback.FireUpdate();
- }
- }
- // Running Status
- else if (bytes[0] == 0x20 && bytes[1] == 0x85 && bytes[4] == 0x10)
- {
- var operationStates = new Dictionary
- {
- { 0x00, "Standby" },
- { 0x04, "Power On" },
- { 0x05, "Cooling" },
- { 0x06, "Standby (error)" },
- { 0x0f, "Standby (power saving" },
- { 0x10, "Network Standby" },
- { 0xff, "Not supported" }
- };
+ // byte[] AppendChecksum(byte[] bytes)
+ // {
+ // byte sum = unchecked((byte)bytes.Sum(x => (int)x));
+ // var retVal = new byte[bytes.Length + 1];
+ // bytes.CopyTo(retVal, 0);
+ // retVal[retVal.Length - 1] = sum;
+ // return retVal;
+ // }
- var newPowerIsOn = bytes[7] == 0x01;
- if (newPowerIsOn != _PowerIsOn)
- {
- _PowerIsOn = newPowerIsOn;
- PowerIsOnFeedback.FireUpdate();
- }
+ // protected override void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args)
+ // {
+ // var bytes = args.Bytes;
+ // ParseBytes(args.Bytes);
+ // }
- Debug.Console(2, this, "PowerIsOn={0}\rCooling={1}\rPowering on/off={2}\rStatus={3}",
- _PowerIsOn,
- bytes[8] == 0x01,
- bytes[9] == 0x01,
- operationStates[bytes[10]]);
+ // void ParseBytes(byte[] bytes)
+ // {
+ // if (bytes[0] == 0x22)
+ // {
+ // // Power on
+ // if (bytes[1] == 0x00)
+ // {
+ // _PowerIsOn = true;
+ // PowerIsOnFeedback.FireUpdate();
+ // }
+ // // Power off
+ // else if (bytes[1] == 0x01)
+ // {
+ // _PowerIsOn = false;
+ // PowerIsOnFeedback.FireUpdate();
+ // }
+ // }
+ // // Running Status
+ // else if (bytes[0] == 0x20 && bytes[1] == 0x85 && bytes[4] == 0x10)
+ // {
+ // var operationStates = new Dictionary
+ // {
+ // { 0x00, "Standby" },
+ // { 0x04, "Power On" },
+ // { 0x05, "Cooling" },
+ // { 0x06, "Standby (error)" },
+ // { 0x0f, "Standby (power saving" },
+ // { 0x10, "Network Standby" },
+ // { 0xff, "Not supported" }
+ // };
+
+ // var newPowerIsOn = bytes[7] == 0x01;
+ // if (newPowerIsOn != _PowerIsOn)
+ // {
+ // _PowerIsOn = newPowerIsOn;
+ // PowerIsOnFeedback.FireUpdate();
+ // }
+
+ // Debug.Console(2, this, "PowerIsOn={0}\rCooling={1}\rPowering on/off={2}\rStatus={3}",
+ // _PowerIsOn,
+ // bytes[8] == 0x01,
+ // bytes[9] == 0x01,
+ // operationStates[bytes[10]]);
- }
- // Lamp remaining
- else if (bytes[0] == 0x23 && bytes[1] == 0x96 && bytes[4] == 0x06 && bytes[6] == 0x04)
- {
- var newValue = bytes[7];
- if (bytes[5] == 0x00)
- {
- if (newValue != _Lamp1RemainingPercent)
- {
- _Lamp1RemainingPercent = newValue;
- Lamp1RemainingPercent.FireUpdate();
- }
- }
- else
- {
- if (newValue != _Lamp2RemainingPercent)
- {
- _Lamp2RemainingPercent = newValue;
- Lamp2RemainingPercent.FireUpdate();
- }
- }
- Debug.Console(0, this, "Lamp {0}, {1}% remaining", (bytes[5] + 1), bytes[7]);
- }
+ // }
+ // // Lamp remaining
+ // else if (bytes[0] == 0x23 && bytes[1] == 0x96 && bytes[4] == 0x06 && bytes[6] == 0x04)
+ // {
+ // var newValue = bytes[7];
+ // if (bytes[5] == 0x00)
+ // {
+ // if (newValue != _Lamp1RemainingPercent)
+ // {
+ // _Lamp1RemainingPercent = newValue;
+ // Lamp1RemainingPercent.FireUpdate();
+ // }
+ // }
+ // else
+ // {
+ // if (newValue != _Lamp2RemainingPercent)
+ // {
+ // _Lamp2RemainingPercent = newValue;
+ // Lamp2RemainingPercent.FireUpdate();
+ // }
+ // }
+ // Debug.Console(0, this, "Lamp {0}, {1}% remaining", (bytes[5] + 1), bytes[7]);
+ // }
- }
+ // }
- public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
- {
- LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
- }
- }
+ // public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ // {
+ // LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
+ // }
+ //}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs
index b2de0f8f..47c08cea 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Display/SamsungMDCDisplay.cs
@@ -1,662 +1,668 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro.CrestronThread;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.DeviceSupport;
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Bridges;
-using PepperDash.Essentials.Core.Config;
-using PepperDash.Essentials.Core.Routing;
-using Feedback = PepperDash.Essentials.Core.Feedback;
-
-using Newtonsoft.Json.Linq;
-
-namespace PepperDash.Essentials.Devices.Displays
-{
- ///
- ///
- ///
- public class SamsungMDC : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor, IInputDisplayPort1, IInputDisplayPort2,
- IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4, IBridgeAdvanced
- {
- public IBasicCommunication Communication { get; private set; }
-
- public StatusMonitorBase CommunicationMonitor { get; private set; }
-
- public byte ID { get; private set; }
-
- bool LastCommandSentWasVolume;
-
- bool _PowerIsOn;
- bool _IsWarmingUp;
- bool _IsCoolingDown;
- ushort _VolumeLevelForSig;
- int _LastVolumeSent;
- bool _IsMuted;
- RoutingInputPort _CurrentInputPort;
- byte[] IncomingBuffer = new byte[]{};
- ActionIncrementer VolumeIncrementer;
- bool VolumeIsRamping;
- public bool IsInStandby { get; private set; }
- bool IsPoweringOnIgnorePowerFb;
-
- protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
- protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
- protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
- protected override Func CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } }
-
- ///
- /// Constructor for IBasicCommunication
- ///
- public SamsungMDC(string key, string name, IBasicCommunication comm, string id)
- : base(key, name)
- {
- Communication = comm;
- Communication.BytesReceived += new EventHandler(Communication_BytesReceived);
-
- ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
- Init();
- }
-
- ///
- /// Constructor for TCP
- ///
- public SamsungMDC(string key, string name, string hostname, int port, string id)
- : base(key, name)
- {
- Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
- ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
- Init();
- }
-
- ///
- /// Constructor for COM
- ///
- public SamsungMDC(string key, string name, ComPort port, ComPort.ComPortSpec spec, string id)
- : base(key, name)
- {
- Communication = new ComPortController(key + "-com", port, spec);
- //Communication.TextReceived += new EventHandler(Communication_TextReceived);
-
- ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
- Init();
- }
-
- void AddRoutingInputPort(RoutingInputPort port, byte fbMatch)
- {
- port.FeedbackMatchObject = fbMatch;
- InputPorts.Add(port);
- }
-
- void Init()
- {
- WarmupTime = 10000;
- CooldownTime = 8000;
-
- CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet);
- DeviceManager.AddDevice(CommunicationMonitor);
-
- VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,
- v => SetVolume((ushort)v),
- () => _LastVolumeSent);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this), 0x21);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1PC, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1PC), this), 0x22);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this), 0x23);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2PC, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2PC), this), 0x24);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this), 0x32);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this), 0x25);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this), 0x18);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
- eRoutingPortConnectionType.Composite, new Action(InputVideo1), this), 0x08);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn1, eRoutingSignalType.Video,
- eRoutingPortConnectionType.Vga, new Action(InputRgb1), this), 0x14);
-
- AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn2, eRoutingSignalType.Video,
- eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb2)), this), 0x1E);
-
- VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevelForSig; });
- MuteFeedback = new BoolFeedback(() => _IsMuted);
-
- StatusGet();
- }
-
- ///
- ///
- ///
- ///
- public override bool CustomActivate()
- {
- Communication.Connect();
- CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
- CommunicationMonitor.Start();
- return true;
- }
-
- public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
- {
- LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
- }
-
- public override FeedbackCollection Feedbacks
- {
- get
- {
- var list = base.Feedbacks;
- list.AddRange(new List
- {
- VolumeLevelFeedback,
- MuteFeedback,
- CurrentInputFeedback
- });
- return list;
- }
- }
-
- ///
- /// /
- ///
- ///
- void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
- {
- try
- {
- // This is probably not thread-safe buffering
- // Append the incoming bytes with whatever is in the buffer
- var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
- IncomingBuffer.CopyTo(newBytes, 0);
- e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
-
- if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
- Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
-
- // Need to find AA FF and have
- for (int i = 0; i < newBytes.Length; i++)
- {
- if (newBytes[i] == 0xAA && newBytes[i + 1] == 0xFF)
- {
- newBytes = newBytes.Skip(i).ToArray(); // Trim off junk if there's "dirt" in the buffer
-
- // parse it
- // If it's at least got the header, then process it,
- while (newBytes.Length > 4 && newBytes[0] == 0xAA && newBytes[1] == 0xFF)
- {
- var msgLen = newBytes[3];
- // if the buffer is shorter than the header (3) + message (msgLen) + checksum (1),
- // give and save it for next time
- if (newBytes.Length < msgLen + 4)
- break;
-
- // Good length, grab the message
- var message = newBytes.Skip(4).Take(msgLen).ToArray();
-
- // At this point, the ack/nak is the first byte
- if (message[0] == 0x41)
- {
- switch (message[1]) // type byte
- {
- case 0x00: // General status
- //UpdatePowerFB(message[2], message[5]); // "power" can be misrepresented when the display sleeps
-
- // Handle the first power on fb when waiting for it.
- if (IsPoweringOnIgnorePowerFb && message[2] == 0x01)
- IsPoweringOnIgnorePowerFb = false;
- // Ignore general-status power off messages when powering up
- if (!(IsPoweringOnIgnorePowerFb && message[2] == 0x00))
- UpdatePowerFB(message[2]);
- UpdateVolumeFB(message[3]);
- UpdateMuteFb(message[4]);
- UpdateInputFb(message[5]);
- break;
-
- case 0x11:
- UpdatePowerFB(message[2]);
- break;
-
- case 0x12:
- UpdateVolumeFB(message[2]);
- break;
-
- case 0x13:
- UpdateMuteFb(message[2]);
- break;
-
- case 0x14:
- UpdateInputFb(message[2]);
- break;
-
- default:
- break;
- }
- }
- // Skip over what we've used and save the rest for next time
- newBytes = newBytes.Skip(5 + msgLen).ToArray();
- }
-
- break; // parsing will mean we can stop looking for header in loop
- }
- }
-
- // Save whatever partial message is here
- IncomingBuffer = newBytes;
- }
- catch (Exception err)
- {
- Debug.Console(2, this, "Error parsing feedback: {0}", err);
- }
- }
-
- ///
- ///
- ///
- void UpdatePowerFB(byte powerByte)
- {
- var newVal = powerByte == 1;
- if (newVal != _PowerIsOn)
- {
- _PowerIsOn = newVal;
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Feedback Power State: {0}", _PowerIsOn);
- PowerIsOnFeedback.FireUpdate();
- }
- }
-
- ///
- /// Updates power status from general updates where source is included.
- /// Compensates for errant standby / power off hiccups by ignoring
- /// power off states with input < 0x10
- ///
- void UpdatePowerFB(byte powerByte, byte inputByte)
- {
- // This should reject errant power feedbacks when switching away from input on standby.
- if (powerByte == 0x01 && inputByte < 0x10)
- IsInStandby = true;
- if (powerByte == 0x00 && IsInStandby) // Ignore power off if coming from standby - glitch
- {
- IsInStandby = false;
- return;
- }
-
- UpdatePowerFB(powerByte);
- }
-
- ///
- ///
- ///
- void UpdateVolumeFB(byte b)
- {
- var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535);
- if (!VolumeIsRamping)
- _LastVolumeSent = newVol;
- if (newVol != _VolumeLevelForSig)
- {
- _VolumeLevelForSig = newVol;
- VolumeLevelFeedback.FireUpdate();
- }
- }
-
- ///
- ///
- ///
- void UpdateMuteFb(byte b)
- {
- var newMute = b == 1;
- if (newMute != _IsMuted)
- {
- _IsMuted = newMute;
- MuteFeedback.FireUpdate();
- }
- }
-
- ///
- ///
- ///
- void UpdateInputFb(byte b)
- {
- var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b));
- if (newInput != null && newInput != _CurrentInputPort)
- {
- _CurrentInputPort = newInput;
- CurrentInputFeedback.FireUpdate();
- }
- }
-
- ///
- /// Formats an outgoing message. Replaces third byte with ID and replaces last byte with checksum
- ///
- ///
- void SendBytes(byte[] b)
- {
- if (LastCommandSentWasVolume) // If the last command sent was volume
- if (b[1] != 0x12) // Check if this command is volume, and if not, delay this command
- CrestronEnvironment.Sleep(100);
-
- b[2] = ID;
- // append checksum by adding all bytes, except last which should be 00
- int checksum = 0;
- for (var i = 1; i < b.Length - 1; i++) // add 2nd through 2nd-to-last bytes
- {
- checksum += b[i];
- }
- checksum = checksum & 0x000000FF; // mask off MSBs
- b[b.Length - 1] = (byte)checksum;
- if(Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
- Debug.Console(2, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
-
- if (b[1] == 0x12)
- LastCommandSentWasVolume = true;
- else
- LastCommandSentWasVolume = false;
-
- Communication.SendBytes(b);
- }
-
-
- ///
- ///
- ///
- public void StatusGet()
- {
- SendBytes(new byte[] { 0xAA, 0x00, 0x00, 0x00, 0x00 });
- }
-
- ///
- ///
- ///
- public override void PowerOn()
- {
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering On Display");
-
- IsPoweringOnIgnorePowerFb = true;
- //Send(PowerOnCmd);
- SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x01, 0x00 });
- if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
- {
- _IsWarmingUp = true;
- IsWarmingUpFeedback.FireUpdate();
- // Fake power-up cycle
- WarmupTimer = new CTimer(o =>
- {
- _IsWarmingUp = false;
- _PowerIsOn = true;
- IsWarmingUpFeedback.FireUpdate();
- PowerIsOnFeedback.FireUpdate();
- }, WarmupTime);
- }
- }
-
- ///
- ///
- ///
- public override void PowerOff()
- {
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering Off Display");
-
- IsPoweringOnIgnorePowerFb = false;
- // If a display has unreliable-power off feedback, just override this and
- // remove this check.
- if (!_IsWarmingUp && !_IsCoolingDown) // PowerIsOnFeedback.BoolValue &&
- {
- //Send(PowerOffCmd);
- SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x00, 0x00 });
- _IsCoolingDown = true;
- _PowerIsOn = false;
- PowerIsOnFeedback.FireUpdate();
- IsCoolingDownFeedback.FireUpdate();
- // Fake cool-down cycle
- CooldownTimer = new CTimer(o =>
- {
- _IsCoolingDown = false;
- IsCoolingDownFeedback.FireUpdate();
- }, CooldownTime);
- }
- }
-
- public override void PowerToggle()
- {
- if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
- PowerOff();
- else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
- PowerOn();
- }
-
- public void PowerGet()
- {
- SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x00, 0x00 });
- }
-
- public void InputHdmi1()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x21, 0x00 });
- }
-
- public void InputHdmi1PC()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x22, 0x00 });
- }
-
- public void InputHdmi2()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x23, 0x00 });
- }
-
- public void InputHdmi2PC()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x24, 0x00 });
- }
-
- public void InputHdmi3()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x32, 0x00 });
- }
-
- public void InputHdmi4()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x34, 0x00 });
- }
-
- public void InputDisplayPort1()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x25, 0x00 });
- }
-
- public void InputDisplayPort2()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x26, 0x00 });
- }
-
- public void InputDvi1()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x18, 0x00 });
- }
-
- public void InputVideo1()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x08, 0x00 });
- }
-
- public void InputRgb1()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x14, 0x00 });
- }
-
- public void InputRgb2()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x1E, 0x00 });
- }
-
- public void InputGet()
- {
- SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x00, 0x00 });
- }
-
-
- ///
- /// Executes a switch, turning on display if necessary.
- ///
- ///
- public override void ExecuteSwitch(object selector)
- {
- //if (!(selector is Action))
- // Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
-
- if (_PowerIsOn)
- (selector as Action)();
- else // if power is off, wait until we get on FB to send it.
- {
- // One-time event handler to wait for power on before executing switch
- EventHandler handler = null; // necessary to allow reference inside lambda to handler
- handler = (o, a) =>
- {
- if (!_IsWarmingUp) // Done warming
- {
- IsWarmingUpFeedback.OutputChange -= handler;
- (selector as Action)();
- }
- };
- IsWarmingUpFeedback.OutputChange += handler; // attach and wait for on FB
- PowerOn();
- }
- }
-
- ///
- /// Scales the level to the range of the display and sends the command
- ///
- ///
- public void SetVolume(ushort level)
- {
- _LastVolumeSent = level;
- var scaled = (int)NumericalHelpers.Scale(level, 0, 65535, 0, 100);
- // The inputs to Scale ensure that byte won't overflow
- SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x01, Convert.ToByte(scaled), 0x00 });
- }
-
- #region IBasicVolumeWithFeedback Members
-
- public IntFeedback VolumeLevelFeedback { get; private set; }
-
- public BoolFeedback MuteFeedback { get; private set; }
-
- ///
- ///
- ///
- public void MuteOff()
- {
- SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x00, 0x00 });
- }
-
- ///
- ///
- ///
- public void MuteOn()
- {
- SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x01, 0x00 });
- }
-
- ///
- ///
- ///
- public void MuteGet()
- {
- SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x00, 0x00 });
- }
-
- #endregion
-
- #region IBasicVolumeControls Members
-
- ///
- ///
- ///
- public void MuteToggle()
- {
- if (_IsMuted)
- MuteOff();
- else
- MuteOn();
- }
-
- ///
- ///
- ///
- ///
- public void VolumeDown(bool pressRelease)
- {
- if (pressRelease)
- {
- VolumeIncrementer.StartDown();
- VolumeIsRamping = true;
- }
- else
- {
- VolumeIsRamping = false;
- VolumeIncrementer.Stop();
- }
- }
-
- ///
- ///
- ///
- ///
- public void VolumeUp(bool pressRelease)
- {
- if (pressRelease)
- {
- VolumeIncrementer.StartUp();
- VolumeIsRamping = true;
- }
- else
- {
- VolumeIsRamping = false;
- VolumeIncrementer.Stop();
- }
- }
-
- ///
- ///
- ///
- public void VolumeGet()
- {
- SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x00, 0x00 });
- }
-
- #endregion
- }
-
- public class SamsungMDCFactory : EssentialsDeviceFactory
- {
- public SamsungMDCFactory()
- {
- TypeNames = new List() { "samsungmdc" };
- }
-
- public override EssentialsDevice BuildDevice(DeviceConfig dc)
- {
- Debug.Console(1, "Factory Attempting to create new Generic Comm Device");
- var comm = CommFactory.CreateCommForDevice(dc);
- if (comm != null)
- return new SamsungMDC(dc.Key, dc.Name, comm, dc.Properties["id"].Value());
- else
- return null;
- }
- }
-
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro.CrestronThread;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Bridges;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Routing;
+using Feedback = PepperDash.Essentials.Core.Feedback;
+
+using Newtonsoft.Json.Linq;
+
+namespace PepperDash.Essentials.Devices.Displays
+{
+ ///
+ ///
+ ///
+ public class SamsungMDC : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor, IInputDisplayPort1, IInputDisplayPort2,
+ IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4, IBridgeAdvanced
+ {
+ public IBasicCommunication Communication { get; private set; }
+
+
+
+ public StatusMonitorBase CommunicationMonitor { get; private set; }
+
+ public byte ID { get; private set; }
+
+ bool LastCommandSentWasVolume;
+
+ bool _PowerIsOn;
+ bool _IsWarmingUp;
+ bool _IsCoolingDown;
+ ushort _VolumeLevelForSig;
+ int _LastVolumeSent;
+ bool _IsMuted;
+ RoutingInputPort _CurrentInputPort;
+ byte[] IncomingBuffer = new byte[]{};
+ ActionIncrementer VolumeIncrementer;
+ bool VolumeIsRamping;
+ public bool IsInStandby { get; private set; }
+ bool IsPoweringOnIgnorePowerFb;
+
+ protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
+ protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
+ protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
+ protected override Func CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } }
+
+ ///
+ /// Constructor for IBasicCommunication
+ ///
+ public SamsungMDC(string key, string name, IBasicCommunication comm, string id)
+ : base(key, name)
+ {
+ Communication = comm;
+ Communication.BytesReceived += new EventHandler(Communication_BytesReceived);
+
+ ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
+ Init();
+ }
+
+ ///
+ /// Constructor for TCP
+ ///
+ public SamsungMDC(string key, string name, string hostname, int port, string id)
+ : base(key, name)
+ {
+ Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
+ ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
+ Init();
+ }
+
+ ///
+ /// Constructor for COM
+ ///
+ public SamsungMDC(string key, string name, ComPort port, ComPort.ComPortSpec spec, string id)
+ : base(key, name)
+ {
+ Communication = new ComPortController(key + "-com", port, spec);
+ //Communication.TextReceived += new EventHandler(Communication_TextReceived);
+
+ ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
+ Init();
+ }
+
+ void AddRoutingInputPort(RoutingInputPort port, byte fbMatch)
+ {
+ port.FeedbackMatchObject = fbMatch;
+ InputPorts.Add(port);
+ }
+
+ void Init()
+ {
+ WarmupTime = 10000;
+ CooldownTime = 8000;
+
+ CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet);
+ DeviceManager.AddDevice(CommunicationMonitor);
+
+ VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,
+ v => SetVolume((ushort)v),
+ () => _LastVolumeSent);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this), 0x21);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1PC, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1PC), this), 0x22);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this), 0x23);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2PC, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2PC), this), 0x24);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this), 0x32);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this), 0x25);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this), 0x18);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Composite, new Action(InputVideo1), this), 0x08);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn1, eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Vga, new Action(InputRgb1), this), 0x14);
+
+ AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn2, eRoutingSignalType.Video,
+ eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb2)), this), 0x1E);
+
+ VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevelForSig; });
+ MuteFeedback = new BoolFeedback(() => _IsMuted);
+
+ StatusGet();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public override bool CustomActivate()
+ {
+ Communication.Connect();
+ CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
+ CommunicationMonitor.Start();
+ return true;
+ }
+
+ public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ {
+ LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
+ }
+
+ public override FeedbackCollection Feedbacks
+ {
+ get
+ {
+ var list = base.Feedbacks;
+ list.AddRange(new List
+ {
+ VolumeLevelFeedback,
+ MuteFeedback,
+ CurrentInputFeedback
+ });
+ return list;
+ }
+ }
+
+ ///
+ /// /
+ ///
+ ///
+ void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
+ {
+ try
+ {
+ // This is probably not thread-safe buffering
+ // Append the incoming bytes with whatever is in the buffer
+ var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
+ IncomingBuffer.CopyTo(newBytes, 0);
+ e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
+
+ if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
+ Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
+
+ // Need to find AA FF and have
+ for (int i = 0; i < newBytes.Length; i++)
+ {
+ if (newBytes[i] == 0xAA && newBytes[i + 1] == 0xFF)
+ {
+ newBytes = newBytes.Skip(i).ToArray(); // Trim off junk if there's "dirt" in the buffer
+
+ // parse it
+ // If it's at least got the header, then process it,
+ while (newBytes.Length > 4 && newBytes[0] == 0xAA && newBytes[1] == 0xFF)
+ {
+ var msgLen = newBytes[3];
+ // if the buffer is shorter than the header (3) + message (msgLen) + checksum (1),
+ // give and save it for next time
+ if (newBytes.Length < msgLen + 4)
+ break;
+
+ // Good length, grab the message
+ var message = newBytes.Skip(4).Take(msgLen).ToArray();
+
+ // At this point, the ack/nak is the first byte
+ if (message[0] == 0x41)
+ {
+ switch (message[1]) // type byte
+ {
+ case 0x00: // General status
+ //UpdatePowerFB(message[2], message[5]); // "power" can be misrepresented when the display sleeps
+
+ // Handle the first power on fb when waiting for it.
+ if (IsPoweringOnIgnorePowerFb && message[2] == 0x01)
+ IsPoweringOnIgnorePowerFb = false;
+ // Ignore general-status power off messages when powering up
+ if (!(IsPoweringOnIgnorePowerFb && message[2] == 0x00))
+ UpdatePowerFB(message[2]);
+ UpdateVolumeFB(message[3]);
+ UpdateMuteFb(message[4]);
+ UpdateInputFb(message[5]);
+ break;
+
+ case 0x11:
+ UpdatePowerFB(message[2]);
+ break;
+
+ case 0x12:
+ UpdateVolumeFB(message[2]);
+ break;
+
+ case 0x13:
+ UpdateMuteFb(message[2]);
+ break;
+
+ case 0x14:
+ UpdateInputFb(message[2]);
+ break;
+
+ default:
+ break;
+ }
+ }
+ // Skip over what we've used and save the rest for next time
+ newBytes = newBytes.Skip(5 + msgLen).ToArray();
+ }
+
+ break; // parsing will mean we can stop looking for header in loop
+ }
+ }
+
+ // Save whatever partial message is here
+ IncomingBuffer = newBytes;
+ }
+ catch (Exception err)
+ {
+ Debug.Console(2, this, "Error parsing feedback: {0}", err);
+ }
+ }
+
+ ///
+ ///
+ ///
+ void UpdatePowerFB(byte powerByte)
+ {
+ var newVal = powerByte == 1;
+ if (newVal != _PowerIsOn)
+ {
+ _PowerIsOn = newVal;
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Feedback Power State: {0}", _PowerIsOn);
+ PowerIsOnFeedback.FireUpdate();
+ }
+ }
+
+ ///
+ /// Updates power status from general updates where source is included.
+ /// Compensates for errant standby / power off hiccups by ignoring
+ /// power off states with input < 0x10
+ ///
+ void UpdatePowerFB(byte powerByte, byte inputByte)
+ {
+ // This should reject errant power feedbacks when switching away from input on standby.
+ if (powerByte == 0x01 && inputByte < 0x10)
+ IsInStandby = true;
+ if (powerByte == 0x00 && IsInStandby) // Ignore power off if coming from standby - glitch
+ {
+ IsInStandby = false;
+ return;
+ }
+
+ UpdatePowerFB(powerByte);
+ }
+
+ ///
+ ///
+ ///
+ void UpdateVolumeFB(byte b)
+ {
+ var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535);
+ if (!VolumeIsRamping)
+ _LastVolumeSent = newVol;
+ if (newVol != _VolumeLevelForSig)
+ {
+ _VolumeLevelForSig = newVol;
+ VolumeLevelFeedback.FireUpdate();
+ }
+ }
+
+ ///
+ ///
+ ///
+ void UpdateMuteFb(byte b)
+ {
+ var newMute = b == 1;
+ if (newMute != _IsMuted)
+ {
+ _IsMuted = newMute;
+ MuteFeedback.FireUpdate();
+ }
+ }
+
+
+
+
+ ///
+ ///
+ ///
+ void UpdateInputFb(byte b)
+ {
+ var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b));
+ if (newInput != null && newInput != _CurrentInputPort)
+ {
+ _CurrentInputPort = newInput;
+ CurrentInputFeedback.FireUpdate();
+ OnSwitchChange(new RoutingNumericEventArgs(null, _CurrentInputPort, eRoutingSignalType.AudioVideo));
+ }
+ }
+
+ ///
+ /// Formats an outgoing message. Replaces third byte with ID and replaces last byte with checksum
+ ///
+ ///
+ void SendBytes(byte[] b)
+ {
+ if (LastCommandSentWasVolume) // If the last command sent was volume
+ if (b[1] != 0x12) // Check if this command is volume, and if not, delay this command
+ CrestronEnvironment.Sleep(100);
+
+ b[2] = ID;
+ // append checksum by adding all bytes, except last which should be 00
+ int checksum = 0;
+ for (var i = 1; i < b.Length - 1; i++) // add 2nd through 2nd-to-last bytes
+ {
+ checksum += b[i];
+ }
+ checksum = checksum & 0x000000FF; // mask off MSBs
+ b[b.Length - 1] = (byte)checksum;
+ if(Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
+ Debug.Console(2, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
+
+ if (b[1] == 0x12)
+ LastCommandSentWasVolume = true;
+ else
+ LastCommandSentWasVolume = false;
+
+ Communication.SendBytes(b);
+ }
+
+
+ ///
+ ///
+ ///
+ public void StatusGet()
+ {
+ SendBytes(new byte[] { 0xAA, 0x00, 0x00, 0x00, 0x00 });
+ }
+
+ ///
+ ///
+ ///
+ public override void PowerOn()
+ {
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering On Display");
+
+ IsPoweringOnIgnorePowerFb = true;
+ //Send(PowerOnCmd);
+ SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x01, 0x00 });
+ if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
+ {
+ _IsWarmingUp = true;
+ IsWarmingUpFeedback.FireUpdate();
+ // Fake power-up cycle
+ WarmupTimer = new CTimer(o =>
+ {
+ _IsWarmingUp = false;
+ _PowerIsOn = true;
+ IsWarmingUpFeedback.FireUpdate();
+ PowerIsOnFeedback.FireUpdate();
+ }, WarmupTime);
+ }
+ }
+
+ ///
+ ///
+ ///
+ public override void PowerOff()
+ {
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Powering Off Display");
+
+ IsPoweringOnIgnorePowerFb = false;
+ // If a display has unreliable-power off feedback, just override this and
+ // remove this check.
+ if (!_IsWarmingUp && !_IsCoolingDown) // PowerIsOnFeedback.BoolValue &&
+ {
+ //Send(PowerOffCmd);
+ SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x00, 0x00 });
+ _IsCoolingDown = true;
+ _PowerIsOn = false;
+ PowerIsOnFeedback.FireUpdate();
+ IsCoolingDownFeedback.FireUpdate();
+ // Fake cool-down cycle
+ CooldownTimer = new CTimer(o =>
+ {
+ _IsCoolingDown = false;
+ IsCoolingDownFeedback.FireUpdate();
+ }, CooldownTime);
+ }
+ }
+
+ public override void PowerToggle()
+ {
+ if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
+ PowerOff();
+ else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
+ PowerOn();
+ }
+
+ public void PowerGet()
+ {
+ SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x00, 0x00 });
+ }
+
+ public void InputHdmi1()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x21, 0x00 });
+ }
+
+ public void InputHdmi1PC()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x22, 0x00 });
+ }
+
+ public void InputHdmi2()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x23, 0x00 });
+ }
+
+ public void InputHdmi2PC()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x24, 0x00 });
+ }
+
+ public void InputHdmi3()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x32, 0x00 });
+ }
+
+ public void InputHdmi4()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x34, 0x00 });
+ }
+
+ public void InputDisplayPort1()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x25, 0x00 });
+ }
+
+ public void InputDisplayPort2()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x26, 0x00 });
+ }
+
+ public void InputDvi1()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x18, 0x00 });
+ }
+
+ public void InputVideo1()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x08, 0x00 });
+ }
+
+ public void InputRgb1()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x14, 0x00 });
+ }
+
+ public void InputRgb2()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x1E, 0x00 });
+ }
+
+ public void InputGet()
+ {
+ SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x00, 0x00 });
+ }
+
+
+ ///
+ /// Executes a switch, turning on display if necessary.
+ ///
+ ///
+ public override void ExecuteSwitch(object selector)
+ {
+ //if (!(selector is Action))
+ // Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
+
+ if (_PowerIsOn)
+ (selector as Action)();
+ else // if power is off, wait until we get on FB to send it.
+ {
+ // One-time event handler to wait for power on before executing switch
+ EventHandler handler = null; // necessary to allow reference inside lambda to handler
+ handler = (o, a) =>
+ {
+ if (!_IsWarmingUp) // Done warming
+ {
+ IsWarmingUpFeedback.OutputChange -= handler;
+ (selector as Action)();
+ }
+ };
+ IsWarmingUpFeedback.OutputChange += handler; // attach and wait for on FB
+ PowerOn();
+ }
+ }
+
+ ///
+ /// Scales the level to the range of the display and sends the command
+ ///
+ ///
+ public void SetVolume(ushort level)
+ {
+ _LastVolumeSent = level;
+ var scaled = (int)NumericalHelpers.Scale(level, 0, 65535, 0, 100);
+ // The inputs to Scale ensure that byte won't overflow
+ SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x01, Convert.ToByte(scaled), 0x00 });
+ }
+
+ #region IBasicVolumeWithFeedback Members
+
+ public IntFeedback VolumeLevelFeedback { get; private set; }
+
+ public BoolFeedback MuteFeedback { get; private set; }
+
+ ///
+ ///
+ ///
+ public void MuteOff()
+ {
+ SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x00, 0x00 });
+ }
+
+ ///
+ ///
+ ///
+ public void MuteOn()
+ {
+ SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x01, 0x00 });
+ }
+
+ ///
+ ///
+ ///
+ public void MuteGet()
+ {
+ SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x00, 0x00 });
+ }
+
+ #endregion
+
+ #region IBasicVolumeControls Members
+
+ ///
+ ///
+ ///
+ public void MuteToggle()
+ {
+ if (_IsMuted)
+ MuteOff();
+ else
+ MuteOn();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void VolumeDown(bool pressRelease)
+ {
+ if (pressRelease)
+ {
+ VolumeIncrementer.StartDown();
+ VolumeIsRamping = true;
+ }
+ else
+ {
+ VolumeIsRamping = false;
+ VolumeIncrementer.Stop();
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void VolumeUp(bool pressRelease)
+ {
+ if (pressRelease)
+ {
+ VolumeIncrementer.StartUp();
+ VolumeIsRamping = true;
+ }
+ else
+ {
+ VolumeIsRamping = false;
+ VolumeIncrementer.Stop();
+ }
+ }
+
+ ///
+ ///
+ ///
+ public void VolumeGet()
+ {
+ SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x00, 0x00 });
+ }
+
+ #endregion
+ }
+
+ public class SamsungMDCFactory : EssentialsDeviceFactory
+ {
+ public SamsungMDCFactory()
+ {
+ TypeNames = new List() { "samsungmdc" };
+ }
+
+ public override EssentialsDevice BuildDevice(DeviceConfig dc)
+ {
+ Debug.Console(1, "Factory Attempting to create new Generic Comm Device");
+ var comm = CommFactory.CreateCommForDevice(dc);
+ if (comm != null)
+ return new SamsungMDC(dc.Key, dc.Name, comm, dc.Properties["id"].Value());
+ else
+ return null;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
index f115f401..54d37613 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
@@ -63,7 +63,7 @@
..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll
-
+
False
..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs
index 71698529..97aacb2d 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/IRSetTopBoxBase.cs
@@ -16,12 +16,12 @@ using PepperDash.Essentials.Core.Routing;
namespace PepperDash.Essentials.Devices.Common
{
[Description("Wrapper class for an IR Set Top Box")]
- public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingOutputs, IUsageTracking, IPower
+ public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingOutputs, IUsageTracking, IHasPowerControl
{
public IrOutputPortController IrPort { get; private set; }
public uint DisplayUiType { get { return DisplayUiConstants.TypeDirecTv; } }
-
+ public ushort IrPulseTime { get; set; }
public bool HasPresets { get; set; }
public bool HasDvr { get; set; }
@@ -35,6 +35,13 @@ namespace PepperDash.Essentials.Devices.Common
: base(key, name)
{
IrPort = portCont;
+ IrPulseTime = 200;
+
+ if (props.IrPulseTime > 0)
+ {
+ IrPulseTime = (ushort)props.IrPulseTime;
+ }
+
DeviceManager.AddDevice(portCont);
HasPresets = props.HasPresets;
@@ -55,7 +62,6 @@ namespace PepperDash.Essentials.Devices.Common
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
eRoutingPortConnectionType.DigitalAudio, null, this);
OutputPorts = new RoutingPortCollection { AnyVideoOut, AnyAudioOut };
-
}
public void LoadPresets(string filePath)
@@ -348,26 +354,17 @@ namespace PepperDash.Essentials.Devices.Common
public void PowerOn()
{
- IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_ON, true);
- IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_ON, false);
-
+ IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
}
public void PowerOff()
{
- IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_OFF, true);
- IrPort.PressRelease(IROutputStandardCommands.IROut_POWER_OFF, false);
-
+ IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
public void PowerToggle()
{
- throw new NotImplementedException();
- }
-
- public BoolFeedback PowerIsOnFeedback
- {
- get { throw new NotImplementedException(); }
+ IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}
#endregion
@@ -395,79 +392,96 @@ namespace PepperDash.Essentials.Devices.Common
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name;
var stbBase = this as ISetTopBoxControls;
+ if (stbBase != null)
+ {
+ trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad;
+ trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric;
+ trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr;
+ trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets;
- trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad;
- trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric;
- trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr;
- trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets;
+ trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList);
+ trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay);
- trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList);
- trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay);
+ trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets);
+ }
- trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets);
-
- var stbPower = this as IPower;
-
- trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn);
- trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff);
- trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle);
+ var stbPower = this as IHasPowerControl;
+ if (stbPower != null)
+ {
+ trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn);
+ trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff);
+ trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle);
+ }
var stbDPad = this as IDPad;
-
- trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up);
- trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down);
- trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left);
- trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right);
- trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select);
- trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu);
- trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit);
+ if (stbDPad != null)
+ {
+ trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up);
+ trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down);
+ trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left);
+ trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right);
+ trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select);
+ trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu);
+ trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit);
+ }
var stbChannel = this as IChannel;
- trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp);
- trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown);
- trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel);
- trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide);
- trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info);
- trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit);
+ if (stbChannel != null)
+ {
+ trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp);
+ trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown);
+ trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel);
+ trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide);
+ trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info);
+ trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit);
+ }
var stbColor = this as IColor;
- trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red);
- trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green);
- trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow);
- trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue);
+ if (stbColor != null)
+ {
+ trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red);
+ trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green);
+ trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow);
+ trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue);
+ }
var stbKeypad = this as ISetTopBoxNumericKeypad;
+ if (stbKeypad != null)
+ {
+ trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label;
+ trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label;
- trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label;
- trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label;
+ trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1;
+ trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2;
- trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1;
- trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2;
-
- trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0);
- trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1);
- trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2);
- trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3);
- trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4);
- trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5);
- trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6);
- trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7);
- trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8);
- trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9);
- trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
- trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
- trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash);
- trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter);
+ trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0);
+ trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1);
+ trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2);
+ trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3);
+ trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4);
+ trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5);
+ trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6);
+ trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7);
+ trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8);
+ trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9);
+ trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
+ trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1);
+ trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash);
+ trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter);
+ }
var stbTransport = this as ITransport;
- trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play);
- trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause);
- trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind);
- trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd);
- trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus);
- trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus);
- trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop);
- trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record);
+ if (stbTransport != null)
+ {
+ trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play);
+ trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause);
+ trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind);
+ trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd);
+ trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus);
+ trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus);
+ trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop);
+ trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record);
+ }
}
}
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/SetTopBoxPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/SetTopBoxPropertiesConfig.cs
index ae9a6709..8faac507 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/SetTopBoxPropertiesConfig.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SetTopBox/SetTopBoxPropertiesConfig.cs
@@ -14,6 +14,7 @@ namespace PepperDash.Essentials.Devices.Common
public bool HasDvr { get; set; }
public bool HasDpad { get; set; }
public bool HasNumeric { get; set; }
+ public int IrPulseTime { get; set; }
public ControlPropertiesConfig Control { get; set; }
}
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SoftCodec/BlueJeansPc.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SoftCodec/BlueJeansPc.cs
index 735df48c..3e17f81d 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/SoftCodec/BlueJeansPc.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/SoftCodec/BlueJeansPc.cs
@@ -106,8 +106,8 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
- if (dest is IPower)
- (dest as IPower).PowerOff();
+ if (dest is IHasPowerControl)
+ (dest as IHasPowerControl).PowerOff();
}
else
{
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs
index 55e6bf11..ea39bb65 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs
@@ -407,6 +407,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CreateOsdSource();
ExternalSourceListEnabled = props.ExternalSourceListEnabled;
+ ExternalSourceInputPort = props.ExternalSourceInputPort;
if (props.UiBranding == null)
{
@@ -416,6 +417,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
props.UiBranding.BrandingUrl);
BrandingEnabled = props.UiBranding.Enable;
+
_brandingUrl = props.UiBranding.BrandingUrl;
}
@@ -1339,10 +1341,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public override void SendDtmf(string s)
{
- if (CallFavorites != null)
- {
- SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s));
- }
+ SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s));
}
public void SelectPresentationSource(int source)
@@ -1920,7 +1919,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
#region IHasExternalSourceSwitching Members
///
- /// Weather the Cisco supports External Source Lists or not
+ /// Wheather the Cisco supports External Source Lists or not
///
public bool ExternalSourceListEnabled
{
@@ -1928,6 +1927,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
private set;
}
+ ///
+ /// The name of the RoutingInputPort to which the upstream external switcher is connected
+ ///
+ public string ExternalSourceInputPort { get; private set; }
+
public bool BrandingEnabled { get; private set; }
private string _brandingUrl;
private bool _sendMcUrl;
@@ -1970,6 +1974,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
}
+ ///
+ /// Sets the selected source of the available external sources on teh Touch10 UI
+ ///
+ public void SetSelectedSource(string key)
+ {
+ SendText(string.Format("xCommand UserInterface Presentation ExternalSource Select SourceIdentifier: {0}", key));
+ }
+
///
/// Action that will run when the External Source is selected.
///
@@ -2097,7 +2109,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
public CiscoSparkCodecFactory()
{
- TypeNames = new List() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit" };
+ TypeNames = new List() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit", "ciscosparkpluscodec" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs
index cd280b29..1836bafb 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodecPropertiesConfig.cs
@@ -31,9 +31,18 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("sharing")]
public SharingProperties Sharing { get; set; }
+ ///
+ /// Enables external source switching capability
+ ///
[JsonProperty("externalSourceListEnabled")]
public bool ExternalSourceListEnabled { get; set; }
+ ///
+ /// The name of the routing input port on the codec to which the external switch is connected
+ ///
+ [JsonProperty("externalSourceInputPort")]
+ public string ExternalSourceInputPort { get; set; }
+
///
/// Optionsal property to set the limit of any phonebook queries for directory or searching
///
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs
index 23594ce2..171e7bd0 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xEvent.cs
@@ -1,131 +1,131 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
-{
- ///
- /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
- ///
- public class CiscoCodecEvents
- {
- public class CauseValue
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CauseType
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CauseString
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class OrigCallDirection
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class RemoteURI
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class DisplayName
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CallId
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CauseCode
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CauseOrigin
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class Protocol
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class Duration
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CallType
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CallRate
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class Encryption
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class RequestedURI
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class PeopleCountAverage
- {
- public string id { get; set; }
- public string Value { get; set; }
- }
-
- public class CallDisconnect
- {
- public string id { get; set; }
- public CauseValue CauseValue { get; set; }
- public CauseType CauseType { get; set; }
- public CauseString CauseString { get; set; }
- public OrigCallDirection OrigCallDirection { get; set; }
- public RemoteURI RemoteURI { get; set; }
- public DisplayName DisplayName { get; set; }
- public CallId CallId { get; set; }
- public CauseCode CauseCode { get; set; }
- public CauseOrigin CauseOrigin { get; set; }
- public Protocol Protocol { get; set; }
- public Duration Duration { get; set; }
- public CallType CallType { get; set; }
- public CallRate CallRate { get; set; }
- public Encryption Encryption { get; set; }
- public RequestedURI RequestedURI { get; set; }
- public PeopleCountAverage PeopleCountAverage { get; set; }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
+{
+ ///
+ /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
+ ///
+ public class CiscoCodecEvents
+ {
+ public class CauseValue
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CauseType
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CauseString
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class OrigCallDirection
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class RemoteURI
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class DisplayName
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CallId
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CauseCode
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CauseOrigin
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class Protocol
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class Duration
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CallType
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CallRate
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class Encryption
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class RequestedURI
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class PeopleCountAverage
+ {
+ public string id { get; set; }
+ public string Value { get; set; }
+ }
+
+ public class CallDisconnect
+ {
+ public string id { get; set; }
+ public CauseValue CauseValue { get; set; }
+ public CauseType CauseType { get; set; }
+ public CauseString CauseString { get; set; }
+ public OrigCallDirection OrigCallDirection { get; set; }
+ public RemoteURI RemoteURI { get; set; }
+ public DisplayName DisplayName { get; set; }
+ public CallId CallId { get; set; }
+ public CauseCode CauseCode { get; set; }
+ public CauseOrigin CauseOrigin { get; set; }
+ public Protocol Protocol { get; set; }
+ public Duration Duration { get; set; }
+ public CallType CallType { get; set; }
+ public CallRate CallRate { get; set; }
+ public Encryption Encryption { get; set; }
+ public RequestedURI RequestedURI { get; set; }
+ public PeopleCountAverage PeopleCountAverage { get; set; }
}
public class UserInterface
{
@@ -151,16 +151,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
public string id { get; set; }
public string Value { get; set; }
- }
- public class Event
- {
+ }
+ public class Event
+ {
public CallDisconnect CallDisconnect { get; set; }
- public UserInterface UserInterface { get; set; }
- }
-
- public class RootObject
- {
- public Event Event { get; set; }
- }
- }
+ public UserInterface UserInterface { get; set; }
+ }
+
+ public class RootObject
+ {
+ public Event Event { get; set; }
+ }
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs
index 9af52bd2..9ec4fa44 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/xStatus.cs
@@ -1368,8 +1368,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
set
{
- // If the incoming value is "Of" it sets the BoolValue true, otherwise sets it false
- BoolValue = value == "Off";
+ // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
+ BoolValue = value == "On";
OnValueChanged();
}
}
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs
index 5af3c655..0977dea2 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs
@@ -5,6 +5,7 @@ using System.Text;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Ssh;
using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Core.Intersystem;
using PepperDash.Core.Intersystem.Tokens;
@@ -231,12 +232,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
///
protected void SetIsReady()
{
- IsReady = true;
- var h = IsReadyChange;
- if (h != null)
- {
- h(this, new EventArgs());
- }
+ CrestronInvoke.BeginInvoke( (o) =>
+ {
+ try
+ {
+ IsReady = true;
+ var h = IsReadyChange;
+ if (h != null)
+ {
+ h(this, new EventArgs());
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Console(2, this, "Error in SetIsReady() : {0}", e);
+ }
+ });
}
// **** DEBUGGING THINGS ****
diff --git a/packages.config b/packages.config
index 296413b6..c138dd1b 100644
--- a/packages.config
+++ b/packages.config
@@ -1,3 +1,3 @@
-
+
\ No newline at end of file