Merge branch 'main' into bugfix/routingPort-typo-isInternal-Constructor

This commit is contained in:
Neil Dorin 2022-06-22 09:14:31 -06:00 committed by GitHub
commit 0df587071d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
101 changed files with 11687 additions and 6115 deletions

View file

@ -22,7 +22,7 @@ env:
RELEASE_BRANCH: main RELEASE_BRANCH: main
jobs: jobs:
Build_Project: Build_Project:
runs-on: windows-latest runs-on: windows-2019
steps: steps:
# First we checkout the source repo # First we checkout the source repo
- name: Checkout repo - name: Checkout repo
@ -98,7 +98,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Push_Nuget_Package: Push_Nuget_Package:
needs: Build_Project needs: Build_Project
runs-on: windows-latest runs-on: windows-2019
steps: steps:
- name: Download Build Version Info - name: Download Build Version Info
uses: actions/download-artifact@v1 uses: actions/download-artifact@v1

View file

@ -19,7 +19,7 @@ env:
RELEASE_BRANCH: main RELEASE_BRANCH: main
jobs: jobs:
Build_Project: Build_Project:
runs-on: windows-latest runs-on: windows-2019
steps: steps:
# First we checkout the source repo # First we checkout the source repo
- name: Checkout repo - name: Checkout repo
@ -82,7 +82,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Push_Nuget_Package: Push_Nuget_Package:
needs: Build_Project needs: Build_Project
runs-on: windows-latest runs-on: windows-2019
steps: steps:
- name: Download Build Version Info - name: Download Build Version Info
uses: actions/download-artifact@v1 uses: actions/download-artifact@v1

View file

@ -28,6 +28,7 @@ namespace PepperDash.Essentials
HttpLogoServer LogoServer; HttpLogoServer LogoServer;
private CTimer _startTimer; private CTimer _startTimer;
private CEvent _initializeEvent;
private const long StartupTime = 500; private const long StartupTime = 500;
public ControlSystem() public ControlSystem()
@ -46,6 +47,24 @@ namespace PepperDash.Essentials
public override void InitializeSystem() public override void InitializeSystem()
{ {
_startTimer = new CTimer(StartSystem,StartupTime); _startTimer = new CTimer(StartSystem,StartupTime);
// If the control system is a DMPS type, we need to wait to exit this method until all devices have had time to activate
// to allow any HD-BaseT DM endpoints to register first.
if (Global.ControlSystemIsDmpsType)
{
Debug.Console(2, "******************* InitializeSystem() Entering **********************");
_initializeEvent = new CEvent();
DeviceManager.AllDevicesActivated += (o, a) =>
{
_initializeEvent.Set();
Debug.Console(2, "******************* InitializeSystem() Exiting **********************");
};
_initializeEvent.Wait(30000);
}
} }
private void StartSystem(object obj) private void StartSystem(object obj)
@ -361,9 +380,7 @@ namespace PepperDash.Essentials
if(propertiesConfig == null) if(propertiesConfig == null)
propertiesConfig = new DM.Config.DmpsRoutingPropertiesConfig(); propertiesConfig = new DM.Config.DmpsRoutingPropertiesConfig();
var dmpsRoutingController = DmpsRoutingController.GetDmpsRoutingController("processor-avRouting", this.ControllerPrompt, propertiesConfig); DeviceManager.AddDevice(DmpsRoutingController.GetDmpsRoutingController("processor-avRouting", this.ControllerPrompt, propertiesConfig));
DeviceManager.AddDevice(dmpsRoutingController);
} }
else if (this.ControllerPrompt.IndexOf("mpc3", StringComparison.OrdinalIgnoreCase) > -1) else if (this.ControllerPrompt.IndexOf("mpc3", StringComparison.OrdinalIgnoreCase) > -1)
{ {
@ -450,14 +467,13 @@ namespace PepperDash.Essentials
return; return;
} }
uint fusionIpId = 0xf1;
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{ {
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom; var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null) if (room != null)
{ {
// default IPID
uint fusionIpId = 0xf1;
// default to no join map key // default to no join map key
string fusionJoinMapKey = string.Empty; string fusionJoinMapKey = string.Empty;
@ -478,7 +494,7 @@ namespace PepperDash.Essentials
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion"); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey)); DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
@ -490,8 +506,11 @@ namespace PepperDash.Essentials
{ {
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion"); if (!(room is EssentialsCombinedHuddleVtc1Room))
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey)); {
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
@ -502,7 +521,7 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion"); "Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey)); DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge"); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
@ -515,9 +534,13 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room); DeviceManager.AddDevice(room);
} }
fusionIpId += 1;
} }
else else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
} }
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");

View file

@ -150,7 +150,7 @@ namespace PepperDash.Essentials.Fusion
protected override void CreateSymbolAndBasicSigs(uint ipId) protected override void CreateSymbolAndBasicSigs(uint ipId)
{ {
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid); Debug.Console(0, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();

View file

@ -144,12 +144,14 @@
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" /> <Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="Room\Config\EssentialsTechRoomConfig.cs" /> <Compile Include="Room\Config\EssentialsTechRoomConfig.cs" />
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" /> <Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
<Compile Include="Room\Types\EssentialsCombinedHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsDualDisplayRoom.cs" /> <Compile Include="Room\Types\EssentialsDualDisplayRoom.cs" />
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" /> <Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" /> <Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomConfig.cs" /> <Compile Include="Room\Config\EssentialsRoomConfig.cs" />
<Compile Include="Room\Types\EssentialsTechRoom.cs" /> <Compile Include="Room\Types\EssentialsTechRoom.cs" />
<Compile Include="Room\Types\IEssentialsHuddleSpaceRoom.cs" /> <Compile Include="Room\Types\Interfaces\IEssentialsHuddleSpaceRoom.cs" />
<Compile Include="Room\Types\Interfaces\IEssentialsHuddleVtc1Room.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" /> <Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" /> <Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" /> <Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ControlSystem> <ControlSystem>
<Name>192.168.10.1</Name> <Name>Test RMC3</Name>
<Address>auto 192.168.10.1</Address> <Address>auto 192.168.1.40;username crestron</Address>
<ProgramSlot>Program01</ProgramSlot> <ProgramSlot>Program01</ProgramSlot>
<Storage>Internal Flash</Storage> <Storage>Internal Flash</Storage>
</ControlSystem> </ControlSystem>

View file

@ -39,6 +39,10 @@ namespace PepperDash.Essentials.Room.Config
{ {
return new EssentialsDualDisplayRoom(roomConfig); return new EssentialsDualDisplayRoom(roomConfig);
} }
if (typeName == "combinedhuddlevtc1")
{
return new EssentialsCombinedHuddleVtc1Room(roomConfig);
}
return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig); return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig);
} }
@ -201,6 +205,12 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
/// <summary>
/// Indicates if this room represents a combination of other rooms
/// </summary>
[JsonProperty("isRoomCombinationScenario")]
public bool IsRoomCombinationScenario { get; set; }
public EssentialsRoomPropertiesConfig() public EssentialsRoomPropertiesConfig()
{ {
LogoLight = new EssentialsLogoPropertiesConfig(); LogoLight = new EssentialsLogoPropertiesConfig();

View file

@ -56,6 +56,9 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("mirroredTuners")] [JsonProperty("mirroredTuners")]
public Dictionary<uint, string> MirroredTuners { get; set; } public Dictionary<uint, string> MirroredTuners { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary> /// <summary>
/// Indicates the room /// Indicates the room
/// </summary> /// </summary>

View file

@ -0,0 +1,821 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials
{
public class EssentialsCombinedHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room
{
private bool _codecExternalSourceChange;
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSourceChange;
//************************
// Call-related stuff
public BoolFeedback InCallFeedback { get; private set; }
///// <summary>
///// Make this more specific
///// </summary>
//public List<CodecActiveCallItem> ActiveCalls { get; private set; }
/// <summary>
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
/// </summary>
public IntFeedback CallTypeFeedback { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
/// <summary>
/// When something in the room is sharing with the far end or through other means
/// </summary>
public BoolFeedback IsSharingFeedback { get; private set; }
//************************
protected override Func<bool> OnFeedbackFunc
{
get
{
return () =>
{
var displays = Displays.OfType<DisplayBase>().ToList();
var val = CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route
&& displays.Count > 0;
//&& disp.PowerIsOnFeedback.BoolValue;
return val;
};
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsWarmingFeedbackFunc
{
get
{
return () => Displays.OfType<TwoWayDisplayBase>().Any((d) => d.IsWarmingUpFeedback.BoolValue);
}
}
/// <summary>
///
/// </summary>
protected override Func<bool> IsCoolingFeedbackFunc
{
get
{
return () => Displays.OfType<TwoWayDisplayBase>().Any((d) => d.IsCoolingDownFeedback.BoolValue);
}
}
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
private List<IRoutingSinkWithSwitching> Displays;
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public VideoCodecBase VideoCodec { get; private set; }
public AudioCodecBase AudioCodec { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
public string DefaultSourceItem { get; set; }
public ushort DefaultVolume { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
/// tag to device.
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _CurrentAudioDevice; }
set
{
if (value == _CurrentAudioDevice) return;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
// remove from in-use tracker, if so equipped
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
// add to in-use tracking
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
var vc = VideoCodec as IHasExternalSourceSwitching;
if (vc != null && !_codecExternalSourceChange)
{
vc.SetSelectedSource(CurrentSourceInfoKey);
}
_codecExternalSourceChange = false;
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; set; }
/// <summary>
/// "codecOsd"
/// </summary>
public string DefaultCodecRouteString { get { return "codecOsd"; } }
/// <summary>
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
/// always returns the VideoCodec if it is capable
/// </summary>
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
CCriticalSection SourceSelectLock = new CCriticalSection();
public EssentialsCombinedHuddleVtc1Room(DeviceConfig config)
: base(config)
{
try
{
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString());
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
Displays = new List<IRoutingSinkWithSwitching>();
Initialize();
}
catch (Exception e)
{
Debug.Console(1, this, "Error building room: \n{0}", e);
}
}
void Initialize()
{
try
{
if (DefaultAudioDevice is IBasicVolumeControls)
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
else if (DefaultAudioDevice is IHasVolumeDevice)
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
// Combines call feedback from both codecs if available
InCallFeedback = new BoolFeedback(() =>
{
bool inAudioCall = false;
bool inVideoCall = false;
if (AudioCodec != null)
inAudioCall = AudioCodec.IsInCall;
if (VideoCodec != null)
inVideoCall = VideoCodec.IsInCall;
if (inAudioCall || inVideoCall)
return true;
else
return false;
});
SetupDisplays();
// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
Debug.Console(2, this, "Microphone Privacy Config evaluated.");
// Get emergency object, if any
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
Debug.Console(2, this, "Emergency Config evaluated.");
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); };
if (AudioCodec != null)
AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
// link privacy to VC (for now?)
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
CallTypeFeedback = new IntFeedback(() => 0);
SetSourceListKey();
EnablePowerOnToLastSource = true;
}
catch (Exception e)
{
Debug.Console(0, this, "Error Initializing Room: {0}", e);
}
}
private void SetupDisplays()
{
//DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey];
foreach (var destination in destinationList)
{
var dest = destination.Value.SinkDevice as IRoutingSinkWithSwitching;
if (dest != null)
{
Displays.Add(dest);
}
var display = dest as DisplayBase;
if (display != null)
{
// Link power, warming, cooling to display
var dispTwoWay = display as IHasPowerControlWithFeedback;
if (dispTwoWay != null)
{
dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
{
//if (!dispTwoWay.PowerIsOnFeedback.BoolValue)
// CurrentSourceInfo = null;
OnFeedback.FireUpdate();
}
if (dispTwoWay.PowerIsOnFeedback.BoolValue)
{
SetDefaultLevels();
}
};
}
display.IsWarmingUpFeedback.OutputChange += (o, a) =>
{
IsWarmingUpFeedback.FireUpdate();
if (!IsWarmingUpFeedback.BoolValue)
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
};
display.IsCoolingDownFeedback.OutputChange += (o, a) =>
{
IsCoolingDownFeedback.FireUpdate();
};
}
}
}
private void SetSourceListKey()
{
if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey))
{
SetSourceListKey(PropertiesConfig.SourceListKey);
}
else
{
SetSourceListKey(Key);
}
SetCodecExternalSources();
}
protected override void CustomSetConfig(DeviceConfig config)
{
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>(config.Properties.ToString());
if (newPropertiesConfig != null)
PropertiesConfig = newPropertiesConfig;
ConfigWriter.UpdateRoomConfig(config);
}
public override bool CustomActivate()
{
// Add Occupancy object from config
if (PropertiesConfig.Occupancy != null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room");
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
}
this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight();
this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark();
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
return base.CustomActivate();
}
/// <summary>
///
/// </summary>
protected override void EndShutdown()
{
VideoCodec.EndAllCalls();
SetDefaultLevels();
RunDefaultPresentRoute();
CrestronEnvironment.Sleep(1000);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff");
VideoCodec.StopSharing();
VideoCodec.StandbyActivate();
}
/// <summary>
/// Routes the default source item, if any. Returns true when default route exists
/// </summary>
public override bool RunDefaultPresentRoute()
{
if (DefaultSourceItem != null)
RunRouteAction(DefaultSourceItem);
return DefaultSourceItem != null;
}
/// <summary>
/// Sets up the room when started into call mode without presenting a source
/// </summary>
/// <returns></returns>
public bool RunDefaultCallRoute()
{
RunRouteAction(DefaultCodecRouteString);
return true;
}
public void RunRouteActionCodec(string routeKey, string sourceListKey)
{
_codecExternalSourceChange = true;
RunRouteAction(routeKey, sourceListKey);
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, new Action(() => { }));
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey)
{
if (string.IsNullOrEmpty(sourceListKey))
{
Debug.Console(1, this, "No sourceListKey present. RunRouteAction assumes default source list.");
RunRouteAction(routeKey, new Action(() => { }));
}
else
{
Debug.Console(1, this, "sourceListKey present but not yet implemented");
throw new NotImplementedException();
}
}
/// <summary>
///
/// </summary>
/// <param name="routeKey"></param>
/// <param name="souceListKey"></param>
/// <param name="successCallback"></param>
public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback)
{
if (string.IsNullOrEmpty(sourceListKey))
{
RunRouteAction(routeKey, successCallback);
}
else
throw new NotImplementedException();
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
// try to prevent multiple simultaneous selections
SourceSelectLock.TryEnter();
try
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Run route action '{0}'", routeKey);
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
if (dict == null)
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
return;
}
// Try to get the list item by it's string key
if (!dict.ContainsKey(routeKey))
{
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
routeKey, SourceListKey);
return;
}
// End usage timer on last source
if (!string.IsNullOrEmpty(LastSourceKey))
{
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
if (usageLastSource != null && usageLastSource.UsageTracker != null)
{
try
{
// There MAY have been failures in here. Protect
usageLastSource.UsageTracker.EndDeviceUsage();
}
catch (Exception e)
{
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
}
}
}
// Let's run it
var item = dict[routeKey];
if (routeKey.ToLower() != "roomoff")
{
LastSourceKey = routeKey;
}
else
CurrentSourceInfoKey = null;
// hand off the individual routes to this helper
foreach (var route in item.RouteList)
DoRouteItem(route);
// Start usage timer on routed source
var usageNewSource = item.SourceDevice as IUsageTracking;
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
{
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
}
// See if this can be moved into common, base-class method -------------
// Set volume control, using default if non provided
IBasicVolumeControls volDev = null;
// Handle special cases for volume control
if (string.IsNullOrEmpty(item.VolumeControlKey)
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
volDev = DefaultVolumeControls;
//else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
// volDev = DefaultDisplay as IBasicVolumeControls;
// Or a specific device, probably rarely used.
else
{
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
if (dev is IBasicVolumeControls)
volDev = dev as IBasicVolumeControls;
else if (dev is IHasVolumeDevice)
volDev = (dev as IHasVolumeDevice).VolumeDevice;
}
if (volDev != CurrentVolumeControls)
{
// zero the volume on the device we are leaving.
// Set the volume to default on device we are entering
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
vd.SetVolume(0);
}
CurrentVolumeControls = volDev;
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
{
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
vd.SetVolume(vol);
}
}
// -----------------------------------------------------------------------
// store the name and UI info for routes
if (item.SourceKey == "$off")
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = null;
}
else if (item.SourceKey != null)
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = item;
}
OnFeedback.FireUpdate();
if (OnFeedback.BoolValue)
{
if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
{
Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
VideoCodec.StandbyDeactivate();
}
if (VideoCodec.StandbyIsOnFeedback.BoolValue)
{
VideoCodec.StandbyDeactivate();
}
else
{
Debug.Console(1, this, "Video codec not in standby. No need to wake.");
}
}
else
{
Debug.Console(1, this, "Room OnFeedback state: {0}", OnFeedback.BoolValue);
}
// report back when done
if (successCallback != null)
successCallback();
}
catch (Exception e)
{
Debug.Console(1, this, "ERROR in routing: {0}", e);
}
SourceSelectLock.Leave();
}, 0); // end of CTimer
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
void DoRouteItem(SourceRouteListItem route)
{
// if there is a $defaultAll on route, run two separate
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
{
foreach (var display in Displays)
{
var tempVideo = new SourceRouteListItem
{
DestinationKey = display.Key,
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Video
};
DoRoute(tempVideo);
}
}
else
DoRoute(route);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSink dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice as IRoutingSink;
//else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
// dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink;
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
return false;
}
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
if (source == null)
{
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
return false;
}
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
//Implement this
}
/// <summary>
/// Does what it says
/// </summary>
public override void SetDefaultLevels()
{
Debug.Console(1, this, "Restoring default levels");
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
if (vc != null)
vc.SetVolume(DefaultVolume);
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public override void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is IEssentialsRoom && !(d as IEssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as IEssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
/// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary>
private void SetCodecExternalSources()
{
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
{
return;
}
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;
videoCodecWithExternalSwitching.ClearExternalSources();
videoCodecWithExternalSwitching.RunRouteAction = RunRouteActionCodec;
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
foreach (var kvp in srcList)
{
var srcConfig = kvp.Value;
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()
{
var vcWithBranding = VideoCodec as IHasBranding;
if (vcWithBranding == null) return;
Debug.Console(1, this, "Setting Codec Branding");
vcWithBranding.InitializeBranding(Key);
}
#region IPrivacy Members
public void PrivacyModeOff()
{
VideoCodec.PrivacyModeOff();
}
public void PrivacyModeOn()
{
VideoCodec.PrivacyModeOn();
}
public void PrivacyModeToggle()
{
VideoCodec.PrivacyModeToggle();
}
#endregion
}
}

View file

@ -210,7 +210,7 @@ namespace PepperDash.Essentials
{ {
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig> PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
(config.Properties.ToString()); (config.Properties.ToString());
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; DefaultDisplay = DeviceManager.GetDeviceForKey((PropertiesConfig as EssentialsHuddleVtc1PropertiesConfig).DefaultDisplayKey) as IRoutingSinkWithSwitching;
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase; PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;

View file

@ -19,7 +19,7 @@ namespace PepperDash.Essentials
{ {
public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{ {
private readonly EssentialsTechRoomConfig _config; public EssentialsTechRoomConfig PropertiesConfig { get; private set; }
private readonly Dictionary<string, TwoWayDisplayBase> _displays; private readonly Dictionary<string, TwoWayDisplayBase> _displays;
private readonly DevicePresetsModel _tunerPresets; private readonly DevicePresetsModel _tunerPresets;
@ -57,16 +57,16 @@ namespace PepperDash.Essentials
public EssentialsTechRoom(DeviceConfig config) : base(config) public EssentialsTechRoom(DeviceConfig config) : base(config)
{ {
_config = config.Properties.ToObject<EssentialsTechRoomConfig>(); PropertiesConfig = config.Properties.ToObject<EssentialsTechRoomConfig>();
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), _config.PresetsFileName); _tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), PropertiesConfig.PresetsFileName);
_tunerPresets.SetFileName(_config.PresetsFileName); _tunerPresets.SetFileName(PropertiesConfig.PresetsFileName);
_tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled; _tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled;
_tuners = GetDevices<IRSetTopBoxBase>(_config.Tuners); _tuners = GetDevices<IRSetTopBoxBase>(PropertiesConfig.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(_config.Displays); _displays = GetDevices<TwoWayDisplayBase>(PropertiesConfig.Displays);
RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn); RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn);
@ -153,7 +153,7 @@ namespace PepperDash.Essentials
private void CreateOrUpdateScheduledEvents() private void CreateOrUpdateScheduledEvents()
{ {
var eventsConfig = _config.ScheduledEvents; var eventsConfig = PropertiesConfig.ScheduledEvents;
GetOrCreateScheduleGroup(); GetOrCreateScheduleGroup();
@ -207,21 +207,21 @@ namespace PepperDash.Essentials
{ {
//update config based on key of scheduleEvent //update config based on key of scheduleEvent
GetOrCreateScheduleGroup(); GetOrCreateScheduleGroup();
var existingEventIndex = _config.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key); var existingEventIndex = PropertiesConfig.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
if (existingEventIndex < 0) if (existingEventIndex < 0)
{ {
_config.ScheduledEvents.Add(scheduledEvent); PropertiesConfig.ScheduledEvents.Add(scheduledEvent);
} }
else else
{ {
_config.ScheduledEvents[existingEventIndex] = scheduledEvent; PropertiesConfig.ScheduledEvents[existingEventIndex] = scheduledEvent;
} }
//create or update event based on config //create or update event based on config
CreateOrUpdateSingleEvent(scheduledEvent); CreateOrUpdateSingleEvent(scheduledEvent);
//save config //save config
Config.Properties = JToken.FromObject(_config); Config.Properties = JToken.FromObject(PropertiesConfig);
CustomSetConfig(Config); CustomSetConfig(Config);
//Fire Event //Fire Event
@ -230,7 +230,7 @@ namespace PepperDash.Essentials
public List<ScheduledEventConfig> GetScheduledEvents() public List<ScheduledEventConfig> GetScheduledEvents()
{ {
return _config.ScheduledEvents ?? new List<ScheduledEventConfig>(); return PropertiesConfig.ScheduledEvents ?? new List<ScheduledEventConfig>();
} }
private void OnScheduledEventUpdate() private void OnScheduledEventUpdate()
@ -242,14 +242,14 @@ namespace PepperDash.Essentials
return; return;
} }
handler(this, new ScheduledEventEventArgs {ScheduledEvents = _config.ScheduledEvents}); handler(this, new ScheduledEventEventArgs {ScheduledEvents = PropertiesConfig.ScheduledEvents});
} }
public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged; public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type) private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type)
{ {
var eventConfig = _config.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name); var eventConfig = PropertiesConfig.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
if (eventConfig == null) if (eventConfig == null)
{ {
@ -286,11 +286,11 @@ Params: {2}"
{ {
Debug.Console(2, this, "Room Powering On"); Debug.Console(2, this, "Room Powering On");
var dummySource = DeviceManager.GetDeviceForKey(_config.DummySourceKey) as IRoutingOutputs; var dummySource = DeviceManager.GetDeviceForKey(PropertiesConfig.DummySourceKey) as IRoutingOutputs;
if (dummySource == null) if (dummySource == null)
{ {
Debug.Console(1, this, "Unable to get source with key: {0}", _config.DummySourceKey); Debug.Console(1, this, "Unable to get source with key: {0}", PropertiesConfig.DummySourceKey);
return; return;
} }
@ -376,12 +376,12 @@ Params: {2}"
bridge.AddJoinMap(Key, joinMap); bridge.AddJoinMap(Key, joinMap);
} }
if (_config.IsPrimary) if (PropertiesConfig.IsPrimary)
{ {
Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring"); Debug.Console(1, this, "Linking Primary system Tuner Preset Mirroring");
if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0) if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{ {
foreach (var tuner in _config.MirroredTuners) foreach (var tuner in PropertiesConfig.MirroredTuners)
{ {
var f = CurrentPresetsFeedbacks[tuner.Value]; var f = CurrentPresetsFeedbacks[tuner.Value];
@ -423,9 +423,9 @@ Params: {2}"
{ {
Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring"); Debug.Console(1, this, "Linking Secondary system Tuner Preset Mirroring");
if (_config.MirroredTuners != null && _config.MirroredTuners.Count > 0) if (PropertiesConfig.MirroredTuners != null && PropertiesConfig.MirroredTuners.Count > 0)
{ {
foreach (var tuner in _config.MirroredTuners) foreach (var tuner in PropertiesConfig.MirroredTuners)
{ {
var t = _tuners[tuner.Value]; var t = _tuners[tuner.Value];

View file

@ -0,0 +1,24 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
}
}

View file

@ -0,0 +1,27 @@

using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
new BoolFeedback InCallFeedback { get; }
new BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View file

@ -16,6 +16,8 @@ namespace PepperDash.Essentials
{ {
public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject public class EssentialsTouchpanelController : EssentialsDevice, IHasBasicTriListWithSmartObject
{ {
private CrestronTouchpanelPropertiesConfig _propertiesConfig;
public BasicTriListWithSmartObject Panel { get; private set; } public BasicTriListWithSmartObject Panel { get; private set; }
public PanelDriverBase PanelDriver { get; private set; } public PanelDriverBase PanelDriver { get; private set; }
@ -27,7 +29,14 @@ namespace PepperDash.Essentials
: base(key, name) : base(key, name)
{ {
Panel = tsw; Panel = tsw;
tsw.LoadSmartObjects(sgdPath);
if (!string.IsNullOrEmpty(sgdPath))
Panel.LoadSmartObjects(sgdPath);
else
Debug.Console(1, this, "No SGD file path defined");
tsw.SigChange += Panel_SigChange; tsw.SigChange += Panel_SigChange;
} }
@ -37,7 +46,7 @@ namespace PepperDash.Essentials
Panel = dge; Panel = dge;
if (!string.IsNullOrEmpty(sgdPath)) if (!string.IsNullOrEmpty(sgdPath))
dge.LoadSmartObjects(sgdPath); Panel.LoadSmartObjects(sgdPath);
else else
Debug.Console(1, this, "No SGD file path defined"); Debug.Console(1, this, "No SGD file path defined");
@ -50,6 +59,7 @@ namespace PepperDash.Essentials
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id) public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
: base(key, name) : base(key, name)
{ {
_propertiesConfig = props;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware..."); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware...");
type = type.ToLower(); type = type.ToLower();
@ -61,6 +71,8 @@ namespace PepperDash.Essentials
app.ParameterProjectName.Value = props.ProjectName; app.ParameterProjectName.Value = props.ProjectName;
Panel = app; Panel = app;
} }
else if (type == "xpanel")
Panel = new XpanelForSmartGraphics(id, Global.ControlSystem);
else if (type == "tsw550") else if (type == "tsw550")
Panel = new Tsw550(id, Global.ControlSystem); Panel = new Tsw550(id, Global.ControlSystem);
else if (type == "tsw552") else if (type == "tsw552")
@ -134,10 +146,194 @@ namespace PepperDash.Essentials
Panel.LoadSmartObjects(sgdName); Panel.LoadSmartObjects(sgdName);
Panel.SigChange += Panel_SigChange; Panel.SigChange += Panel_SigChange;
AddPostActivationAction(() =>
{
// Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event
var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner;
if (roomCombiner != null)
{
// Subscribe to the even
roomCombiner.RoomCombinationScenarioChanged += new EventHandler<EventArgs>(roomCombiner_RoomCombinationScenarioChanged);
// Connect to the initial roomKey
if (roomCombiner.CurrentScenario != null)
{
// Use the current scenario
DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario);
}
else
{
// Current Scenario not yet set. Use default
SetupPanelDrivers(_propertiesConfig.DefaultRoomKey);
}
}
else
{
// No room combiner, use the default key
SetupPanelDrivers(_propertiesConfig.DefaultRoomKey);
}
});
} }
void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e)
{
var roomCombiner = sender as IEssentialsRoomCombiner;
DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario);
}
/// <summary>
/// Determines the room key to use based on the scenario
/// </summary>
/// <param name="scenario"></param>
void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario)
{
string newRoomKey = null;
if (scenario.UiMap.ContainsKey(Key))
{
newRoomKey = scenario.UiMap[Key];
}
else if (scenario.UiMap.ContainsKey(_propertiesConfig.DefaultRoomKey))
{
newRoomKey = scenario.UiMap[_propertiesConfig.DefaultRoomKey];
}
SetupPanelDrivers(newRoomKey);
}
/// <summary>
/// Sets up drivers and links them to the room specified
/// </summary>
/// <param name="roomKey">key of room to link the drivers to</param>
void SetupPanelDrivers(string roomKey)
{
// Clear out any existing actions
Panel.ClearAllSigActions();
Debug.Console(0, this, "Linking TP '{0}' to Room '{1}'", Key, roomKey);
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, _propertiesConfig);
// Then the sub drivers
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(roomKey);
if (room is IEssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig);
// Header Driver
Debug.Console(0, this, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig);
// AV Driver
Debug.Console(0, this, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, _propertiesConfig);
avDriver.DefaultRoomKey = roomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, this, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else if (room is IEssentialsHuddleVtc1Room)
{
Debug.Console(0, this, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, _propertiesConfig);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, _propertiesConfig);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, _propertiesConfig);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver,
(room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = roomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, this, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, _propertiesConfig);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
LoadAndShowDriver(mainDriver);
}
else
{
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", roomKey);
}
}
public void LoadAndShowDriver(PanelDriverBase driver) public void LoadAndShowDriver(PanelDriverBase driver)
{ {
if (PanelDriver != null)
{
var mainDriver = PanelDriver as EssentialsPanelMainInterfaceDriver;
if (mainDriver != null)
{
mainDriver.Dispose();
}
}
PanelDriver = driver; PanelDriver = driver;
driver.Show(); driver.Show();
} }
@ -148,7 +344,6 @@ namespace PepperDash.Essentials
PanelDriver.BackButtonPressed(); PanelDriver.BackButtonPressed();
} }
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{ {
// If the sig is transitioning on, mark it in case it was home button that transitioned it // If the sig is transitioning on, mark it in case it was home button that transitioned it
@ -225,119 +420,6 @@ namespace PepperDash.Essentials
var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt); var panelController = new EssentialsTouchpanelController(dc.Key, dc.Name, dc.Type, props, comm.IpIdInt);
panelController.AddPostActivationAction(() =>
{
var mainDriver = new EssentialsPanelMainInterfaceDriver(panelController.Panel, props);
// Then the sub drivers
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is IEssentialsHuddleSpaceRoom)
{
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
Debug.Console(0, panelController, "Adding header driver");
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
// AV Driver
Debug.Console(0, panelController, "Adding huddle space AV driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleSpaceRoom;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, panelController, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (panelController.Panel is TswFt5ButtonSystem)
{
var tsw = panelController.Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else if (room is IEssentialsHuddleVtc1Room)
{
Debug.Console(0, panelController, "Adding huddle space VTC AV driver");
// Screen Saver Driver
mainDriver.ScreenSaverController = new ScreenSaverController(mainDriver, props);
// Header Driver
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
// AV Driver
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver,
(room as IEssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
avDriver.SetVideoCodecDriver(codecDriver);
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
avDriver.CurrentRoom = room as IEssentialsHuddleVtc1Room;
// Environment Driver
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
{
Debug.Console(0, panelController, "Adding environment driver");
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
}
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (panelController.Panel is TswFt5ButtonSystem)
{
var tsw = panelController.Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
if (mainDriver.EnvironmentDriver != null)
tsw.Lights.UserObject = new Action<bool>(b =>
{
if (!b)
{
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
mainDriver.EnvironmentDriver.Toggle();
}
});
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
}
}
else
{
Debug.Console(0, panelController, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
}
});
return panelController; return panelController;
} }
} }

View file

@ -14,6 +14,8 @@ namespace PepperDash.Essentials
{ {
public SourceListItem SourceItem { get; private set; } public SourceListItem SourceItem { get; private set; }
private IHasCurrentSourceInfoChange _room;
public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner, public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
SourceListItem sourceItem, Action<bool> routeAction) SourceListItem sourceItem, Action<bool> routeAction)
: base(index, owner) : base(index, owner)
@ -25,6 +27,7 @@ namespace PepperDash.Essentials
public void RegisterForSourceChange(IHasCurrentSourceInfoChange room) public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
{ {
_room = room;
room.CurrentSourceChange -= room_CurrentSourceInfoChange; room.CurrentSourceChange -= room_CurrentSourceInfoChange;
room.CurrentSourceChange += room_CurrentSourceInfoChange; room.CurrentSourceChange += room_CurrentSourceInfoChange;
} }
@ -44,6 +47,9 @@ namespace PepperDash.Essentials
{ {
Owner.BoolInputSig(Index, 1).UserObject = null; Owner.BoolInputSig(Index, 1).UserObject = null;
Owner.StringInputSig(Index, 1).StringValue = ""; Owner.StringInputSig(Index, 1).StringValue = "";
if(_room != null)
_room.CurrentSourceChange -= room_CurrentSourceInfoChange;
} }
/// <summary> /// <summary>

View file

@ -11,7 +11,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController public class EssentialsPanelMainInterfaceDriver : PanelDriverBase, IHasScreenSaverController, IDisposable
{ {
CTimer InactivityTimer; CTimer InactivityTimer;
@ -69,6 +69,35 @@ namespace PepperDash.Essentials
} }
} }
#region IDisposable Members
public void Dispose()
{
var avDriver = AvDriver as PanelDriverBase;
if (avDriver != null)
{
avDriver.Hide();
}
if (ScreenSaverController != null)
{
ScreenSaverController.Dispose();
}
if (HeaderDriver != null)
{
HeaderDriver.Hide();
}
if (EnvironmentDriver != null)
{
EnvironmentDriver.Hide();
}
if (CurrentChildDriver != null)
{
CurrentChildDriver.Hide();
}
}
#endregion
void ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange(Crestron.SimplSharpPro.DeviceExtender currentDeviceExtender, Crestron.SimplSharpPro.SigEventArgs args) void ExtenderTouchDetectionReservedSigs_DeviceExtenderSigChange(Crestron.SimplSharpPro.DeviceExtender currentDeviceExtender, Crestron.SimplSharpPro.SigEventArgs args)
{ {
@ -130,7 +159,7 @@ namespace PepperDash.Essentials
if(CurrentChildDriver != null) if(CurrentChildDriver != null)
CurrentChildDriver.BackButtonPressed(); CurrentChildDriver.BackButtonPressed();
} }
} }
public interface IHasScreenSaverController public interface IHasScreenSaverController
{ {

View file

@ -306,7 +306,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () => TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{ {
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl) if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle(); (CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
}); });

View file

@ -354,7 +354,7 @@ namespace PepperDash.Essentials
TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () => TriList.SetSigFalseAction(UIBoolJoin.DisplayPowerTogglePress, () =>
{ {
if (CurrentRoom != null && CurrentRoom.DefaultDisplay is IHasPowerControl) if (CurrentRoom != null && CurrentRoom.DefaultDisplay != null && CurrentRoom.DefaultDisplay is IHasPowerControl)
(CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle(); (CurrentRoom.DefaultDisplay as IHasPowerControl).PowerToggle();
}); });
@ -493,10 +493,10 @@ namespace PepperDash.Essentials
// and the LastMeetingDismissed != this meeting // and the LastMeetingDismissed != this meeting
var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId); var lastMeetingDismissed = meetings.FirstOrDefault(m => m.Id == LastMeetingDismissedId);
Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*", //Debug.Console(0, "*#* Room on: {0}, lastMeetingDismissedId: {1} {2} *#*",
CurrentRoom.OnFeedback.BoolValue, // CurrentRoom.OnFeedback.BoolValue,
LastMeetingDismissedId, // LastMeetingDismissedId,
lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : ""); // lastMeetingDismissed != null ? lastMeetingDismissed.StartTime.ToString("t", Global.Culture) : "");
var meeting = meetings.LastOrDefault(m => m.Joinable); var meeting = meetings.LastOrDefault(m => m.Joinable);
if (CurrentRoom.OnFeedback.BoolValue if (CurrentRoom.OnFeedback.BoolValue

View file

@ -52,7 +52,7 @@ namespace PepperDash.Essentials
{ {
var prevJoin = CurrentJoin; var prevJoin = CurrentJoin;
var wasShown = _IsShown; var wasShown = _IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join); //Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
if (CurrentJoin == join && TriList.BooleanInput[join].BoolValue) if (CurrentJoin == join && TriList.BooleanInput[join].BoolValue)
return; return;
SetButDontShow(join); SetButDontShow(join);
@ -71,7 +71,7 @@ namespace PepperDash.Essentials
var prevJoin = CurrentJoin; var prevJoin = CurrentJoin;
var wasShown = IsShown; var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join); //Debug.Console(2, "Trilist {0:X2}, interlock swapping {1} for {2}", TriList.ID, CurrentJoin, join);
if (CurrentJoin == join) if (CurrentJoin == join)
HideAndClear(); HideAndClear();
else else
@ -92,7 +92,7 @@ namespace PepperDash.Essentials
{ {
var prevJoin = CurrentJoin; var prevJoin = CurrentJoin;
var wasShown = IsShown; var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin); //Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
Hide(); Hide();
CurrentJoin = 0; CurrentJoin = 0;
@ -108,7 +108,7 @@ namespace PepperDash.Essentials
var prevJoin = CurrentJoin; var prevJoin = CurrentJoin;
var wasShown = IsShown; var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin); //Debug.Console(2, "Trilist {0:X2}, interlock hiding {1}", TriList.ID, CurrentJoin);
if (CurrentJoin > 0) if (CurrentJoin > 0)
{ {
TriList.BooleanInput[CurrentJoin].BoolValue = false; TriList.BooleanInput[CurrentJoin].BoolValue = false;
@ -125,7 +125,7 @@ namespace PepperDash.Essentials
var prevJoin = CurrentJoin; var prevJoin = CurrentJoin;
var wasShown = IsShown; var wasShown = IsShown;
Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin); //Debug.Console(2, "Trilist {0:X2}, interlock showing {1}", TriList.ID, CurrentJoin);
if (CurrentJoin > 0) if (CurrentJoin > 0)
{ {
TriList.BooleanInput[CurrentJoin].BoolValue = true; TriList.BooleanInput[CurrentJoin].BoolValue = true;

View file

@ -12,7 +12,7 @@ namespace PepperDash.Essentials
/// <summary> /// <summary>
/// Driver responsible for controlling the screenshaver showing the client logo, MC connection information and QR Code. Moves the elements around to prevent screen burn in /// Driver responsible for controlling the screenshaver showing the client logo, MC connection information and QR Code. Moves the elements around to prevent screen burn in
/// </summary> /// </summary>
public class ScreenSaverController : PanelDriverBase public class ScreenSaverController : PanelDriverBase, IDisposable
{ {
/// <summary> /// <summary>
@ -42,7 +42,7 @@ namespace PepperDash.Essentials
PositionInterlock = new JoinedSigInterlock(parent.TriList); PositionInterlock = new JoinedSigInterlock(parent.TriList);
var cmdName = String.Format("shwscrsvr-{0}", parent.TriList.ID); var cmdName = String.Format("shwscrsvr-{0:X2}", parent.TriList.ID);
CrestronConsole.AddNewConsoleCommand((o) => Show(), cmdName, "Shows Panel Screensaver", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand((o) => Show(), cmdName, "Shows Panel Screensaver", ConsoleAccessLevelEnum.AccessOperator);
@ -51,6 +51,8 @@ namespace PepperDash.Essentials
public override void Show() public override void Show()
{ {
//Debug.Console(2, "Showing ScreenSaverController: {0:X2}", TriList.ID);
if (_parent.AvDriver != null) if (_parent.AvDriver != null)
{ {
_parent.AvDriver.PopupInterlock.ShowInterlocked(UIBoolJoin.MCScreenSaverVisible); _parent.AvDriver.PopupInterlock.ShowInterlocked(UIBoolJoin.MCScreenSaverVisible);
@ -65,10 +67,11 @@ namespace PepperDash.Essentials
public override void Hide() public override void Hide()
{ {
Debug.Console(1, "Hiding ScreenSaverController"); //Debug.Console(2, "Hiding ScreenSaverController: {0:X2}", TriList.ID);
if (PositionTimer != null) if (PositionTimer != null)
{ {
//Debug.Console(2, "Stopping PositionTimer: {0:X2}", TriList.ID);
PositionTimer.Stop(); PositionTimer.Stop();
PositionTimer.Dispose(); PositionTimer.Dispose();
PositionTimer = null; PositionTimer = null;
@ -86,6 +89,8 @@ namespace PepperDash.Essentials
void StartPositionTimer() void StartPositionTimer()
{ {
//Debug.Console(2, "Starting Position Timer: {0:X2}", TriList.ID);
if (PositionTimer == null) if (PositionTimer == null)
{ {
PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs); PositionTimer = new CTimer((o) => PositionTimerExpired(), PositionTimeoutMs);
@ -117,7 +122,7 @@ namespace PepperDash.Essentials
CurrentPositionIndex = 0; CurrentPositionIndex = 0;
} }
Debug.Console(1, "ScreenSaver Position Timer Expired: Setting new position: {0}", CurrentPositionIndex); //Debug.Console(2, "ScreenSaver Position Timer Expired: Setting new position: {0} ID: {1:X2}", CurrentPositionIndex, TriList.ID);
} }
// //
@ -129,9 +134,19 @@ namespace PepperDash.Essentials
void ClearAllPositions() void ClearAllPositions()
{ {
Debug.Console(1, "Hiding all screensaver positions"); //Debug.Console(2, "Hiding all screensaver positions: {0:X2}", TriList.ID);
PositionInterlock.HideAndClear(); PositionInterlock.HideAndClear();
} }
#region IDisposable Members
public void Dispose()
{
Hide();
}
#endregion
} }
} }

View file

@ -632,7 +632,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
VCControlsInterlock.StatusChanged += new EventHandler<StatusChangedEventArgs>(VCControlsInterlock_StatusChanged); VCControlsInterlock.StatusChanged += new EventHandler<StatusChangedEventArgs>(VCControlsInterlock_StatusChanged);
var codecOffCameras = Codec as IHasCameraOff; var codecOffCameras = Codec as IHasCameraOff;
var supportsCameraOffMode = Codec.SupportsCameraOff; var supportsCameraOffMode = Codec.SupportsCameraOff;
@ -643,6 +642,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (codecAutoCameras != null && supportsAutoCameraMode) if (codecAutoCameras != null && supportsAutoCameraMode)
{ {
CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn()); CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn());
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true; TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true;
codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]); codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]);
@ -672,6 +672,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
} }
}; };
} }
// Manual button always visible // Manual button always visible
@ -683,6 +684,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
if (codecOffCameras != null && supportsCameraOffMode) if (codecOffCameras != null && supportsCameraOffMode)
{ {
TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true; TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true;
codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]); codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]);
CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff()); CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff());
@ -710,6 +712,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
} }
}; };
} }
} }

View file

@ -42,3 +42,6 @@ devjson:2 {"deviceKey":"display01Comm-com", "methodName":"SendText", "params": [
devjson:10 {"deviceKey":"dmLink-ssh", "methodName":"Connect", "params": []} devjson:10 {"deviceKey":"dmLink-ssh", "methodName":"Connect", "params": []}
devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["combined"]}
devjson:2 {"deviceKey":"roomCombiner", "methodName":"SetRoomCombinationScenario", "params": ["divided"]}

View file

@ -46,6 +46,14 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete RawOccupancyUsFeedback = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, public JoinDataComplete RawOccupancyUsFeedback = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 },
new JoinMetadata { Description = "Raw Occupancy Us Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Raw Occupancy Us Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital });
[JoinName("IdentityModeOn")]
public JoinDataComplete IdentityMode = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 },
new JoinMetadata { Description = "Enable Identity Mode", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("IdentityModeFeedback")]
public JoinDataComplete IdentityModeFeedback = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 },
new JoinMetadata { Description = "Identity Mode Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital });
[JoinName("EnableLedFlash")] [JoinName("EnableLedFlash")]
public JoinDataComplete EnableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, public JoinDataComplete EnableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata { Description = "Enable Led Flash", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Enable Led Flash", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });

View file

@ -10,7 +10,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinMetadata new JoinMetadata
{ {
Description = "DM Chassis enable audio breakaway routing", Description = "DM Chassis enable audio breakaway routing",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinMetadata new JoinMetadata
{ {
Description = "DM Chassis enable USB breakaway routing", Description = "DM Chassis enable USB breakaway routing",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -84,6 +84,10 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 }, public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("NoRouteName")]
public JoinDataComplete NoRouteName = new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("InputNames")] [JoinName("InputNames")]
public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
@ -96,7 +100,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData {JoinNumber = 501, JoinSpan = 200}, new JoinDataComplete(new JoinData {JoinNumber = 501, JoinSpan = 200},
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Video Input Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
@ -106,7 +110,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 200 }, new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 200 },
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Audio Input Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
@ -115,7 +119,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 200 }, new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 200 },
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Video Output Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
@ -124,7 +128,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 200 }, new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 200 },
new JoinMetadata new JoinMetadata
{ {
Description = "Video Input Name", Description = "DM Chassis Audio Output Names",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });

View file

@ -28,6 +28,10 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete EdidSerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, public JoinDataComplete EdidSerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata { Description = "DM RMC EDID Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM RMC EDID Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 },
new JoinMetadata { Description = "DM RMC Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("AudioVideoSource")] [JoinName("AudioVideoSource")]
public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });

View file

@ -32,6 +32,10 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM TX Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("VideoInput")] [JoinName("VideoInput")]
public JoinDataComplete VideoInput = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete VideoInput = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX Video Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM TX Video Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
@ -42,7 +46,7 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("HdcpSupportCapability")] [JoinName("HdcpSupportCapability")]
public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata { Description = "DM TX HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "DM TX HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog });
[JoinName("Port1HdcpState")] [JoinName("Port1HdcpState")]
public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 },

View file

@ -7,7 +7,15 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("MasterVolumeLevel")] [JoinName("MasterVolumeLevel")]
public JoinDataComplete MasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete MasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Master Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MasterVolumeLevelScaled")]
public JoinDataComplete MasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MixerPresetRecall")]
public JoinDataComplete MixerPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata { Description = "Mixer Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MasterVolumeMuteOn")] [JoinName("MasterVolumeMuteOn")]
public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
@ -23,11 +31,19 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("MasterVolumeDown")] [JoinName("MasterVolumeDown")]
public JoinDataComplete MasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, public JoinDataComplete MasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Master Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MasterVolumeLevelScaledSend")]
public JoinDataComplete MasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata { Description = "Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SourceVolumeLevel")] [JoinName("SourceVolumeLevel")]
public JoinDataComplete SourceVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, public JoinDataComplete SourceVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Source Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("SourceVolumeLevelScaled")]
public JoinDataComplete SourceVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("SourceVolumeMuteOn")] [JoinName("SourceVolumeMuteOn")]
public JoinDataComplete SourceVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, public JoinDataComplete SourceVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 },
@ -43,11 +59,19 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("SourceVolumeDown")] [JoinName("SourceVolumeDown")]
public JoinDataComplete SourceVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, public JoinDataComplete SourceVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Source Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SourceVolumeLevelScaledSend")]
public JoinDataComplete SourceVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 },
new JoinMetadata { Description = "Source Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec1VolumeLevel")] [JoinName("Codec1VolumeLevel")]
public JoinDataComplete Codec1VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, public JoinDataComplete Codec1VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Codec1 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec1VolumeLevelScaled")]
public JoinDataComplete Codec1VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec1VolumeMuteOn")] [JoinName("Codec1VolumeMuteOn")]
public JoinDataComplete Codec1VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, public JoinDataComplete Codec1VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 },
@ -63,11 +87,19 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("Codec1VolumeDown")] [JoinName("Codec1VolumeDown")]
public JoinDataComplete Codec1VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, public JoinDataComplete Codec1VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Codec1 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec1VolumeLevelScaledSend")]
public JoinDataComplete Codec1VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 },
new JoinMetadata { Description = "Codec1 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec2VolumeLevel")] [JoinName("Codec2VolumeLevel")]
public JoinDataComplete Codec2VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, public JoinDataComplete Codec2VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); new JoinMetadata { Description = "Codec2 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec2VolumeLevelScaled")]
public JoinDataComplete Codec2VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("Codec2VolumeMuteOn")] [JoinName("Codec2VolumeMuteOn")]
public JoinDataComplete Codec2VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, public JoinDataComplete Codec2VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 },
@ -83,8 +115,39 @@ namespace PepperDash.Essentials.Core.Bridges
[JoinName("Codec2VolumeDown")] [JoinName("Codec2VolumeDown")]
public JoinDataComplete Codec2VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, public JoinDataComplete Codec2VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume Mute Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "Codec2 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("Codec2VolumeLevelScaledSend")]
public JoinDataComplete Codec2VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 },
new JoinMetadata { Description = "Codec2 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeLevel")]
public JoinDataComplete MicsMasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicsMasterVolumeLevelScaled")]
public JoinDataComplete MicsMasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicsMasterVolumeMuteOn")]
public JoinDataComplete MicsMasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeMuteOff")]
public JoinDataComplete MicsMasterVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeUp")]
public JoinDataComplete MicsMasterVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeDown")]
public JoinDataComplete MicsMasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 44, JoinSpan = 1 },
new JoinMetadata { Description = "MicsMaster Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicsMasterVolumeLevelScaledSend")]
public JoinDataComplete MicsMasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 45, JoinSpan = 1 },
new JoinMetadata { Description = "Mics Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
/// <summary> /// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it /// Constructor to use when instantiating this Join Map without inheriting from it

View file

@ -0,0 +1,50 @@
using System;
namespace PepperDash.Essentials.Core.Bridges
{
public class DmpsMicrophoneControllerJoinMap : JoinMapBaseAdvanced
{
[JoinName("MicGain")]
public JoinDataComplete MicGain = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Gain dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicGainScaled")]
public JoinDataComplete MicGainScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Gain 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog });
[JoinName("MicMuteOn")]
public JoinDataComplete MicMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicMuteOff")]
public JoinDataComplete MicMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicGainScaledSend")]
public JoinDataComplete MicGainScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Gain Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("MicName")]
public JoinDataComplete MicName = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "Mic Name Get", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
/// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
public DmpsMicrophoneControllerJoinMap(uint joinStart)
: this(joinStart, typeof(DmpsMicrophoneControllerJoinMap))
{
}
/// <summary>
/// Constructor to use when extending this Join map
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
/// <param name="type">Type of the child join map</param>
protected DmpsMicrophoneControllerJoinMap(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
}

View file

@ -4,6 +4,26 @@ namespace PepperDash.Essentials.Core.Bridges
{ {
public class DmpsRoutingControllerJoinMap : JoinMapBaseAdvanced public class DmpsRoutingControllerJoinMap : JoinMapBaseAdvanced
{ {
[JoinName("EnableRouting")]
public JoinDataComplete EnableRouting = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS Enable Audio and Video Routing", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SystemPowerOn")]
public JoinDataComplete SystemPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS System Power On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("SystemPowerOff")]
public JoinDataComplete SystemPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS System Power Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("FrontPanelLockOn")]
public JoinDataComplete FrontPanelLockOn = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS Front Panel Lock On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("FrontPanelLockOff")]
public JoinDataComplete FrontPanelLockOff = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 },
new JoinMetadata { Description = "DMPS Front Panel Lock Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital });
[JoinName("VideoSyncStatus")] [JoinName("VideoSyncStatus")]
public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 },
new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital });
@ -32,6 +52,44 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("InputVideoNames")]
public JoinDataComplete InputVideoNames =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 },
new JoinMetadata
{
Description = "Video Input Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("InputAudioNames")]
public JoinDataComplete InputAudioNames =
new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 },
new JoinMetadata
{
Description = "Audio Input Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("OutputVideoNames")]
public JoinDataComplete OutputVideoNames =
new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 32 },
new JoinMetadata
{
Description = "Video Output Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("OutputAudioNames")]
public JoinDataComplete OutputAudioNames =
new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 32 },
new JoinMetadata
{
Description = "Audio Output Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("OutputCurrentVideoInputNames")] [JoinName("OutputCurrentVideoInputNames")]
public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 }, public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });

View file

@ -5,6 +5,9 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
{ {
public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced
{ {
#region Digital
[JoinName("IsOnline")] [JoinName("IsOnline")]
public JoinDataComplete IsOnline = new JoinDataComplete( public JoinDataComplete IsOnline = new JoinDataComplete(
new JoinData new JoinData
@ -19,19 +22,6 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(
new JoinData
{
JoinNumber = 1,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sensor Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("Enable")] [JoinName("Enable")]
public JoinDataComplete Enable = new JoinDataComplete( public JoinDataComplete Enable = new JoinDataComplete(
@ -103,6 +93,10 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
#endregion
#region Analog
[JoinName("Sensitivity")] [JoinName("Sensitivity")]
public JoinDataComplete Sensitivity = new JoinDataComplete( public JoinDataComplete Sensitivity = new JoinDataComplete(
new JoinData new JoinData
@ -117,6 +111,28 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
#endregion
#region Serial
[JoinName("Name")]
public JoinDataComplete Name = new JoinDataComplete(
new JoinData
{
JoinNumber = 1,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sensor Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
#endregion
/// <summary> /// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it /// Constructor to use when instantiating this Join Map without inheriting from it
/// </summary> /// </summary>

View file

@ -45,7 +45,7 @@ namespace PepperDash.Essentials.Core.Bridges
new JoinMetadata { Description = "Processor Last Boot", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); new JoinMetadata { Description = "Processor Last Boot", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });
[JoinName("ProgramOffsetJoin")] [JoinName("ProgramOffsetJoin")]
public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 5 },
new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None });
[JoinName("ProgramStart")] [JoinName("ProgramStart")]

View file

@ -20,7 +20,21 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("1")] [JoinName("SendDtmfToSpecificCallIndex")]
public JoinDataComplete SendDtmfToSpecificCallIndex = new JoinDataComplete(
new JoinData
{
JoinNumber = 10,
JoinSpan = 1
},
new JoinMetadata
{
Description = "If High, will send DTMF tones to the call set by SelectCall analog. If low sends DTMF tones to last connected call.",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("Dtmf1")]
public JoinDataComplete Dtmf1 = new JoinDataComplete( public JoinDataComplete Dtmf1 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -34,7 +48,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("2")] [JoinName("Dtmf2")]
public JoinDataComplete Dtmf2 = new JoinDataComplete( public JoinDataComplete Dtmf2 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -48,7 +62,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("3")] [JoinName("Dtmf3")]
public JoinDataComplete Dtmf3 = new JoinDataComplete( public JoinDataComplete Dtmf3 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -62,7 +76,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("4")] [JoinName("Dtmf4")]
public JoinDataComplete Dtmf4 = new JoinDataComplete( public JoinDataComplete Dtmf4 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -76,7 +90,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("5")] [JoinName("Dtmf5")]
public JoinDataComplete Dtmf5 = new JoinDataComplete( public JoinDataComplete Dtmf5 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -90,7 +104,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("6")] [JoinName("Dtmf6")]
public JoinDataComplete Dtmf6 = new JoinDataComplete( public JoinDataComplete Dtmf6 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -104,7 +118,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("7")] [JoinName("Dtmf7")]
public JoinDataComplete Dtmf7 = new JoinDataComplete( public JoinDataComplete Dtmf7 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -118,7 +132,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("8")] [JoinName("Dtmf8")]
public JoinDataComplete Dtmf8 = new JoinDataComplete( public JoinDataComplete Dtmf8 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -132,7 +146,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("9")] [JoinName("Dtmf9")]
public JoinDataComplete Dtmf9 = new JoinDataComplete( public JoinDataComplete Dtmf9 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -146,7 +160,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("0")] [JoinName("Dtmf0")]
public JoinDataComplete Dtmf0 = new JoinDataComplete( public JoinDataComplete Dtmf0 = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -160,7 +174,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("*")] [JoinName("DtmfStar")]
public JoinDataComplete DtmfStar = new JoinDataComplete( public JoinDataComplete DtmfStar = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -174,7 +188,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("#")] [JoinName("DtmfPound")]
public JoinDataComplete DtmfPound = new JoinDataComplete( public JoinDataComplete DtmfPound = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -188,8 +202,8 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("EndCall")] [JoinName("EndAllCalls")]
public JoinDataComplete EndCall = new JoinDataComplete( public JoinDataComplete EndAllCalls = new JoinDataComplete(
new JoinData new JoinData
{ {
JoinNumber = 24, JoinNumber = 24,
@ -197,7 +211,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Hang Up", Description = "End All Calls",
JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -226,7 +240,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
new JoinMetadata new JoinMetadata
{ {
Description = "Speed Dial", Description = "Speed Dial",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -281,12 +295,12 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Dial manual string", Description = "Dial manual string specified by CurrentDialString serial join",
JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("DialPhoneCall")] [JoinName("DialPhone")]
public JoinDataComplete DialPhone = new JoinDataComplete( public JoinDataComplete DialPhone = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -314,7 +328,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("EndPhoneCall")] [JoinName("HangUpPhone")]
public JoinDataComplete HangUpPhone = new JoinDataComplete( public JoinDataComplete HangUpPhone = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -323,11 +337,53 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Hang Up PHone", Description = "Hang Up Phone",
JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("EndCallStart")]
public JoinDataComplete EndCallStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 81,
JoinSpan = 8
},
new JoinMetadata
{
Description = "End a specific call by call index. ",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("JoinAllCalls")]
public JoinDataComplete JoinAllCalls = new JoinDataComplete(
new JoinData
{
JoinNumber = 90,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Join all calls",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("JoinCallStart")]
public JoinDataComplete JoinCallStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 91,
JoinSpan = 8
},
new JoinMetadata
{
Description = "Join a specific call by call index. ",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectorySearchBusy")] [JoinName("DirectorySearchBusy")]
public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( public JoinDataComplete DirectorySearchBusy = new JoinDataComplete(
new JoinData new JoinData
@ -408,7 +464,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
new JoinMetadata new JoinMetadata
{ {
Description = "Go to Directory Root", Description = "Go to Directory Root",
JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -440,6 +496,33 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("DirectoryDisableAutoDialSelectedLine")]
public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete(
new JoinData
{
JoinNumber = 107,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Set high to disable automatic dialing of a contact when selected",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryDialSelectedContactMethod")]
public JoinDataComplete DirectoryDialSelectedContactMethod = new JoinDataComplete(
new JoinData
{
JoinNumber = 108,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to dial the selected contact method",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraTiltUp")] [JoinName("CameraTiltUp")]
public JoinDataComplete CameraTiltUp = new JoinDataComplete( public JoinDataComplete CameraTiltUp = new JoinDataComplete(
@ -525,6 +608,48 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("CameraFocusNear")]
public JoinDataComplete CameraFocusNear = new JoinDataComplete(
new JoinData
{
JoinNumber = 117,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Camera Focus Near",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraFocusFar")]
public JoinDataComplete CameraFocusFar = new JoinDataComplete(
new JoinData
{
JoinNumber = 118,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Camera Focus Far",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraFocusAuto")]
public JoinDataComplete CameraFocusAuto = new JoinDataComplete(
new JoinData
{
JoinNumber = 119,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Camera Auto Focus Trigger",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPresetSave")] [JoinName("CameraPresetSave")]
public JoinDataComplete CameraPresetSave = new JoinDataComplete( public JoinDataComplete CameraPresetSave = new JoinDataComplete(
new JoinData new JoinData
@ -534,7 +659,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Save Selected Preset", Description = "Pulse to save selected preset spcified by CameraPresetSelect analog join. FB will pulse for 3s when preset saved.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -548,7 +673,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Camera Mode Auto", Description = "Camera Mode Auto. Enables camera auto tracking mode, with feedback",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -562,7 +687,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Camera Mode Manual", Description = "Camera Mode Manual. Disables camera auto tracking mode, with feedback",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -576,7 +701,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Camera Mode Off", Description = "Camera Mode Off. Disables camera video, with feedback. Works like video mute.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
@ -805,6 +930,34 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("RemoveSelectedRecentCallItem")]
public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete(
new JoinData
{
JoinNumber = 181,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DialSelectedRecentCallItem")]
public JoinDataComplete DialSelectedRecentCallItem = new JoinDataComplete(
new JoinData
{
JoinNumber = 182,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceShareStart")] [JoinName("SourceShareStart")]
public JoinDataComplete SourceShareStart = new JoinDataComplete( public JoinDataComplete SourceShareStart = new JoinDataComplete(
new JoinData new JoinData
@ -870,11 +1023,81 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "advance selfview position", Description = "Toggles selfview position",
JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("HoldAllCalls")]
public JoinDataComplete HoldAllCalls = new JoinDataComplete(
new JoinData
{
JoinNumber = 220,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Holds all calls",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("HoldCallsStart")]
public JoinDataComplete HoldCallsStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 221,
JoinSpan = 8
},
new JoinMetadata
{
Description = "Holds Call at specified index. FB reported on Call Status XSIG",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ResumeCallsStart")]
public JoinDataComplete ResumeCallsStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 231,
JoinSpan = 8
},
new JoinMetadata
{
Description = "Resume Call at specified index",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("MultiSiteOptionIsEnabled")]
public JoinDataComplete MultiSiteOptionIsEnabled = new JoinDataComplete(
new JoinData
{
JoinNumber = 301,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Multi site option is enabled FB",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AutoAnswerEnabled")]
public JoinDataComplete AutoAnswerEnabled = new JoinDataComplete(
new JoinData
{
JoinNumber = 302,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Auto Answer is enabled FB",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ParticipantAudioMuteToggleStart")] [JoinName("ParticipantAudioMuteToggleStart")]
public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(
new JoinData new JoinData
@ -939,6 +1162,35 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
[JoinName("SelectCall")]
public JoinDataComplete SelectCall = new JoinDataComplete(
new JoinData
{
JoinNumber = 24,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sets the selected Call for DTMF commands. Valid values 1-8",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("ConnectedCallCount")]
public JoinDataComplete ConnectedCallCount = new JoinDataComplete(
new JoinData
{
JoinNumber = 25,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the number of currently connected calls",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("MinutesBeforeMeetingStart")] [JoinName("MinutesBeforeMeetingStart")]
public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete(
new JoinData new JoinData
@ -962,11 +1214,25 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Camera Number Select/FB", Description = "Camera Number Select/FB. 1 based index. Valid range is 1 to the value reported by CameraCount.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
[JoinName("CameraCount")]
public JoinDataComplete CameraCount = new JoinDataComplete(
new JoinData
{
JoinNumber = 61,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the number of cameras",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("DirectoryRowCount")] [JoinName("DirectoryRowCount")]
public JoinDataComplete DirectoryRowCount = new JoinDataComplete( public JoinDataComplete DirectoryRowCount = new JoinDataComplete(
new JoinData new JoinData
@ -995,6 +1261,34 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
[JoinName("SelectedContactMethodCount")]
public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete(
new JoinData
{
JoinNumber = 102,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Reports the number of contact methods for the selected contact",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("SelectContactMethod")]
public JoinDataComplete SelectContactMethod = new JoinDataComplete(
new JoinData
{
JoinNumber = 103,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Selects a contact method by index",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("CameraPresetSelect")] [JoinName("CameraPresetSelect")]
public JoinDataComplete CameraPresetSelect = new JoinDataComplete( public JoinDataComplete CameraPresetSelect = new JoinDataComplete(
new JoinData new JoinData
@ -1005,10 +1299,24 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
new JoinMetadata new JoinMetadata
{ {
Description = "Camera Preset Select", Description = "Camera Preset Select",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
[JoinName("FarEndPresetSelect")]
public JoinDataComplete FarEndPresetSelect = new JoinDataComplete(
new JoinData
{
JoinNumber = 122,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Far End Preset Preset Select",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("ParticipantCount")] [JoinName("ParticipantCount")]
public JoinDataComplete ParticipantCount = new JoinDataComplete( public JoinDataComplete ParticipantCount = new JoinDataComplete(
new JoinData new JoinData
@ -1051,6 +1359,48 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Analog JoinType = eJoinType.Analog
}); });
[JoinName("SelectRecentCallItem")]
public JoinDataComplete SelectRecentCallItem = new JoinDataComplete(
new JoinData
{
JoinNumber = 180,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Select/FB for Recent Call Item. Valid values 1 - 10",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("RecentCallOccurrenceType")]
public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete(
new JoinData
{
JoinNumber = 181,
JoinSpan = 10
},
new JoinMetadata
{
Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("RecentCallCount")]
public JoinDataComplete RecentCallCount = new JoinDataComplete(
new JoinData
{
JoinNumber = 191,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Recent Call Count",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
#endregion #endregion
@ -1066,12 +1416,12 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
}, },
new JoinMetadata new JoinMetadata
{ {
Description = "Current Dial String", Description = "Value to dial when ManualDial digital join is pulsed",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
[JoinName("PhoneString")] [JoinName("PhoneDialString")]
public JoinDataComplete PhoneDialString = new JoinDataComplete( public JoinDataComplete PhoneDialString = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -1085,7 +1435,7 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
[JoinName("CurrentCallName")] [JoinName("CurrentCallData")]
public JoinDataComplete CurrentCallData = new JoinDataComplete( public JoinDataComplete CurrentCallData = new JoinDataComplete(
new JoinData new JoinData
{ {
@ -1184,6 +1534,20 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
[JoinName("ContactMethods")]
public JoinDataComplete ContactMethods = new JoinDataComplete(
new JoinData
{
JoinNumber = 103,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Contact Methods - XSig, 10 entries",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CameraPresetNames")] [JoinName("CameraPresetNames")]
public JoinDataComplete CameraPresetNames = new JoinDataComplete( public JoinDataComplete CameraPresetNames = new JoinDataComplete(
new JoinData new JoinData
@ -1198,8 +1562,8 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
[JoinName("CameraLayoutStringFb")] [JoinName("CurrentLayoutStringFb")]
public JoinDataComplete CameraLayoutStringFb = new JoinDataComplete( public JoinDataComplete CurrentLayoutStringFb = new JoinDataComplete(
new JoinData new JoinData
{ {
JoinNumber = 141, JoinNumber = 141,
@ -1226,6 +1590,76 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
[JoinName("CameraNamesFb")]
public JoinDataComplete CameraNamesFb = new JoinDataComplete(
new JoinData
{
JoinNumber = 161,
JoinSpan = 10
},
new JoinMetadata
{
Description = "Camera Name Fb",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SelectedRecentCallName")]
public JoinDataComplete SelectedRecentCallName = new JoinDataComplete(
new JoinData
{
JoinNumber = 171,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Selected Recent Call Name",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SelectedRecentCallNumber")]
public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete(
new JoinData
{
JoinNumber = 172,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Selected Recent Call Number",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("RecentCallNamesStart")]
public JoinDataComplete RecentCallNamesStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 181,
JoinSpan = 10
},
new JoinMetadata
{
Description = "Recent Call Names",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("RecentCallTimesStart")]
public JoinDataComplete RecentCallTimesStart = new JoinDataComplete(
new JoinData
{
JoinNumber = 191,
JoinSpan = 10
},
new JoinMetadata
{
Description = "Recent Calls Times",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentSource")] [JoinName("CurrentSource")]
public JoinDataComplete CurrentSource = new JoinDataComplete( public JoinDataComplete CurrentSource = new JoinDataComplete(
new JoinData new JoinData
@ -1254,6 +1688,76 @@ namespace PepperDash.Essentials.Core.Bridges.JoinMaps
JoinType = eJoinType.Serial JoinType = eJoinType.Serial
}); });
[JoinName("DeviceIpAddresss")]
public JoinDataComplete DeviceIpAddresss = new JoinDataComplete(
new JoinData
{
JoinNumber = 301,
JoinSpan = 1
},
new JoinMetadata
{
Description = "IP Address of device",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SipPhoneNumber")]
public JoinDataComplete SipPhoneNumber = new JoinDataComplete(
new JoinData
{
JoinNumber = 302,
JoinSpan = 1
},
new JoinMetadata
{
Description = "SIP phone number of device",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("E164Alias")]
public JoinDataComplete E164Alias = new JoinDataComplete(
new JoinData
{
JoinNumber = 303,
JoinSpan = 1
},
new JoinMetadata
{
Description = "E164 alias of device",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("H323Id")]
public JoinDataComplete H323Id = new JoinDataComplete(
new JoinData
{
JoinNumber = 304,
JoinSpan = 1
},
new JoinMetadata
{
Description = "H323 ID of device",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SipUri")]
public JoinDataComplete SipUri = new JoinDataComplete(
new JoinData
{
JoinNumber = 305,
JoinSpan = 1
},
new JoinMetadata
{
Description = "SIP URI of device",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntrySelectedName")] [JoinName("DirectoryEntrySelectedName")]
public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete(
new JoinData new JoinData

View file

@ -66,7 +66,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion #endregion
} }
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2nRthsController> public class C2NIoControllerFactory : EssentialsDeviceFactory<C2NIoController>
{ {
public C2NIoControllerFactory() public C2NIoControllerFactory()
{ {

View file

@ -0,0 +1,77 @@
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Wrapper class for CEN-IO-RY-104 relay module
/// </summary>
[Description("Wrapper class for the CEN-IO-RY-104 relay module")]
public class CenIoRy104Controller : EssentialsDevice, IRelayPorts
{
private readonly CenIoRy104 _ry104;
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="ry104"></param>
public CenIoRy104Controller(string key, string name, CenIoRy104 ry104)
: base(key, name)
{
_ry104 = ry104;
}
/// <summary>
/// Relay port collection
/// </summary>
public CrestronCollection<Relay> RelayPorts
{
get { return _ry104.RelayPorts; }
}
/// <summary>
/// Number of relay ports property
/// </summary>
public int NumberOfRelayPorts
{
get { return _ry104.NumberOfRelayPorts; }
}
}
/// <summary>
/// CEN-IO-RY Controller factory
/// </summary>
public class CenIoRy104ControllerFactory : EssentialsDeviceFactory<CenIoRy104Controller>
{
/// <summary>
/// Constructor
/// </summary>
public CenIoRy104ControllerFactory()
{
TypeNames = new List<string>() { "ceniory104" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create a new CEN-IO-RY-104 Device");
var controlPropertiesConfig = CommFactory.GetControlPropertiesConfig(dc);
if (controlPropertiesConfig == null)
{
Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device");
return null;
}
var ipid = controlPropertiesConfig.IpIdInt;
if (ipid != 0) return new CenIoRy104Controller(dc.Key, dc.Name, new CenIoRy104(ipid, Global.ControlSystem));
Debug.Console(1, "Factory failed to create a new CEN-IO-RY-104 Device using IP-ID-{0}", ipid);
return null;
}
}
}

View file

@ -69,19 +69,28 @@ namespace PepperDash.Essentials.Core
public override bool CustomActivate() public override bool CustomActivate()
{ {
Debug.Console(0, this, "Activating"); Debug.Console(0, this, "Activating");
if (!PreventRegistration) if (!PreventRegistration)
{ {
//Debug.Console(1, this, " Does not require registration. Skipping"); //Debug.Console(1, this, " Does not require registration. Skipping");
var response = Hardware.RegisterWithLogging(Key); var response = Hardware.RegisterWithLogging(Key);
if (response != eDeviceRegistrationUnRegistrationResponse.Success) if (response != eDeviceRegistrationUnRegistrationResponse.Success)
{ {
//Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); //Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response);
return false; return false;
} }
IsRegistered.FireUpdate(); IsRegistered.FireUpdate();
} }
else
{
AddPostActivationAction(() =>
{
var response = Hardware.RegisterWithLogging(Key);
IsRegistered.FireUpdate();
});
}
foreach (var f in Feedbacks) foreach (var f in Feedbacks)
{ {

View file

@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary> /// </summary>
public interface IMobileControl : IKeyed public interface IMobileControl : IKeyed
{ {
void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent); void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
void LinkSystemMonitorToAppServer(); void LinkSystemMonitorToAppServer();
} }

View file

@ -60,6 +60,7 @@ namespace PepperDash.Essentials.Core
DeviceCriticalSection.Enter(); DeviceCriticalSection.Enter();
AddDeviceEnabled = false; AddDeviceEnabled = false;
// PreActivate all devices // PreActivate all devices
Debug.Console(0,"****PreActivation starting...****");
foreach (var d in Devices.Values) foreach (var d in Devices.Values)
{ {
try try
@ -69,9 +70,12 @@ namespace PepperDash.Essentials.Core
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e); Debug.Console(0, d, "ERROR: Device {1} PreActivation failure: {0}", e.Message, d.Key);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
} }
} }
Debug.Console(0, "****PreActivation complete****");
Debug.Console(0, "****Activation starting...****");
// Activate all devices // Activate all devices
foreach (var d in Devices.Values) foreach (var d in Devices.Values)
@ -83,10 +87,14 @@ namespace PepperDash.Essentials.Core
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e); Debug.Console(0, d, "ERROR: Device {1} Activation failure: {0}", e.Message, d.Key);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
} }
} }
Debug.Console(0, "****Activation complete****");
Debug.Console(0, "****PostActivation starting...****");
// PostActivate all devices // PostActivate all devices
foreach (var d in Devices.Values) foreach (var d in Devices.Values)
{ {
@ -97,10 +105,13 @@ namespace PepperDash.Essentials.Core
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e); Debug.Console(0, d, "ERROR: Device {1} PostActivation failure: {0}", e.Message, d.Key);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
} }
} }
Debug.Console(0, "****PostActivation complete****");
OnAllDevicesActivated(); OnAllDevicesActivated();
} }
finally finally

View file

@ -57,7 +57,7 @@ namespace PepperDash.Essentials.Core
public DescriptionAttribute(string description) public DescriptionAttribute(string description)
{ {
Debug.Console(2, "Setting Description: {0}", description); //Debug.Console(2, "Setting Description: {0}", description);
_Description = description; _Description = description;
} }
@ -74,7 +74,7 @@ namespace PepperDash.Essentials.Core
public ConfigSnippetAttribute(string configSnippet) public ConfigSnippetAttribute(string configSnippet)
{ {
Debug.Console(2, "Setting Config Snippet {0}", configSnippet); //Debug.Console(2, "Setting Config Snippet {0}", configSnippet);
_ConfigSnippet = configSnippet; _ConfigSnippet = configSnippet;
} }
@ -103,7 +103,7 @@ namespace PepperDash.Essentials.Core
{ {
foreach (var typeName in TypeNames) foreach (var typeName in TypeNames)
{ {
Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); //Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
string description = descriptionAttribute[0].Description; string description = descriptionAttribute[0].Description;
var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];

View file

@ -112,6 +112,11 @@ namespace PepperDash.Essentials.Core
public override void ExecuteSwitch(object selector) public override void ExecuteSwitch(object selector)
{ {
Debug.Console(2, this, "ExecuteSwitch: {0}", selector); Debug.Console(2, this, "ExecuteSwitch: {0}", selector);
if (!_PowerIsOn)
{
PowerOn();
}
} }

View file

@ -69,13 +69,13 @@ namespace PepperDash.Essentials.Core
/// <returns></returns> /// <returns></returns>
public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method) public static void AddFactoryForType(string typeName, Func<DeviceConfig, IKeyed> method)
{ {
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); //Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method});
} }
public static void AddFactoryForType(string typeName, string description, CType cType, Func<DeviceConfig, IKeyed> method) public static void AddFactoryForType(string typeName, string description, CType cType, Func<DeviceConfig, IKeyed> method)
{ {
Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName); //Debug.Console(1, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
if(FactoryMethods.ContainsKey(typeName)) if(FactoryMethods.ContainsKey(typeName))
{ {

View file

@ -62,6 +62,11 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc; ValueFunc = valueFunc;
} }
public void SetValueFunc(Func<bool> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate() public override void FireUpdate()
{ {
bool newValue = InTestMode ? TestValue : ValueFunc.Invoke(); bool newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View file

@ -51,6 +51,12 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc; ValueFunc = valueFunc;
} }
public void SetValueFunc(Func<int> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate() public override void FireUpdate()
{ {
var newValue = InTestMode ? TestValue : ValueFunc.Invoke(); var newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View file

@ -52,7 +52,10 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc; ValueFunc = valueFunc;
} }
public void SetValueFunc(Func<string> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate() public override void FireUpdate()
{ {

View file

@ -119,7 +119,19 @@ namespace PepperDash.Essentials.Core.Fusion
var slot = Global.ControlSystem.ProgramNumber; var slot = Global.ControlSystem.ProgramNumber;
var guidFilePath = Global.FilePathPrefix + var guidFilePath = Global.FilePathPrefix +
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag); string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _ipId);
var oldGuidFilePath = Global.FilePathPrefix +
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
if (File.Exists(oldGuidFilePath))
{
Debug.Console(0, this, "Migrating from old Fusion GUID file to new Fusion GUID File");
File.Copy(oldGuidFilePath, guidFilePath);
File.Delete(oldGuidFilePath);
}
_guidFileExists = File.Exists(guidFilePath); _guidFileExists = File.Exists(guidFilePath);
@ -149,19 +161,7 @@ namespace PepperDash.Essentials.Core.Fusion
} }
AddPostActivationAction(() => AddPostActivationAction(() => PostActivate(guidFilePath));
{
CreateSymbolAndBasicSigs(_ipId);
SetUpSources();
SetUpCommunitcationMonitors();
SetUpDisplay();
SetUpError();
ExecuteCustomSteps();
FusionRVI.GenerateFileForAllFusionDevices();
GenerateGuidFile(guidFilePath);
});
} }
catch (Exception e) catch (Exception e)
{ {
@ -169,6 +169,20 @@ namespace PepperDash.Essentials.Core.Fusion
} }
} }
private void PostActivate(string guidFilePath)
{
CreateSymbolAndBasicSigs(_ipId);
SetUpSources();
SetUpCommunitcationMonitors();
SetUpDisplay();
SetUpError();
ExecuteCustomSteps();
FusionRVI.GenerateFileForAllFusionDevices();
GenerateGuidFile(guidFilePath);
}
protected string RoomGuid protected string RoomGuid
{ {
get { return _guiDs.RoomGuid; } get { return _guiDs.RoomGuid; }
@ -314,7 +328,7 @@ namespace PepperDash.Essentials.Core.Fusion
protected virtual void CreateSymbolAndBasicSigs(uint ipId) protected virtual void CreateSymbolAndBasicSigs(uint ipId)
{ {
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0}", RoomGuid); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();

View file

@ -32,6 +32,27 @@ namespace PepperDash.Essentials.Core
// TODO: consider making this configurable later // TODO: consider making this configurable later
public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US"); public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US");
/// <summary>
/// True when the processor type is a DMPS variant
/// </summary>
public static bool ControlSystemIsDmpsType
{
get
{
return ControlSystem.ControllerPrompt.ToLower().IndexOf("dmps") > -1;
}
}
/// <summary>
/// True when the processor type is a DMPS 4K variant
/// </summary>
public static bool ControlSystemIsDmps4kType
{
get
{
return ControlSystemIsDmpsType && ControlSystem.ControllerPrompt.ToLower().IndexOf("4k") > -1;
}
}
/// <summary> /// <summary>
/// The file path prefix to the folder containing configuration files /// The file path prefix to the folder containing configuration files

View file

@ -16,11 +16,28 @@ namespace PepperDash.Essentials.Core
/// <summary> /// <summary>
/// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when /// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when
/// statuses change. /// statuses change.
/// Default monitoring uses TextReceived event on Client.
/// </summary> /// </summary>
public class GenericCommunicationMonitor : StatusMonitorBase public class GenericCommunicationMonitor : StatusMonitorBase
{ {
public IBasicCommunication Client { get; private set; } public IBasicCommunication Client { get; private set; }
/// <summary>
/// Will monitor Client.BytesReceived if set to true. Otherwise the default is to monitor Client.TextReceived
/// </summary>
public bool MonitorBytesReceived { get; private set; }
/// <summary>
/// Return true if the Client is ISocketStatus
/// </summary>
public bool IsSocket
{
get
{
return Client is ISocketStatus;
}
}
long PollTime; long PollTime;
CTimer PollTimer; CTimer PollTimer;
string PollString; string PollString;
@ -46,8 +63,20 @@ namespace PepperDash.Essentials.Core
Client = client; Client = client;
PollTime = pollTime; PollTime = pollTime;
PollString = pollString; PollString = pollString;
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
} }
public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime,
long warningTime, long errorTime, string pollString, bool monitorBytesReceived) :
this(parent, client, pollTime, warningTime, errorTime, pollString)
{
SetMonitorBytesReceived(monitorBytesReceived);
}
/// <summary> /// <summary>
/// Poll is a provided action instead of string /// Poll is a provided action instead of string
/// </summary> /// </summary>
@ -69,6 +98,19 @@ namespace PepperDash.Essentials.Core
Client = client; Client = client;
PollTime = pollTime; PollTime = pollTime;
PollAction = pollAction; PollAction = pollAction;
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
}
public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime,
long warningTime, long errorTime, Action pollAction, bool monitorBytesReceived) :
this(parent, client, pollTime, warningTime, errorTime, pollAction)
{
SetMonitorBytesReceived(monitorBytesReceived);
} }
@ -79,23 +121,96 @@ namespace PepperDash.Essentials.Core
CommunicationMonitorConfig props) : CommunicationMonitorConfig props) :
this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString)
{ {
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
} }
/// <summary>
/// Builds the monitor from a config object and takes a bool to specify whether to monitor BytesReceived
/// Default is to monitor TextReceived
/// </summary>
/// <param name="parent"></param>
/// <param name="client"></param>
/// <param name="props"></param>
/// <param name="monitorBytesReceived"></param>
public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props, bool monitorBytesReceived) :
this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString)
{
SetMonitorBytesReceived(monitorBytesReceived);
}
void SetMonitorBytesReceived(bool monitorBytesReceived)
{
MonitorBytesReceived = monitorBytesReceived;
}
public override void Start() public override void Start()
{ {
Client.BytesReceived += Client_BytesReceived; if (MonitorBytesReceived)
Poll(); {
PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime); Client.BytesReceived += Client_BytesReceived;
}
else
{
Client.TextReceived += Client_TextReceived;
}
if (!IsSocket)
{
BeginPolling();
}
} }
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
if (!e.Client.IsConnected)
{
// Immediately stop polling and notify that device is offline
Stop();
Status = MonitorStatus.InError;
ResetErrorTimers();
}
else
{
// Start polling and set status to unknow and let poll result update the status to IsOk when a response is received
Status = MonitorStatus.StatusUnknown;
Start();
BeginPolling();
}
}
void BeginPolling()
{
Poll();
PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime);
}
public override void Stop() public override void Stop()
{ {
Client.BytesReceived -= this.Client_BytesReceived; if(MonitorBytesReceived)
PollTimer.Stop(); {
PollTimer = null; Client.BytesReceived -= this.Client_BytesReceived;
StopErrorTimers(); }
else
{
Client.TextReceived -= Client_TextReceived;
}
if (PollTimer != null)
{
PollTimer.Stop();
PollTimer = null;
StopErrorTimers();
}
} }
void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e)
{
DataReceived();
}
/// <summary> /// <summary>
/// Upon any receipt of data, set everything to ok! /// Upon any receipt of data, set everything to ok!
/// </summary> /// </summary>
@ -103,10 +218,14 @@ namespace PepperDash.Essentials.Core
/// <param name="e"></param> /// <param name="e"></param>
void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{ {
Status = MonitorStatus.IsOk; DataReceived();
ResetErrorTimers(); }
//
} void DataReceived()
{
Status = MonitorStatus.IsOk;
ResetErrorTimers();
}
void Poll() void Poll()
{ {
@ -124,19 +243,6 @@ namespace PepperDash.Essentials.Core
Debug.Console(2, this, "Comm not connected"); Debug.Console(2, this, "Comm not connected");
} }
} }
/// <summary>
/// When the client connects, and we're waiting for it, respond and disconect from event
/// </summary>
void OneTimeConnectHandler(object o, EventArgs a)
{
if (Client.IsConnected)
{
//Client.IsConnected -= OneTimeConnectHandler;
Debug.Console(2, this, "Comm connected");
Poll();
}
}
} }

View file

@ -301,7 +301,7 @@ namespace PepperDash.Essentials.Core.Monitoring
p.Value.AggregatedProgramInfoFeedback.LinkInputSig( p.Value.AggregatedProgramInfoFeedback.LinkInputSig(
trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]); trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]);
programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinNumber; programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinSpan;
} }
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Resources;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
@ -61,6 +62,8 @@ namespace PepperDash.Essentials.Core
public BoolFeedback RawOccupancyUsFeedback { get; private set; } public BoolFeedback RawOccupancyUsFeedback { get; private set; }
public BoolFeedback IdentityModeFeedback { get; private set; }
// Debug properties // Debug properties
public bool InTestMode { get; private set; } public bool InTestMode { get; private set; }
@ -117,6 +120,8 @@ namespace PepperDash.Essentials.Core
RawOccupancyUsFeedback = new BoolFeedback(() => OccSensor.RawOccupancyDetectedByUltrasonicSensorFeedback.BoolValue); RawOccupancyUsFeedback = new BoolFeedback(() => OccSensor.RawOccupancyDetectedByUltrasonicSensorFeedback.BoolValue);
IdentityModeFeedback = new BoolFeedback(()=>OccSensor.IdentityModeOnFeedback.BoolValue);
UltrasonicSensitivityInVacantStateFeedback = new IntFeedback(() => (int)OccSensor.UltrasonicSensorSensitivityInVacantStateFeedback); UltrasonicSensitivityInVacantStateFeedback = new IntFeedback(() => (int)OccSensor.UltrasonicSensorSensitivityInVacantStateFeedback);
UltrasonicSensitivityInOccupiedStateFeedback = new IntFeedback(() => (int)OccSensor.UltrasonicSensorSensitivityInOccupiedStateFeedback); UltrasonicSensitivityInOccupiedStateFeedback = new IntFeedback(() => (int)OccSensor.UltrasonicSensorSensitivityInOccupiedStateFeedback);
@ -199,6 +204,27 @@ namespace PepperDash.Essentials.Core
{ {
SetAndWhenVacatedState((bool)PropertiesConfig.AndWhenVacatedState); SetAndWhenVacatedState((bool)PropertiesConfig.AndWhenVacatedState);
} }
// TODO [ ] feature/cenoodtcpoe-sensor-sensitivity-configuration
if (PropertiesConfig.UsSensitivityOccupied != null)
{
SetUsSensitivityOccupied((ushort)PropertiesConfig.UsSensitivityOccupied);
}
if (PropertiesConfig.UsSensitivityVacant != null)
{
SetUsSensitivityVacant((ushort)PropertiesConfig.UsSensitivityVacant);
}
if (PropertiesConfig.PirSensitivityOccupied != null)
{
SetPirSensitivityOccupied((ushort)PropertiesConfig.PirSensitivityOccupied);
}
if (PropertiesConfig.PirSensitivityVacant != null)
{
SetPirSensitivityVacant((ushort)PropertiesConfig.PirSensitivityVacant);
}
} }
/// <summary> /// <summary>
@ -279,7 +305,21 @@ namespace PepperDash.Essentials.Core
} }
} }
/// <summary> /// <summary>
/// Sets the identity mode on or off
/// </summary>
/// <param name="state"></param>
public void SetIdentityMode(bool state)
{
if (state)
OccSensor.IdentityModeOn();
else
OccSensor.IdentityModeOff();
Debug.Console(1, this, "Identity Mode: {0}", OccSensor.IdentityModeOnFeedback.BoolValue ? "On" : "Off");
}
/// <summary>
/// Enables or disables the PIR sensor /// Enables or disables the PIR sensor
/// </summary> /// </summary>
/// <param name="state"></param> /// <param name="state"></param>
@ -506,6 +546,54 @@ namespace PepperDash.Essentials.Core
} }
} }
/// <summary>
/// Sets the US sensor sensitivity for occupied state
/// </summary>
/// <param name="sensitivity"></param>
public void SetUsSensitivityOccupied(ushort sensitivity)
{
var level = (eSensitivityLevel) sensitivity;
if (level == 0) return;
OccSensor.UltrasonicSensorSensitivityInOccupiedState = level;
}
/// <summary>
/// Sets the US sensor sensitivity for vacant state
/// </summary>
/// <param name="sensitivity"></param>
public void SetUsSensitivityVacant(ushort sensitivity)
{
var level = (eSensitivityLevel)sensitivity;
if (level == 0) return;
OccSensor.UltrasonicSensorSensitivityInVacantState = level;
}
/// <summary>
/// Sets the PIR sensor sensitivity for occupied state
/// </summary>
/// <param name="sensitivity"></param>
public void SetPirSensitivityOccupied(ushort sensitivity)
{
var level = (eSensitivityLevel)sensitivity;
if (level == 0) return;
OccSensor.PassiveInfraredSensorSensitivityInOccupiedState = level;
}
/// <summary>
/// Sets the PIR sensor sensitivity for vacant state
/// </summary>
/// <param name="sensitivity"></param>
public void SetPirSensitivityVacant(ushort sensitivity)
{
var level = (eSensitivityLevel)sensitivity;
if (level == 0) return;
OccSensor.PassiveInfraredSensorSensitivityInVacantState = level;
}
/// <summary> /// <summary>
/// Method to print current settings to console /// Method to print current settings to console
/// </summary> /// </summary>
@ -649,6 +737,9 @@ namespace PepperDash.Essentials.Core
occController.RawOccupancyPirFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RawOccupancyPirFeedback.JoinNumber]); occController.RawOccupancyPirFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RawOccupancyPirFeedback.JoinNumber]);
occController.RawOccupancyUsFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RawOccupancyUsFeedback.JoinNumber]); occController.RawOccupancyUsFeedback.LinkInputSig(trilist.BooleanInput[joinMap.RawOccupancyUsFeedback.JoinNumber]);
// Identity mode
trilist.SetBoolSigAction(joinMap.IdentityMode.JoinNumber, occController.SetIdentityMode);
occController.IdentityModeFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IdentityModeFeedback.JoinNumber]);
} }
public class CenOdtOccupancySensorBaseControllerFactory : EssentialsDeviceFactory<CenOdtOccupancySensorBaseController> public class CenOdtOccupancySensorBaseControllerFactory : EssentialsDeviceFactory<CenOdtOccupancySensorBaseController>

View file

@ -47,5 +47,35 @@ namespace PepperDash.Essentials.Core
[JsonProperty("andWhenVacatedState")] [JsonProperty("andWhenVacatedState")]
public bool? AndWhenVacatedState { get; set; } public bool? AndWhenVacatedState { get; set; }
// PoE Sensors: CenOdtCPoe
/// <summary>
/// Sets the sensitivity level for US while sensor is in occupied state
/// 1 = low; 2 = medium; 3 = high; 4 = xlow; 5 = 2xlow; 6 = 3xlow
/// </summary>
[JsonProperty("usSensitivityOccupied")]
public ushort? UsSensitivityOccupied { get; set; }
/// <summary>
/// Sets the sensitivity level for US while sensor is in vacant state
/// 1 = low; 2 = medium; 3 = high; 4 = xlow; 5 = 2xlow; 6 = 3xlow
/// </summary>
[JsonProperty("usSensitivityVacant")]
public ushort? UsSensitivityVacant { get; set; }
/// <summary>
/// Sets the sensitivity level for PIR while sensor is in occupied state
/// 1 = low; 2 = medium; 3 = high
/// </summary>
[JsonProperty("pirSensitivityOccupied")]
public ushort? PirSensitivityOccupied { get; set; }
/// <summary>
/// Sets the sensitivity level for PIR while sensor is in vacant state
/// 1 = low; 2 = medium; 3 = high
/// </summary>
[JsonProperty("pirSensitivityVacant")]
public ushort? PirSensitivityVacant { get; set; }
} }
} }

View file

@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Represents an abstract controller device for a partition dividing rooms that are combinable
///
/// In Auto mode, it can use a partition sensor to automatically determine whether the partition is present.
///
/// In Manual mode it accepts user input to tell it whether the partition is present.
/// </summary>
public class EssentialsPartitionController : IPartitionController
{
private IPartitionStateProvider _partitionSensor;
private bool isInAutoMode;
private bool partitionPresent;
public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List<string> adjacentRoomKeys)
{
Key = key;
Name = name;
AdjacentRoomKeys = adjacentRoomKeys;
if (sensor != null)
{
_partitionSensor = sensor;
if (!defaultToManualMode)
{
SetAutoMode();
}
else
{
SetManualMode();
}
}
else
{
SetManualMode();
}
PartitionPresentFeedback.FireUpdate();
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
if (isInAutoMode)
{
PartitionPresentFeedback.FireUpdate();
}
}
#region IPartitionController Members
public List<string> AdjacentRoomKeys { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
}
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
}
}
public void SetManualMode()
{
isInAutoMode = false;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => partitionPresent);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => partitionPresent);
}
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
}
}
public void SetPartitionStatePresent()
{
if (!isInAutoMode)
{
partitionPresent = true;
PartitionPresentFeedback.FireUpdate();
}
}
public void SetPartitionStateNotPresent()
{
if (!isInAutoMode)
{
partitionPresent = false;
PartitionPresentFeedback.FireUpdate();
}
}
public void ToggglePartitionState()
{
if (!isInAutoMode)
{
partitionPresent = !partitionPresent;
PartitionPresentFeedback.FireUpdate();
}
}
#endregion
#region IPartitionStateProvider Members
public BoolFeedback PartitionPresentFeedback { get; private set; }
#endregion
#region IKeyName Members
public string Name { get; private set; }
#endregion
#region IKeyed Members
public string Key { get; private set; }
#endregion
}
}

View file

@ -1,4 +1,5 @@
using Crestron.SimplSharpPro; using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.GeneralIO; using Crestron.SimplSharpPro.GeneralIO;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -9,17 +10,20 @@ using PepperDash.Essentials.Core.Bridges.JoinMaps;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
using PepperDash_Essentials_Core.PartitionSensor;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
[Description("Wrapper class for GLS Cresnet Partition Sensor")] [Description("Wrapper class for GLS Cresnet Partition Sensor")]
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice, IPartitionStateProvider
{ {
private GlsPartCn _partitionSensor;
public StringFeedback NameFeedback { get; private set; } public GlsPartitionSensorPropertiesConfig PropertiesConfig { get; private set; }
private GlsPartCn _partitionSensor;
public BoolFeedback EnableFeedback { get; private set; } public BoolFeedback EnableFeedback { get; private set; }
public BoolFeedback PartitionSensedFeedback { get; private set; } public BoolFeedback PartitionPresentFeedback { get; private set; }
public BoolFeedback PartitionNotSensedFeedback { get; private set; } public BoolFeedback PartitionNotSensedFeedback { get; private set; }
public IntFeedback SensitivityFeedback { get; private set; } public IntFeedback SensitivityFeedback { get; private set; }
@ -32,23 +36,71 @@ namespace PepperDash.Essentials.Core
public GlsPartitionSensorController(string key, Func<DeviceConfig, GlsPartCn> preActivationFunc, DeviceConfig config) public GlsPartitionSensorController(string key, Func<DeviceConfig, GlsPartCn> preActivationFunc, DeviceConfig config)
: base(key, config.Name) : base(key, config.Name)
{ {
var props = config.Properties.ToObject<GlsPartitionSensorPropertiesConfig>();
if (props != null)
{
PropertiesConfig = props;
}
else
{
Debug.Console(1, this, "props are null. Unable to deserialize into GlsPartSensorPropertiesConfig");
}
AddPreActivationAction(() => AddPreActivationAction(() =>
{ {
_partitionSensor = preActivationFunc(config); _partitionSensor = preActivationFunc(config);
RegisterCrestronGenericBase(_partitionSensor); RegisterCrestronGenericBase(_partitionSensor);
NameFeedback = new StringFeedback(() => Name); EnableFeedback = new BoolFeedback(() => InTestMode ? TestEnableFeedback : _partitionSensor.EnableFeedback.BoolValue);
EnableFeedback = new BoolFeedback(() => _partitionSensor.EnableFeedback.BoolValue); PartitionPresentFeedback = new BoolFeedback(() => InTestMode ? TestPartitionSensedFeedback : _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue); PartitionNotSensedFeedback = new BoolFeedback(() => InTestMode ? !TestPartitionSensedFeedback : _partitionSensor.PartitionNotSensedFeedback.BoolValue);
PartitionNotSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionNotSensedFeedback.BoolValue); SensitivityFeedback = new IntFeedback(() => InTestMode ? TestSensitivityFeedback : _partitionSensor.SensitivityFeedback.UShortValue);
SensitivityFeedback = new IntFeedback(() => _partitionSensor.SensitivityFeedback.UShortValue);
if (_partitionSensor != null) _partitionSensor.BaseEvent += PartitionSensor_BaseEvent; if (_partitionSensor != null)
{
_partitionSensor.BaseEvent += PartitionSensor_BaseEvent;
}
});
AddPostActivationAction(() =>
{
_partitionSensor.OnlineStatusChange += (o, a) =>
{
if (a.DeviceOnLine)
{
ApplySettingsToSensorFromConfig();
}
};
if (_partitionSensor.IsOnline)
{
ApplySettingsToSensorFromConfig();
}
}); });
} }
private void PartitionSensor_BaseEvent(GenericBase device, BaseEventArgs args) private void ApplySettingsToSensorFromConfig()
{
if (_partitionSensor.IsOnline == false) return;
Debug.Console(1, this, "Attempting to apply settings to sensor from config");
if (PropertiesConfig.Sensitivity != null)
{
Debug.Console(1, this, "Sensitivity found, attempting to set value '{0}' from config",
PropertiesConfig.Sensitivity);
_partitionSensor.Sensitivity.UShortValue = (ushort) PropertiesConfig.Sensitivity;
}
else
{
Debug.Console(1, this, "Sensitivity null, no value specified in config");
}
}
private void PartitionSensor_BaseEvent(GenericBase device, BaseEventArgs args)
{ {
Debug.Console(2, this, "EventId: {0}, Index: {1}", args.EventId, args.Index); Debug.Console(2, this, "EventId: {0}, Index: {1}", args.EventId, args.Index);
@ -61,11 +113,13 @@ namespace PepperDash.Essentials.Core
} }
case (GlsPartCn.PartitionSensedFeedbackEventId): case (GlsPartCn.PartitionSensedFeedbackEventId):
{ {
PartitionSensedFeedback.FireUpdate(); Debug.Console(1, this, "Partition Sensed State: {0}", _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionPresentFeedback.FireUpdate();
break; break;
} }
case (GlsPartCn.PartitionNotSensedFeedbackEventId): case (GlsPartCn.PartitionNotSensedFeedbackEventId):
{ {
Debug.Console(1, this, "Partition Not Sensed State: {0}", _partitionSensor.PartitionNotSensedFeedback.BoolValue);
PartitionNotSensedFeedback.FireUpdate(); PartitionNotSensedFeedback.FireUpdate();
break; break;
} }
@ -93,6 +147,9 @@ namespace PepperDash.Essentials.Core
if (InTestMode) if (InTestMode)
{ {
TestEnableFeedback = state; TestEnableFeedback = state;
EnableFeedback.FireUpdate();
Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString()); Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString());
return; return;
} }
@ -105,6 +162,10 @@ namespace PepperDash.Essentials.Core
if (InTestMode) if (InTestMode)
{ {
TestPartitionSensedFeedback = state; TestPartitionSensedFeedback = state;
PartitionPresentFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate();
Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString()); Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString());
return; return;
} }
@ -117,6 +178,8 @@ namespace PepperDash.Essentials.Core
if (InTestMode) if (InTestMode)
{ {
TestSensitivityFeedback = value; TestSensitivityFeedback = value;
SensitivityFeedback.FireUpdate();
Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback); Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback);
return; return;
} }
@ -124,7 +187,22 @@ namespace PepperDash.Essentials.Core
Debug.Console(1, this, "InTestMode: {0}, unable to set sensitivity value: {1}", InTestMode.ToString(), value); Debug.Console(1, this, "InTestMode: {0}, unable to set sensitivity value: {1}", InTestMode.ToString(), value);
} }
public void SetEnableState(bool state) public void GetSettings()
{
var dash = new string('*', 50);
CrestronConsole.PrintLine(string.Format("{0}\n", dash));
Debug.Console(0, this, "Enabled State: {0}", _partitionSensor.EnableFeedback.BoolValue);
Debug.Console(0, this, "Partition Sensed State: {0}", _partitionSensor.PartitionSensedFeedback.BoolValue);
Debug.Console(0, this, "Partition Not Sensed State: {0}", _partitionSensor.PartitionNotSensedFeedback.BoolValue);
Debug.Console(0, this, "Sensitivity Value: {0}", _partitionSensor.SensitivityFeedback.UShortValue);
CrestronConsole.PrintLine(string.Format("{0}\n", dash));
}
public void SetEnableState(bool state)
{ {
Debug.Console(2, this, "Sensor is {0}, SetEnableState: {1}", _partitionSensor == null ? "null" : "not null", state); Debug.Console(2, this, "Sensor is {0}, SetEnableState: {1}", _partitionSensor == null ? "null" : "not null", state);
if (_partitionSensor == null) if (_partitionSensor == null)
@ -180,18 +258,20 @@ namespace PepperDash.Essentials.Core
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name); Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name);
// link input from simpl IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = _partitionSensor.Name;
trilist.SetBoolSigAction(joinMap.Enable.JoinNumber, SetEnableState); trilist.SetBoolSigAction(joinMap.Enable.JoinNumber, SetEnableState);
EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
PartitionPresentFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity); trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity);
trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity); trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity);
trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity);
// link output to simpl SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity);
EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
FeedbacksFireUpdates(); FeedbacksFireUpdates();
@ -209,6 +289,7 @@ namespace PepperDash.Essentials.Core
{ {
if (a.DeviceOnLine) if (a.DeviceOnLine)
{ {
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = _partitionSensor.Name;
FeedbacksFireUpdates(); FeedbacksFireUpdates();
} }
}; };
@ -217,9 +298,8 @@ namespace PepperDash.Essentials.Core
private void FeedbacksFireUpdates() private void FeedbacksFireUpdates()
{ {
IsOnline.FireUpdate(); IsOnline.FireUpdate();
NameFeedback.FireUpdate();
EnableFeedback.FireUpdate(); EnableFeedback.FireUpdate();
PartitionSensedFeedback.FireUpdate(); PartitionPresentFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate(); PartitionNotSensedFeedback.FireUpdate();
SensitivityFeedback.FireUpdate(); SensitivityFeedback.FireUpdate();
} }
@ -260,7 +340,7 @@ namespace PepperDash.Essentials.Core
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
{ {
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device"); Debug.Console(1, "Factory Attempting to create new GlsPartitionSensorController Device");
return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc); return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc);
} }

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash_Essentials_Core.PartitionSensor
{
public class GlsPartitionSensorPropertiesConfig
{
/// <summary>
/// Sets the sensor sensitivity
/// </summary>
/// <remarks>
/// The sensitivity range shall be between 1(lowest) to 10 (highest).
/// </remarks>
[JsonProperty("sensitivity")]
public ushort? Sensitivity { get; set; }
}
}

View file

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality of a device that senses and provides partition state
/// </summary>
public interface IPartitionStateProvider : IKeyName
{
BoolFeedback PartitionPresentFeedback { get; }
}
/// <summary>
/// Describes the functionality of a device that can provide partition state either manually via user input or optionally via a sensor state
/// </summary>
public interface IPartitionController : IPartitionStateProvider
{
List<string> AdjacentRoomKeys { get; }
void SetPartitionStatePresent();
void SetPartitionStateNotPresent();
void ToggglePartitionState();
void SetManualMode();
void SetAutoMode();
}
}

View file

@ -131,6 +131,7 @@
<Compile Include="Bridges\JoinMaps\DmBladeChassisControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmBladeChassisControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmChassisControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmChassisControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsAudioOutputControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmpsAudioOutputControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsMicrophoneControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmpsRoutingControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmpsRoutingControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmRmcControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmRmcControllerJoinMap.cs" />
<Compile Include="Bridges\JoinMaps\DmTxControllerJoinMap.cs" /> <Compile Include="Bridges\JoinMaps\DmTxControllerJoinMap.cs" />
@ -182,6 +183,7 @@
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" /> <Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" />
<Compile Include="Crestron IO\Inputs\IDigitalInput.cs" /> <Compile Include="Crestron IO\Inputs\IDigitalInput.cs" />
<Compile Include="Crestron IO\IOPortConfig.cs" /> <Compile Include="Crestron IO\IOPortConfig.cs" />
<Compile Include="Crestron IO\Relay\CenIoRy104Controller.cs" />
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" /> <Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" /> <Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />
<Compile Include="Crestron IO\StatusSign\StatusSignController.cs" /> <Compile Include="Crestron IO\StatusSign\StatusSignController.cs" />
@ -235,6 +237,9 @@
<Compile Include="Interfaces\ILogStringsWithLevel.cs" /> <Compile Include="Interfaces\ILogStringsWithLevel.cs" />
<Compile Include="Occupancy\GlsOccupancySensorPropertiesConfig.cs" /> <Compile Include="Occupancy\GlsOccupancySensorPropertiesConfig.cs" />
<Compile Include="Occupancy\GlsOirOccupancySensorController.cs" /> <Compile Include="Occupancy\GlsOirOccupancySensorController.cs" />
<Compile Include="PartitionSensor\EssentialsPartitionController.cs" />
<Compile Include="PartitionSensor\GlsPartitionSensorPropertiesConfig.cs" />
<Compile Include="PartitionSensor\IPartitionStateProvider.cs" />
<Compile Include="Occupancy\OccupancyAggregatorConfig.cs" /> <Compile Include="Occupancy\OccupancyAggregatorConfig.cs" />
<Compile Include="Queues\ComsMessage.cs" /> <Compile Include="Queues\ComsMessage.cs" />
<Compile Include="Queues\ProcessStringMessage.cs" /> <Compile Include="Queues\ProcessStringMessage.cs" />
@ -290,6 +295,10 @@
<Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" /> <Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" />
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" /> <Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" /> <Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombinerPropertiesConfig.cs" />
<Compile Include="Room\Combining\IEssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\RoomCombinationScenario.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" /> <Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" /> <Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" />
<Compile Include="Room\IEssentialsRoom.cs" /> <Compile Include="Room\IEssentialsRoom.cs" />

View file

@ -123,7 +123,7 @@ namespace PepperDash.Essentials
/// <param name="fileName"></param> /// <param name="fileName"></param>
static LoadedAssembly LoadAssembly(string filePath) static LoadedAssembly LoadAssembly(string filePath)
{ {
Debug.Console(2, "Attempting to load {0}", filePath); //Debug.Console(2, "Attempting to load {0}", filePath);
var assembly = Assembly.LoadFrom(filePath); var assembly = Assembly.LoadFrom(filePath);
if (assembly != null) if (assembly != null)
{ {

View file

@ -0,0 +1,297 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
{
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
private IRoomCombinationScenario _currentScenario;
private List<IEssentialsRoom> _rooms;
private bool isInAutoMode;
private CTimer _scenarioChangeDebounceTimer;
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
: base(key)
{
_propertiesConfig = props;
Partitions = new List<IPartitionController>();
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
if (_propertiesConfig.ScenarioChangeDebounceTimeSeconds > 0)
{
_scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds;
}
IsInAutoModeFeedback = new BoolFeedback(() => isInAutoMode);
// default to auto mode
isInAutoMode = true;
if (_propertiesConfig.defaultToManualMode)
{
isInAutoMode = false;
}
IsInAutoModeFeedback.FireUpdate();
CreateScenarios();
AddPostActivationAction(() =>
{
SetupPartitionStateProviders();
SetRooms();
if (isInAutoMode)
{
DetermineRoomCombinationScenario();
}
else
{
SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey);
}
});
}
void CreateScenarios()
{
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
{
var scenario = new RoomCombinationScenario(scenarioConfig);
RoomCombinationScenarios.Add(scenario);
}
}
void SetRooms()
{
_rooms = new List<IEssentialsRoom>();
foreach (var roomKey in _propertiesConfig.RoomKeys)
{
var room = DeviceManager.GetDeviceForKey(roomKey) as IEssentialsRoom;
if (room != null)
{
_rooms.Add(room);
}
}
}
void SetupPartitionStateProviders()
{
foreach (var pConfig in _propertiesConfig.Partitions)
{
var sensor = DeviceManager.GetDeviceForKey(pConfig.DeviceKey) as IPartitionStateProvider;
var partition = new EssentialsPartitionController(pConfig.Key, pConfig.Name, sensor, _propertiesConfig.defaultToManualMode, pConfig.AdjacentRoomKeys);
partition.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
Partitions.Add(partition);
}
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
StartDebounceTimer();
}
void StartDebounceTimer()
{
var time = _scenarioChangeDebounceTimeSeconds * 1000;
if (_scenarioChangeDebounceTimer == null)
{
_scenarioChangeDebounceTimer = new CTimer((o) => DetermineRoomCombinationScenario(), time);
}
else
{
_scenarioChangeDebounceTimer.Reset(time);
}
}
/// <summary>
/// Determines the current room combination scenario based on the state of the partition sensors
/// </summary>
void DetermineRoomCombinationScenario()
{
if (_scenarioChangeDebounceTimer != null)
{
_scenarioChangeDebounceTimer.Dispose();
_scenarioChangeDebounceTimer = null;
}
var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) =>
{
// iterate the partition states
foreach (var partitionState in s.PartitionStates)
{
// get the partition by key
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue)
{
// the partition can't be found or the state doesn't match
return false;
}
}
// if it hasn't returned false by now we have the matching scenario
return true;
});
if (currentScenario != null)
{
CurrentScenario = currentScenario;
}
}
#region IEssentialsRoomCombiner Members
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
public IRoomCombinationScenario CurrentScenario
{
get
{
return _currentScenario;
}
private set
{
if (value != _currentScenario)
{
// Deactivate the old scenario first
if (_currentScenario != null)
{
_currentScenario.Deactivate();
}
_currentScenario = value;
// Activate the new scenario
if (_currentScenario != null)
{
_currentScenario.Activate();
Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name);
}
var handler = RoomCombinationScenarioChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
}
public BoolFeedback IsInAutoModeFeedback { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
IsInAutoModeFeedback.FireUpdate();
}
public void SetManualMode()
{
isInAutoMode = false;
IsInAutoModeFeedback.FireUpdate();
}
public void ToggleMode()
{
isInAutoMode = !isInAutoMode;
IsInAutoModeFeedback.FireUpdate();
}
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
public List<IPartitionController> Partitions { get; private set; }
public void TogglePartitionState(string partitionKey)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController;
if (partition != null)
{
partition.ToggglePartitionState();
}
}
public void SetRoomCombinationScenario(string scenarioKey)
{
if (isInAutoMode)
{
Debug.Console(0, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first.");
return;
}
// Get the scenario
var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey));
// Set the parition states from the scenario manually
if (scenario != null)
{
Debug.Console(0, this, "Manually setting scenario to '{0}'", scenario.Key);
foreach (var partitionState in scenario.PartitionStates)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
if (partition != null)
{
if (partitionState.PartitionPresent)
{
Debug.Console(0, this, "Manually setting state to Present for: '{0}'", partition.Key);
partition.SetPartitionStatePresent();
}
else
{
Debug.Console(0, this, "Manually setting state to Not Present for: '{0}'", partition.Key);
partition.SetPartitionStateNotPresent();
}
}
else
{
Debug.Console(1, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey);
}
}
}
else
{
Debug.Console(1, this, "Unable to find scenario with key: '{0}'", scenarioKey);
}
}
#endregion
}
public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory<EssentialsRoomCombiner>
{
public EssentialsRoomCombinerFactory()
{
TypeNames = new List<string> { "essentialsroomcombiner" };
}
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new EssentialsRoomCombiner Device");
var props = dc.Properties.ToObject<EssentialsRoomCombinerPropertiesConfig>();
return new EssentialsRoomCombiner(dc.Key, props);
}
}
}

View file

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Config properties for an EssentialsRoomCombiner device
/// </summary>
public class EssentialsRoomCombinerPropertiesConfig
{
/// <summary>
/// The list of partitions that device the rooms
/// </summary>
[JsonProperty("partitions")]
public List<PartitionConfig> Partitions {get; set;}
/// <summary>
/// The list of combinations scenarios for the rooms
/// </summary>
[JsonProperty("scenarios")]
public List<RoomCombinationScenarioConfig> Scenarios { get; set; }
/// <summary>
/// The list of rooms keys that can be combined
/// </summary>
[JsonProperty("roomKeys")]
public List<string> RoomKeys {get; set;}
/// <summary>
/// Set to true to default to manual mode
/// </summary>
[JsonProperty("defaultToManualMode")]
public bool defaultToManualMode { get; set; }
/// <summary>
/// The key of the scenario to default to at system startup if in manual mode
/// </summary>
[JsonProperty("defaultScenarioKey")]
public string defaultScenarioKey { get; set; }
[JsonProperty("scenarioChangeDebounceTimeSeconds")]
public int ScenarioChangeDebounceTimeSeconds { get; set; }
}
/// <summary>
/// Config properties for a partition that separates rooms
/// </summary>
public class PartitionConfig : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Key of the device that implements IPartitionStateProvider to provide the state of the partition
/// </summary>
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
/// <summary>
/// Keys of the rooms that this partion would be located between
/// </summary>
[JsonProperty("adjacentRoomKeys")]
public List<string> AdjacentRoomKeys { get; set; }
}
/// <summary>
/// Config propeties for a room combination scenario
/// </summary>
public class RoomCombinationScenarioConfig : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; set; }
/// <summary>
/// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to
/// </summary>
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }
[JsonProperty("activationActions")]
public List<DeviceActionWrapper> ActivationActions { get; set; }
[JsonProperty("deactivationActions")]
public List<DeviceActionWrapper> DeactivationActions { get; set; }
}
/// <summary>
/// Config properties to represent the state of a partition sensor in a RoomCombinationScenario
/// </summary>
public class PartitionState
{
[JsonProperty("partitionKey")]
public string PartitionKey { get; set; }
[JsonProperty("partitionSensedState")]
public bool PartitionPresent { get; set; }
}
}

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality for an EssentailsRoomCombiner device
/// </summary>
public interface IEssentialsRoomCombiner : IKeyed
{
/// <summary>
/// Indicates that the room combination scenario has changed
/// </summary>
event EventHandler<EventArgs> RoomCombinationScenarioChanged;
/// <summary>
/// The current room combination scenario
/// </summary>
IRoomCombinationScenario CurrentScenario { get; }
/// <summary>
/// When true, indicates the current mode is auto mode
/// </summary>
BoolFeedback IsInAutoModeFeedback {get;}
/// <summary>
/// Sets auto mode
/// </summary>
void SetAutoMode();
/// <summary>
/// Sets manual mode
/// </summary>
void SetManualMode();
/// <summary>
/// Toggles the current mode between auto and manual
/// </summary>
void ToggleMode();
/// <summary>
/// The available room combinatino scenarios
/// </summary>
List<IRoomCombinationScenario> RoomCombinationScenarios { get; }
/// <summary>
/// The partition
/// </summary>
List<IPartitionController> Partitions { get; }
/// <summary>
/// Toggles the state of a manual partition sensor
/// </summary>
/// <param name="partitionKey"></param>
void TogglePartitionState(string partitionKey);
/// <summary>
/// Sets the room combination scenario (if in manual mode)
/// </summary>
/// <param name="scenarioKey"></param>
void SetRoomCombinationScenario(string scenarioKey);
}
public interface IRoomCombinationScenario : IKeyName
{
/// <summary>
/// When true, indicates that this room combination scenario is active
/// </summary>
BoolFeedback IsActiveFeedback { get; }
/// <summary>
/// Activates this room combination scenario
/// </summary>
void Activate();
/// <summary>
/// Deactivates this room combination scenario
/// </summary>
void Deactivate();
/// <summary>
/// The state of the partitions that would activate this scenario
/// </summary>
List<PartitionState> PartitionStates { get; }
/// <summary>
/// The mapping of UIs by key to rooms by key
/// </summary>
Dictionary<string, string> UiMap { get; set; }
}
}

View file

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Represents a room combination scenario
/// </summary>
public class RoomCombinationScenario: IRoomCombinationScenario
{
private RoomCombinationScenarioConfig _config;
public string Key { get; set; }
public string Name { get; set; }
public List<PartitionState> PartitionStates { get; private set; }
public Dictionary<string, string> UiMap { get; set; }
private bool _isActive;
public BoolFeedback IsActiveFeedback { get; private set; }
private List<DeviceActionWrapper> activationActions;
private List<DeviceActionWrapper> deactivationActions;
public RoomCombinationScenario(RoomCombinationScenarioConfig config)
{
Key = config.Key;
Name = config.Name;
PartitionStates = config.PartitionStates;
UiMap = config.UiMap;
activationActions = config.ActivationActions;
deactivationActions = config.DeactivationActions;
_config = config;
IsActiveFeedback = new BoolFeedback(() => _isActive);
}
public void Activate()
{
Debug.Console(1, "Activating Scenario: '{0}' with {1} action(s) defined", Name, activationActions.Count);
if (activationActions != null)
{
foreach (var action in activationActions)
{
DeviceJsonApi.DoDeviceAction(action);
}
}
_isActive = true;
IsActiveFeedback.FireUpdate();
}
public void Deactivate()
{
Debug.Console(1, "Deactivating Scenario: '{0}' with {1} action(s) defined", Name, deactivationActions.Count);
if (deactivationActions != null)
{
foreach (var action in deactivationActions)
{
DeviceJsonApi.DoDeviceAction(action);
}
}
_isActive = false;
IsActiveFeedback.FireUpdate();
}
}
}

View file

@ -206,6 +206,27 @@ namespace PepperDash.Essentials.Core
return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig; return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig;
} }
/// <summary>
/// Clears all actions on all sigs
/// </summary>
public static void ClearAllSigActions(this BasicTriList t1)
{
foreach (var sig in t1.BooleanOutput)
{
ClearSigAction(sig);
}
foreach (var sig in t1.UShortOutput)
{
ClearSigAction(sig);
}
foreach (var sig in t1.StringOutput)
{
ClearSigAction(sig);
}
}
/// <summary> /// <summary>
/// Helper method to set the value of a bool Sig on TriList /// Helper method to set the value of a bool Sig on TriList
/// </summary> /// </summary>

View file

@ -16,7 +16,8 @@ using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.DM.Config; using PepperDash.Essentials.DM.Config;
namespace PepperDash.Essentials.DM { namespace PepperDash.Essentials.DM
{
/// <summary> /// <summary>
/// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions /// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions
/// ///
@ -75,8 +76,10 @@ namespace PepperDash.Essentials.DM {
/// Factory method to create a new chassis controller from config data. Limited to 8x8 right now /// Factory method to create a new chassis controller from config data. Limited to 8x8 right now
/// </summary> /// </summary>
public static DmBladeChassisController GetDmChassisController(string key, string name, public static DmBladeChassisController GetDmChassisController(string key, string name,
string type, DMChassisPropertiesConfig properties) { string type, DMChassisPropertiesConfig properties)
try { {
try
{
type = type.ToLower(); type = type.ToLower();
uint ipid = properties.Control.IpIdInt; uint ipid = properties.Control.IpIdInt;
@ -85,7 +88,8 @@ namespace PepperDash.Essentials.DM {
else if (type == "dmmd128x128") { chassis = new DmMd128x128(ipid, Global.ControlSystem); } else if (type == "dmmd128x128") { chassis = new DmMd128x128(ipid, Global.ControlSystem); }
if (chassis == null) { if (chassis == null)
{
return null; return null;
} }
@ -93,11 +97,13 @@ namespace PepperDash.Essentials.DM {
// add the cards and port names // add the cards and port names
foreach (var kvp in properties.InputSlots) foreach (var kvp in properties.InputSlots)
controller.AddInputBlade(kvp.Value, kvp.Key); controller.AddInputBlade(kvp.Value, kvp.Key);
foreach (var kvp in properties.OutputSlots) { foreach (var kvp in properties.OutputSlots)
{
controller.AddOutputBlade(kvp.Value, kvp.Key); controller.AddOutputBlade(kvp.Value, kvp.Key);
} }
foreach (var kvp in properties.VolumeControls) { foreach (var kvp in properties.VolumeControls)
{
// get the card // get the card
// check it for an audio-compatible type // check it for an audio-compatible type
// make a something-something that will make it work // make a something-something that will make it work
@ -123,7 +129,8 @@ namespace PepperDash.Essentials.DM {
controller.PropertiesConfig = properties; controller.PropertiesConfig = properties;
return controller; return controller;
} }
catch (System.Exception e) { catch (System.Exception e)
{
Debug.Console(0, "Error creating DM chassis:\r{0}", e); Debug.Console(0, "Error creating DM chassis:\r{0}", e);
} }
return null; return null;
@ -137,7 +144,8 @@ namespace PepperDash.Essentials.DM {
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="chassis"></param> /// <param name="chassis"></param>
public DmBladeChassisController(string key, string name, BladeSwitch chassis) public DmBladeChassisController(string key, string name, BladeSwitch chassis)
: base(key, name, chassis) { : base(key, name, chassis)
{
Chassis = chassis; Chassis = chassis;
InputPorts = new RoutingPortCollection<RoutingInputPort>(); InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@ -161,68 +169,87 @@ namespace PepperDash.Essentials.DM {
InputCardHdcpCapabilityFeedbacks = new Dictionary<uint, IntFeedback>(); InputCardHdcpCapabilityFeedbacks = new Dictionary<uint, IntFeedback>();
InputCardHdcpCapabilityTypes = new Dictionary<uint, eHdcpCapabilityType>(); InputCardHdcpCapabilityTypes = new Dictionary<uint, eHdcpCapabilityType>();
for (uint x = 1; x <= Chassis.NumberOfOutputs; x++) { for (uint x = 1; x <= Chassis.NumberOfOutputs; x++)
{
var tempX = x; var tempX = x;
if (Chassis.Outputs[tempX] != null) { if (Chassis.Outputs[tempX] != null)
VideoOutputFeedbacks[tempX] = new IntFeedback(() => { {
VideoOutputFeedbacks[tempX] = new IntFeedback(() =>
{
if (Chassis.Outputs[tempX].VideoOutFeedback != null) { return (ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number; } if (Chassis.Outputs[tempX].VideoOutFeedback != null) { return (ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number; }
else { return 0; }; else { return 0; };
}); });
OutputNameFeedbacks[tempX] = new StringFeedback(() => { OutputNameFeedbacks[tempX] = new StringFeedback(() =>
if (Chassis.Outputs[tempX].NameFeedback != null) { {
if (Chassis.Outputs[tempX].NameFeedback != null)
{
return Chassis.Outputs[tempX].NameFeedback.StringValue; return Chassis.Outputs[tempX].NameFeedback.StringValue;
} }
else { else
{
return ""; return "";
} }
}); });
OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => { OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() =>
if (Chassis.Outputs[tempX].VideoOutFeedback != null) { {
if (Chassis.Outputs[tempX].VideoOutFeedback != null)
{
return Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue; return Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue;
} }
else { else
{
return ""; return "";
} }
}); });
OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() =>
{
//if (Chassis.Outputs[tempX].Endpoint != null) //if (Chassis.Outputs[tempX].Endpoint != null)
// return Chassis.Outputs[tempX].Endpoint.IsOnline; // return Chassis.Outputs[tempX].Endpoint.IsOnline;
//else //else
return Chassis.Outputs[tempX].EndpointOnlineFeedback; return Chassis.Outputs[tempX].EndpointOnlineFeedback;
}); });
} }
if (Chassis.Inputs[tempX] != null) { if (Chassis.Inputs[tempX] != null)
UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() => { {
UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() =>
{
if (Chassis.Inputs[tempX].USBRoutedToFeedback != null) { return (ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number; } if (Chassis.Inputs[tempX].USBRoutedToFeedback != null) { return (ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number; }
else { return 0; }; else { return 0; };
}); });
VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => { VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() =>
{
if (Chassis.Inputs[tempX].VideoDetectedFeedback != null) if (Chassis.Inputs[tempX].VideoDetectedFeedback != null)
return Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue; return Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue;
else else
return false; return false;
}); });
InputNameFeedbacks[tempX] = new StringFeedback(() => { InputNameFeedbacks[tempX] = new StringFeedback(() =>
if (Chassis.Inputs[tempX].NameFeedback != null) { {
if (Chassis.Inputs[tempX].NameFeedback != null)
{
return Chassis.Inputs[tempX].NameFeedback.StringValue; return Chassis.Inputs[tempX].NameFeedback.StringValue;
} }
else { else
{
return ""; return "";
} }
}); });
InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => { InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() =>
{
return Chassis.Inputs[tempX].EndpointOnlineFeedback; return Chassis.Inputs[tempX].EndpointOnlineFeedback;
}); });
InputCardHdcpCapabilityFeedbacks[tempX] = new IntFeedback(() => { InputCardHdcpCapabilityFeedbacks[tempX] = new IntFeedback(() =>
{
var inputCard = Chassis.Inputs[tempX]; var inputCard = Chassis.Inputs[tempX];
if (inputCard.Card is DmHdmi4kInputBladeCard) { if (inputCard.Card is DmHdmi4kInputBladeCard)
{
InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support;
if ((inputCard.Card as DmHdmi4kInputBladeCard).Hdmi4kInput.HdcpSupportOnFeedback.BoolValue) if ((inputCard.Card as DmHdmi4kInputBladeCard).Hdmi4kInput.HdcpSupportOnFeedback.BoolValue)
@ -231,7 +258,8 @@ namespace PepperDash.Essentials.DM {
return 0; return 0;
} }
if (inputCard.Card is DmC4kInputBladeCard) { if (inputCard.Card is DmC4kInputBladeCard)
{
InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support; InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support;
if ((inputCard.Card as DmC4kInputBladeCard).DmInput.HdcpCapabilityFeedback.Equals(eHdcpCapabilityType.HdcpSupportOff)) if ((inputCard.Card as DmC4kInputBladeCard).DmInput.HdcpCapabilityFeedback.Equals(eHdcpCapabilityType.HdcpSupportOff))
@ -252,45 +280,56 @@ namespace PepperDash.Essentials.DM {
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="number"></param> /// <param name="number"></param>
public void AddInputBlade(string type, uint number) { public void AddInputBlade(string type, uint number)
{
Debug.Console(2, this, "Adding input blade '{0}', slot {1}", type, number); Debug.Console(2, this, "Adding input blade '{0}', slot {1}", type, number);
type = type.ToLower(); type = type.ToLower();
if (type == "dmb4kihd") { if (type == "dmb4kihd")
{
var inputBlade = new Dmb4kIHd(number, this.Chassis); var inputBlade = new Dmb4kIHd(number, this.Chassis);
foreach (var item in inputBlade.Inputs) { foreach (var item in inputBlade.Inputs)
{
var card = (item.Card as DmHdmi4kInputBladeCard).Hdmi4kInput; var card = (item.Card as DmHdmi4kInputBladeCard).Hdmi4kInput;
var cecPort = card as ICec; var cecPort = card as ICec;
AddHdmiInBladePorts(item.Number, cecPort); AddHdmiInBladePorts(item.Number, cecPort);
} }
} }
else if (type == "dmb4kihddnt") { else if (type == "dmb4kihddnt")
{
var inputBlade = new Dmb4kIHd(number, this.Chassis); var inputBlade = new Dmb4kIHd(number, this.Chassis);
foreach (var item in inputBlade.Inputs) { foreach (var item in inputBlade.Inputs)
{
var card = (item.Card as DmHdmi4kInputBladeCard).Hdmi4kInput; var card = (item.Card as DmHdmi4kInputBladeCard).Hdmi4kInput;
var cecPort = card as ICec; var cecPort = card as ICec;
AddHdmiInBladePorts(item.Number, cecPort); AddHdmiInBladePorts(item.Number, cecPort);
} }
} }
else if (type == "dmb4kic") { else if (type == "dmb4kic")
{
var inputBlade = new Dmb4kIC(number, this.Chassis); var inputBlade = new Dmb4kIC(number, this.Chassis);
foreach (var item in inputBlade.Inputs) { foreach (var item in inputBlade.Inputs)
{
AddDmInBladePorts(item.Number); AddDmInBladePorts(item.Number);
} }
} }
else if (type == "dmbis") { else if (type == "dmbis")
{
var inputBlade = new DmbIS(number, this.Chassis); var inputBlade = new DmbIS(number, this.Chassis);
foreach (var item in inputBlade.Inputs) { foreach (var item in inputBlade.Inputs)
{
AddDmInMmFiberPorts(item.Number); AddDmInMmFiberPorts(item.Number);
} }
} }
else if (type == "dmbis2") { else if (type == "dmbis2")
{
var inputBlade = new DmbIS2(number, this.Chassis); var inputBlade = new DmbIS2(number, this.Chassis);
foreach (var item in inputBlade.Inputs) { foreach (var item in inputBlade.Inputs)
{
AddDmInSmFiberPorts(item.Number); AddDmInSmFiberPorts(item.Number);
} }
} }
@ -307,19 +346,23 @@ namespace PepperDash.Essentials.DM {
} }
void AddHdmiInBladePorts(uint number, ICec cecPort) { void AddHdmiInBladePorts(uint number, ICec cecPort)
{
AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort); AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort);
} }
void AddDmInBladePorts(uint number) { void AddDmInBladePorts(uint number)
{
AddInputPortWithDebug(number, "dmCIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat); AddInputPortWithDebug(number, "dmCIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat);
} }
void AddDmInMmFiberPorts(uint number) { void AddDmInMmFiberPorts(uint number)
{
AddInputPortWithDebug(number, "dmMmIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber); AddInputPortWithDebug(number, "dmMmIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber);
} }
void AddDmInSmFiberPorts(uint number) { void AddDmInSmFiberPorts(uint number)
{
AddInputPortWithDebug(number, "dmSmIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber); AddInputPortWithDebug(number, "dmSmIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber);
} }
@ -328,64 +371,81 @@ namespace PepperDash.Essentials.DM {
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="number"></param> /// <param name="number"></param>
public void AddOutputBlade(string type, uint number) { public void AddOutputBlade(string type, uint number)
{
type = type.ToLower(); type = type.ToLower();
Debug.Console(2, this, "Adding output blade '{0}', slot {1}", type, number); Debug.Console(2, this, "Adding output blade '{0}', slot {1}", type, number);
if (type == "dmb4kohd") { if (type == "dmb4kohd")
{
var outputBlade = new Dmb4KOHD(number, Chassis); var outputBlade = new Dmb4KOHD(number, Chassis);
foreach (var item in outputBlade.Outputs) { foreach (var item in outputBlade.Outputs)
{
AddHdmiOutBladePorts(item.Number); AddHdmiOutBladePorts(item.Number);
} }
} }
else if (type == "dmb4kohddnt") { else if (type == "dmb4kohddnt")
{
var outputBlade = new Dmb4KOHD(number, Chassis); var outputBlade = new Dmb4KOHD(number, Chassis);
foreach (var item in outputBlade.Outputs) { foreach (var item in outputBlade.Outputs)
{
AddHdmiOutBladePorts(item.Number); AddHdmiOutBladePorts(item.Number);
} }
} }
else if (type == "dmb4koc") { else if (type == "dmb4koc")
{
var outputBlade = new Dmb4KOC(number, Chassis); var outputBlade = new Dmb4KOC(number, Chassis);
foreach (var item in outputBlade.Outputs) { foreach (var item in outputBlade.Outputs)
{
AddDmOutBladePorts(item.Number); AddDmOutBladePorts(item.Number);
} }
} }
else if (type == "dmb4koc") { else if (type == "dmb4koc")
{
var outputBlade = new Dmb4KOC(number, Chassis); var outputBlade = new Dmb4KOC(number, Chassis);
foreach (var item in outputBlade.Outputs) { foreach (var item in outputBlade.Outputs)
{
AddDmOutBladePorts(item.Number); AddDmOutBladePorts(item.Number);
} }
} }
else if (type == "dmbos") { else if (type == "dmbos")
{
var outputBlade = new DmbOS(number, Chassis); var outputBlade = new DmbOS(number, Chassis);
foreach (var item in outputBlade.Outputs) { foreach (var item in outputBlade.Outputs)
{
AddDmOutMmFiberBladePorts(item.Number); AddDmOutMmFiberBladePorts(item.Number);
} }
} }
else if (type == "dmbos2") { else if (type == "dmbos2")
{
var outputBlade = new DmbOS2(number, Chassis); var outputBlade = new DmbOS2(number, Chassis);
foreach (var item in outputBlade.Outputs) { foreach (var item in outputBlade.Outputs)
{
AddDmOutSmFiberBladePorts(item.Number); AddDmOutSmFiberBladePorts(item.Number);
} }
} }
} }
void AddHdmiOutBladePorts(uint number) { void AddHdmiOutBladePorts(uint number)
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("hdmiOut{0}", number) , eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, Chassis.Outputs[number]); {
AddOutputPortWithDebug(number, "hdmiOut", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, Chassis.Outputs[number]);
} }
void AddDmOutBladePorts(uint number) { void AddDmOutBladePorts(uint number)
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("dmOut{0}", number), eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, Chassis.Outputs[number]); {
AddOutputPortWithDebug(number, "dmOut", eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, Chassis.Outputs[number]);
} }
void AddDmOutMmFiberBladePorts(uint number) { void AddDmOutMmFiberBladePorts(uint number)
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("dmOut{0}", number), eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[number]); {
AddOutputPortWithDebug(number, "dmMmOut", eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[number]);
} }
void AddDmOutSmFiberBladePorts(uint number) { void AddDmOutSmFiberBladePorts(uint number)
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("dmOut{0}", number), eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[number]); {
AddOutputPortWithDebug(number, "dmSmOut", eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[number]);
} }
@ -417,23 +477,44 @@ namespace PepperDash.Essentials.DM {
} }
/// <summary>
/// Adds OutputPort /*void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) {
/// </summary>
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) {
var portKey = string.Format("{0}--{1}", cardName, portName); var portKey = string.Format("{0}--{1}", cardName, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey); 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 = selector FeedbackMatchObject = selector
}); });
}*/
/// <summary>
/// Adds OutputPort
/// </summary>
void AddOutputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector)
{
try
{
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)
{
FeedbackMatchObject = Chassis.Outputs[cardNum]
};
OutputPorts.Add(outputPort);
}
catch (Exception ex)
{
Debug.Console(0, this, "Exception : {0}", ex);
}
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
void AddVolumeControl(uint number, Audio.Output audio) { void AddVolumeControl(uint number, Audio.Output audio)
{
VolumeControls.Add(number, new DmCardAudioOutputController(audio)); VolumeControls.Add(number, new DmCardAudioOutputController(audio));
} }
@ -443,35 +524,43 @@ namespace PepperDash.Essentials.DM {
//} //}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args) { void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
switch (args.EventId) { switch (args.EventId)
case DMInputEventIds.EndpointOnlineEventId: { {
case DMInputEventIds.EndpointOnlineEventId:
{
Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
break; break;
} }
case DMInputEventIds.OnlineFeedbackEventId: { case DMInputEventIds.OnlineFeedbackEventId:
{
Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
break; break;
} }
case DMInputEventIds.VideoDetectedEventId: { case DMInputEventIds.VideoDetectedEventId:
{
Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number);
VideoInputSyncFeedbacks[args.Number].FireUpdate(); VideoInputSyncFeedbacks[args.Number].FireUpdate();
break; break;
} }
case DMInputEventIds.InputNameEventId: { case DMInputEventIds.InputNameEventId:
{
Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number);
InputNameFeedbacks[args.Number].FireUpdate(); InputNameFeedbacks[args.Number].FireUpdate();
break; break;
} }
case DMInputEventIds.HdcpCapabilityFeedbackEventId: { case DMInputEventIds.HdcpCapabilityFeedbackEventId:
{
Debug.Console(2, this, "DM Input {0} HdcpCapabilityFeedbackEventId", args.Number); Debug.Console(2, this, "DM Input {0} HdcpCapabilityFeedbackEventId", args.Number);
InputCardHdcpCapabilityFeedbacks[args.Number].FireUpdate(); InputCardHdcpCapabilityFeedbacks[args.Number].FireUpdate();
break; break;
} }
default: { default:
{
Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId); Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId);
break; break;
} }
@ -487,74 +576,74 @@ namespace PepperDash.Essentials.DM {
switch (args.EventId) switch (args.EventId)
{ {
case DMOutputEventIds.VolumeEventId: case DMOutputEventIds.VolumeEventId:
{
if (VolumeControls.ContainsKey(output))
{ {
VolumeControls[args.Number].VolumeEventFromChassis(); if (VolumeControls.ContainsKey(output))
{
VolumeControls[args.Number].VolumeEventFromChassis();
}
break;
} }
break;
}
case DMOutputEventIds.EndpointOnlineEventId: 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, Debug.Console(2, this,
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}", "Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}",
args.Number, Chassis.Outputs[output].Endpoint.IsOnline); 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(); OutputEndpointOnlineFeedbacks[output].FireUpdate();
break; break;
} }
case DMOutputEventIds.OnlineFeedbackEventId: case DMOutputEventIds.OnlineFeedbackEventId:
{ {
Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}", Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback); args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
OutputEndpointOnlineFeedbacks[output].FireUpdate(); OutputEndpointOnlineFeedbacks[output].FireUpdate();
break; break;
} }
case DMOutputEventIds.VideoOutEventId: 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 = var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.Outputs[output].VideoOutFeedback.Number;
OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == Chassis.Outputs[output]);
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(); VideoOutputFeedbacks[output].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output, OnSwitchChange(new RoutingNumericEventArgs(output,
inputNumber, inputNumber,
localOutputPort, localOutputPort,
localInputPort, localInputPort,
eRoutingSignalType.AudioVideo)); eRoutingSignalType.AudioVideo));
}
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
{
OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
break;
} }
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
{
OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
break;
}
case DMOutputEventIds.OutputNameEventId: case DMOutputEventIds.OutputNameEventId:
{ {
Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output); Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
OutputNameFeedbacks[output].FireUpdate(); OutputNameFeedbacks[output].FireUpdate();
break; break;
} }
default: default:
{ {
Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}", Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}",
args.Number, args.EventId); args.Number, args.EventId);
break; break;
} }
} }
} }
@ -564,7 +653,8 @@ namespace PepperDash.Essentials.DM {
/// ///
/// </summary> /// </summary>
/// <param name="pnt"></param> /// <param name="pnt"></param>
void StartOffTimer(PortNumberType pnt) { void StartOffTimer(PortNumberType pnt)
{
if (RouteOffTimers.ContainsKey(pnt)) if (RouteOffTimers.ContainsKey(pnt))
return; return;
RouteOffTimers[pnt] = new CTimer(o => ExecuteSwitch(null, pnt.Selector, pnt.Type), RouteOffTime); RouteOffTimers[pnt] = new CTimer(o => ExecuteSwitch(null, pnt.Selector, pnt.Type), RouteOffTime);
@ -572,8 +662,10 @@ namespace PepperDash.Essentials.DM {
// Send out sigs when coming online // Send out sigs when coming online
void IsOnline_OutputChange(object sender, EventArgs e) { void IsOnline_OutputChange(object sender, EventArgs e)
if (IsOnline.BoolValue) { {
if (IsOnline.BoolValue)
{
Chassis.EnableUSBBreakaway.BoolValue = true; Chassis.EnableUSBBreakaway.BoolValue = true;
if (InputNames != null) if (InputNames != null)
@ -587,7 +679,8 @@ namespace PepperDash.Essentials.DM {
#region IRouting Members #region IRouting Members
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) { public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType)
{
Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType); Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType);
var input = inputSelector as DMInput; // Cast can sometimes fail var input = inputSelector as DMInput; // Cast can sometimes fail
@ -605,11 +698,14 @@ namespace PepperDash.Essentials.DM {
// Check to see if there's an off timer waiting on this and if so, cancel // Check to see if there's an off timer waiting on this and if so, cancel
var key = new PortNumberType(output, sigType); var key = new PortNumberType(output, sigType);
if (input == null) { if (input == null)
{
StartOffTimer(key); StartOffTimer(key);
} }
else { else
if (RouteOffTimers.ContainsKey(key)) { {
if (RouteOffTimers.ContainsKey(key))
{
Debug.Console(2, this, "{0} cancelling route off due to new source", output); Debug.Console(2, this, "{0} cancelling route off due to new source", output);
RouteOffTimers[key].Stop(); RouteOffTimers[key].Stop();
RouteOffTimers.Remove(key); RouteOffTimers.Remove(key);
@ -671,7 +767,7 @@ namespace PepperDash.Essentials.DM {
var ioSlotJoin = ioSlot - 1; var ioSlotJoin = ioSlot - 1;
// Control // Control
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Video)); trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteNumericSwitch(o, (ushort)ioSlot, eRoutingSignalType.Video));
if (TxDictionary.ContainsKey(ioSlot)) if (TxDictionary.ContainsKey(ioSlot))
{ {

View file

@ -1901,6 +1901,8 @@ namespace PepperDash.Essentials.DM
EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]); EnableAudioBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAudioBreakaway.JoinNumber]);
EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]); EnableUsbBreakawayFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableUsbBreakaway.JoinNumber]);
trilist.SetString(joinMap.NoRouteName.JoinNumber, NoRouteText);
trilist.OnlineStatusChange += (o, a) => trilist.OnlineStatusChange += (o, a) =>
{ {
if (!a.DeviceOnLine) if (!a.DeviceOnLine)
@ -1912,6 +1914,8 @@ namespace PepperDash.Essentials.DM
EnableUsbBreakawayFeedback.FireUpdate(); EnableUsbBreakawayFeedback.FireUpdate();
SystemIdBusyFeedback.FireUpdate(); SystemIdBusyFeedback.FireUpdate();
SystemIdFeebdack.FireUpdate(); SystemIdFeebdack.FireUpdate();
trilist.SetString(joinMap.NoRouteName.JoinNumber, NoRouteText);
}; };
} }

View file

@ -25,10 +25,10 @@ namespace PepperDash.Essentials.DM
public DmpsAudioOutput MasterVolumeLevel { get; private set; } public DmpsAudioOutput MasterVolumeLevel { get; private set; }
public DmpsAudioOutput SourceVolumeLevel { get; private set; } public DmpsAudioOutput SourceVolumeLevel { get; private set; }
public DmpsAudioOutput MicsMasterVolumeLevel { get; private set; }
public DmpsAudioOutput Codec1VolumeLevel { get; private set; } public DmpsAudioOutput Codec1VolumeLevel { get; private set; }
public DmpsAudioOutput Codec2VolumeLevel { get; private set; } public DmpsAudioOutput Codec2VolumeLevel { get; private set; }
public DmpsAudioOutputController(string key, string name, Card.Dmps3OutputBase card) public DmpsAudioOutputController(string key, string name, Card.Dmps3OutputBase card)
: base(key, name) : base(key, name)
{ {
@ -36,69 +36,129 @@ namespace PepperDash.Essentials.DM
OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange); OutputCard.BaseDevice.DMOutputChange += new DMOutputEventHandler(BaseDevice_DMOutputChange);
MasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Master);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
if (card is Card.Dmps3ProgramOutput) if (card is Card.Dmps3ProgramOutput)
{ {
//(card as Card.Dmps3ProgramOutput).OutputMixer.MicLevel MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3ProgramOutput).OutputMixer);
//TODO: Hook up mic levels and mutes SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1);
Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2);
} }
else if (card is Card.Dmps3Aux1Output) else if (card is Card.Dmps3Aux1Output)
{ {
MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux1Output).OutputMixer);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2); Codec2VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec2);
} }
else if (card is Card.Dmps3Aux2Output) else if (card is Card.Dmps3Aux2Output)
{ {
MasterVolumeLevel = new DmpsAudioOutputWithMixer(card, eDmpsLevelType.Master, (card as Card.Dmps3Aux2Output).OutputMixer);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1); Codec1VolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Codec1);
} }
else //Digital Outputs
{
MasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Master);
SourceVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.Source);
MicsMasterVolumeLevel = new DmpsAudioOutput(card, eDmpsLevelType.MicsMaster);
}
} }
void BaseDevice_DMOutputChange(Switch device, DMOutputEventArgs args) void BaseDevice_DMOutputChange(Switch device, DMOutputEventArgs args)
{ {
Debug.Console(2, this, "Dmps Audio Controller Event Output: {0} EventId: {1}", args.Number, args.EventId.ToString());
switch (args.EventId) switch (args.EventId)
{ {
case DMOutputEventIds.OutputVuFeedBackEventId:
{
//Frequently called event that isn't needed
return;
}
case DMOutputEventIds.MasterVolumeFeedBackEventId: case DMOutputEventIds.MasterVolumeFeedBackEventId:
{ {
MasterVolumeLevel.VolumeLevelFeedback.FireUpdate(); MasterVolumeLevel.VolumeLevelFeedback.FireUpdate();
break; MasterVolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
} break;
}
case DMOutputEventIds.MasterMuteOnFeedBackEventId: case DMOutputEventIds.MasterMuteOnFeedBackEventId:
{ {
MasterVolumeLevel.MuteFeedback.FireUpdate(); MasterVolumeLevel.MuteFeedback.FireUpdate();
break; break;
} }
case DMOutputEventIds.SourceLevelFeedBackEventId: case DMOutputEventIds.SourceLevelFeedBackEventId:
{ {
SourceVolumeLevel.VolumeLevelFeedback.FireUpdate(); SourceVolumeLevel.VolumeLevelFeedback.FireUpdate();
break; SourceVolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
} break;
}
case DMOutputEventIds.SourceMuteOnFeedBackEventId:
{
SourceVolumeLevel.MuteFeedback.FireUpdate();
break;
}
case DMOutputEventIds.MicMasterLevelFeedBackEventId:
{
MicsMasterVolumeLevel.VolumeLevelFeedback.FireUpdate();
MicsMasterVolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
break;
}
case DMOutputEventIds.MicMasterMuteOnFeedBackEventId:
{
MicsMasterVolumeLevel.MuteFeedback.FireUpdate();
break;
}
case DMOutputEventIds.Codec1LevelFeedBackEventId: case DMOutputEventIds.Codec1LevelFeedBackEventId:
{ {
if(Codec1VolumeLevel != null) if (Codec1VolumeLevel != null)
Codec1VolumeLevel.VolumeLevelFeedback.FireUpdate(); {
break; Codec1VolumeLevel.VolumeLevelFeedback.FireUpdate();
} Codec1VolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
}
break;
}
case DMOutputEventIds.Codec1MuteOnFeedBackEventId: case DMOutputEventIds.Codec1MuteOnFeedBackEventId:
{ {
if (Codec1VolumeLevel != null) if (Codec1VolumeLevel != null)
Codec1VolumeLevel.MuteFeedback.FireUpdate(); Codec1VolumeLevel.MuteFeedback.FireUpdate();
break; break;
} }
case DMOutputEventIds.Codec2LevelFeedBackEventId: case DMOutputEventIds.Codec2LevelFeedBackEventId:
{ {
if (Codec2VolumeLevel != null) if (Codec2VolumeLevel != null)
Codec2VolumeLevel.VolumeLevelFeedback.FireUpdate(); {
break; Codec2VolumeLevel.VolumeLevelFeedback.FireUpdate();
} Codec2VolumeLevel.VolumeLevelScaledFeedback.FireUpdate();
}
break;
}
case DMOutputEventIds.Codec2MuteOnFeedBackEventId: case DMOutputEventIds.Codec2MuteOnFeedBackEventId:
{ {
if (Codec2VolumeLevel != null) if (Codec2VolumeLevel != null)
Codec2VolumeLevel.MuteFeedback.FireUpdate(); Codec2VolumeLevel.MuteFeedback.FireUpdate();
break; break;
} }
case DMOutputEventIds.MinVolumeFeedBackEventId:
{
Debug.Console(2, this, "MinVolumeFeedBackEventId: {0}", args.Index);
var level = MasterVolumeLevel as DmpsAudioOutputWithMixer;
if (level != null)
{
level.GetVolumeMin();
}
break;
}
case DMOutputEventIds.MaxVolumeFeedBackEventId:
{
Debug.Console(2, this, "MaxVolumeFeedBackEventId: {0}", args.Index);
var level = MasterVolumeLevel as DmpsAudioOutputWithMixer;
if (level != null)
{
level.GetVolumeMax();
}
break;
}
} }
} }
@ -106,11 +166,6 @@ namespace PepperDash.Essentials.DM
{ {
var joinMap = new DmpsAudioOutputControllerJoinMap(joinStart); var joinMap = new DmpsAudioOutputControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DmpsAudioOutputControllerJoinMap>(joinMapSerialized);
if (bridge != null) if (bridge != null)
{ {
bridge.AddJoinMap(Key, joinMap); bridge.AddJoinMap(Key, joinMap);
@ -125,6 +180,11 @@ namespace PepperDash.Essentials.DM
if (MasterVolumeLevel != null) if (MasterVolumeLevel != null)
{ {
SetUpDmpsAudioOutputJoins(trilist, MasterVolumeLevel, joinMap.MasterVolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, MasterVolumeLevel, joinMap.MasterVolumeLevel.JoinNumber);
var mixer = MasterVolumeLevel as DmpsAudioOutputWithMixer;
if (mixer != null)
{
trilist.SetUShortSigAction(joinMap.MixerPresetRecall.JoinNumber, mixer.RecallPreset);
}
} }
if (SourceVolumeLevel != null) if (SourceVolumeLevel != null)
@ -132,6 +192,11 @@ namespace PepperDash.Essentials.DM
SetUpDmpsAudioOutputJoins(trilist, SourceVolumeLevel, joinMap.SourceVolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, SourceVolumeLevel, joinMap.SourceVolumeLevel.JoinNumber);
} }
if (MicsMasterVolumeLevel != null)
{
SetUpDmpsAudioOutputJoins(trilist, MicsMasterVolumeLevel, joinMap.MicsMasterVolumeLevel.JoinNumber);
}
if (Codec1VolumeLevel != null) if (Codec1VolumeLevel != null)
{ {
SetUpDmpsAudioOutputJoins(trilist, Codec1VolumeLevel, joinMap.Codec1VolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, Codec1VolumeLevel, joinMap.Codec1VolumeLevel.JoinNumber);
@ -141,20 +206,20 @@ namespace PepperDash.Essentials.DM
{ {
SetUpDmpsAudioOutputJoins(trilist, Codec2VolumeLevel, joinMap.Codec2VolumeLevel.JoinNumber); SetUpDmpsAudioOutputJoins(trilist, Codec2VolumeLevel, joinMap.Codec2VolumeLevel.JoinNumber);
} }
} }
static void SetUpDmpsAudioOutputJoins(BasicTriList trilist, DmpsAudioOutput output, uint joinStart) static void SetUpDmpsAudioOutputJoins(BasicTriList trilist, DmpsAudioOutput output, uint joinStart)
{ {
var volumeLevelJoin = joinStart; var volumeLevelJoin = joinStart;
var volumeLevelScaledJoin = joinStart + 1;
var muteOnJoin = joinStart; var muteOnJoin = joinStart;
var muteOffJoin = joinStart + 1; var muteOffJoin = joinStart + 1;
var volumeUpJoin = joinStart + 2; var volumeUpJoin = joinStart + 2;
var volumeDownJoin = joinStart + 3; var volumeDownJoin = joinStart + 3;
var sendScaledVolumeJoin = joinStart + 4;
trilist.SetUShortSigAction(volumeLevelJoin, output.SetVolume);
output.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[volumeLevelJoin]); output.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[volumeLevelJoin]);
output.VolumeLevelScaledFeedback.LinkInputSig(trilist.UShortInput[volumeLevelScaledJoin]);
trilist.SetSigTrueAction(muteOnJoin, output.MuteOn); trilist.SetSigTrueAction(muteOnJoin, output.MuteOn);
output.MuteFeedback.LinkInputSig(trilist.BooleanInput[muteOnJoin]); output.MuteFeedback.LinkInputSig(trilist.BooleanInput[muteOnJoin]);
@ -163,19 +228,64 @@ namespace PepperDash.Essentials.DM
trilist.SetBoolSigAction(volumeUpJoin, output.VolumeUp); trilist.SetBoolSigAction(volumeUpJoin, output.VolumeUp);
trilist.SetBoolSigAction(volumeDownJoin, output.VolumeDown); trilist.SetBoolSigAction(volumeDownJoin, output.VolumeDown);
trilist.SetBoolSigAction(sendScaledVolumeJoin, output.SendScaledVolume);
trilist.SetUShortSigAction(volumeLevelJoin, output.SetVolume);
trilist.SetUShortSigAction(volumeLevelScaledJoin, output.SetVolumeScaled);
}
}
public class DmpsAudioOutputWithMixer : DmpsAudioOutput
{
CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo Mixer;
public DmpsAudioOutputWithMixer(Card.Dmps3OutputBase output, eDmpsLevelType type, CrestronControlSystem.Dmps3OutputMixerWithMonoAndStereo mixer)
: base(output, type)
{
Mixer = mixer;
GetVolumeMax();
GetVolumeMin();
}
public void GetVolumeMin()
{
MinLevel = (short)Mixer.MinVolumeFeedback.UShortValue;
if (VolumeLevelScaledFeedback != null)
{
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void GetVolumeMax()
{
MaxLevel = (short)Mixer.MaxVolumeFeedback.UShortValue;
if (VolumeLevelScaledFeedback != null)
{
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void RecallPreset(ushort preset)
{
Debug.Console(1, "DMPS Recalling Preset {0}", preset);
Mixer.PresetNumber.UShortValue = preset;
Mixer.RecallPreset();
} }
} }
public class DmpsAudioOutput : IBasicVolumeWithFeedback public class DmpsAudioOutput : IBasicVolumeWithFeedback
{ {
Card.Dmps3OutputBase Output; Card.Dmps3OutputBase Output;
eDmpsLevelType Type;
UShortInputSig Level; UShortInputSig Level;
eDmpsLevelType Type; private bool EnableVolumeSend;
private ushort VolumeLevelInput;
protected short MinLevel { get; set; }
protected short MaxLevel { get; set; }
public BoolFeedback MuteFeedback { get; private set; } public BoolFeedback MuteFeedback { get; private set; }
public IntFeedback VolumeLevelFeedback { get; private set; } public IntFeedback VolumeLevelFeedback { get; private set; }
public IntFeedback VolumeLevelScaledFeedback { get; private set; }
Action MuteOnAction; Action MuteOnAction;
Action MuteOffAction; Action MuteOffAction;
@ -185,8 +295,11 @@ namespace PepperDash.Essentials.DM
public DmpsAudioOutput(Card.Dmps3OutputBase output, eDmpsLevelType type) public DmpsAudioOutput(Card.Dmps3OutputBase output, eDmpsLevelType type)
{ {
Output = output; Output = output;
VolumeLevelInput = 0;
EnableVolumeSend = false;
Type = type; Type = type;
MinLevel = -800;
MaxLevel = 100;
switch (type) switch (type)
{ {
@ -194,14 +307,12 @@ namespace PepperDash.Essentials.DM
{ {
Level = output.MasterVolume; Level = output.MasterVolume;
MuteFeedback = new BoolFeedback( new Func<bool> (() => Output.MasterMuteOnFeedBack.BoolValue)); MuteFeedback = new BoolFeedback(new Func<bool>(() => Output.MasterMuteOnFeedBack.BoolValue));
VolumeLevelFeedback = new IntFeedback(new Func<int>(() => Output.MasterVolumeFeedBack.UShortValue)); VolumeLevelFeedback = new IntFeedback(new Func<int>(() => Output.MasterVolumeFeedBack.UShortValue));
MuteOnAction = new Action(Output.MasterMuteOn); MuteOnAction = new Action(Output.MasterMuteOn);
MuteOffAction = new Action(Output.MasterMuteOff); MuteOffAction = new Action(Output.MasterMuteOff);
VolumeUpAction = new Action<bool>((b) => Output.MasterVolumeUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => Output.MasterVolumeUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => Output.MasterVolumeDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => Output.MasterVolumeDown.BoolValue = b);
break; break;
} }
case eDmpsLevelType.MicsMaster: case eDmpsLevelType.MicsMaster:
@ -214,7 +325,6 @@ namespace PepperDash.Essentials.DM
MuteOffAction = new Action(Output.MicMasterMuteOff); MuteOffAction = new Action(Output.MicMasterMuteOff);
VolumeUpAction = new Action<bool>((b) => Output.MicMasterLevelUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => Output.MicMasterLevelUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => Output.MicMasterLevelDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => Output.MicMasterLevelDown.BoolValue = b);
break; break;
} }
case eDmpsLevelType.Source: case eDmpsLevelType.Source:
@ -243,7 +353,6 @@ namespace PepperDash.Essentials.DM
MuteOffAction = new Action(programOutput.Codec1MuteOff); MuteOffAction = new Action(programOutput.Codec1MuteOff);
VolumeUpAction = new Action<bool>((b) => programOutput.Codec1LevelUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => programOutput.Codec1LevelUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => programOutput.Codec1LevelDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => programOutput.Codec1LevelDown.BoolValue = b);
} }
else else
{ {
@ -274,7 +383,6 @@ namespace PepperDash.Essentials.DM
MuteOffAction = new Action(programOutput.Codec2MuteOff); MuteOffAction = new Action(programOutput.Codec2MuteOff);
VolumeUpAction = new Action<bool>((b) => programOutput.Codec2LevelUp.BoolValue = b); VolumeUpAction = new Action<bool>((b) => programOutput.Codec2LevelUp.BoolValue = b);
VolumeDownAction = new Action<bool>((b) => programOutput.Codec2LevelDown.BoolValue = b); VolumeDownAction = new Action<bool>((b) => programOutput.Codec2LevelDown.BoolValue = b);
} }
else else
{ {
@ -292,7 +400,38 @@ namespace PepperDash.Essentials.DM
break; break;
} }
} }
if (VolumeLevelFeedback != null)
{
VolumeLevelScaledFeedback = new IntFeedback(new Func<int>(() => ScaleVolumeFeedback(VolumeLevelFeedback.UShortValue)));
VolumeLevelFeedback.FireUpdate();
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void SetVolumeScaled(ushort level)
{
Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} level:{1} min:{2} max:{3}", Output.Name, level.ToString(), MinLevel.ToString(), MaxLevel.ToString());
VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel);
if (EnableVolumeSend == true)
{
Level.UShortValue = VolumeLevelInput;
}
}
public ushort ScaleVolumeFeedback(ushort level)
{
short signedLevel = (short)level;
Debug.Console(2, Debug.ErrorLogLevel.None, "Scaling DMPS volume:{0} feedback:{1} min:{2} max:{3}", Output.Name, signedLevel.ToString(), MinLevel.ToString(), MaxLevel.ToString());
return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel));
}
public void SendScaledVolume(bool pressRelease)
{
EnableVolumeSend = pressRelease;
if (pressRelease == false)
{
SetVolumeScaled(VolumeLevelInput);
}
} }
#region IBasicVolumeWithFeedback Members #region IBasicVolumeWithFeedback Members

View file

@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.DM
{
/// <summary>
/// Exposes the volume levels for microphones DMPS3 chassis
/// </summary>
public class DmpsMicrophoneController
{
private Dictionary<uint, DmpsMicrophone> Mics;
public DmpsMicrophoneController(CrestronControlSystem dmps)
{
Debug.Console(2, "Creating Dmps Microphone Controller");
Mics = new Dictionary<uint,DmpsMicrophone>();
foreach (var mic in dmps.Microphones)
{
Debug.Console(0, "Dmps Microphone Controller Adding Mic: {0} Name: {1}", mic.ID, mic.Name);
var dmpsMic = new DmpsMicrophone("processor-microphone" + mic.ID, mic.Name, mic);
DeviceManager.AddDevice(dmpsMic);
Mics.Add(mic.ID, dmpsMic);
}
dmps.MicrophoneChange += new MicrophoneChangeEventHandler(Dmps_MicrophoneChange);
}
void Dmps_MicrophoneChange(MicrophoneBase mic, GenericEventArgs args)
{
Debug.Console(2, "Dmps Microphone Controller Index: {0} EventId: {1}", mic.ID, args.EventId.ToString());
if(Mics.ContainsKey(mic.ID))
{
Mics[mic.ID].Event(args.EventId);
}
}
}
public class DmpsMicrophone : EssentialsBridgeableDevice, IBasicVolumeWithFeedback
{
MicrophoneBase Mic;
private bool EnableVolumeSend;
private ushort VolumeLevelInput;
protected short MinLevel { get; set; }
protected short MaxLevel { get; set; }
public BoolFeedback MuteFeedback { get; private set; }
public IntFeedback VolumeLevelFeedback { get; private set; }
public IntFeedback VolumeLevelScaledFeedback { get; private set; }
public StringFeedback NameFeedback { get; private set; }
Action MuteOnAction;
Action MuteOffAction;
public DmpsMicrophone(string key, string name, MicrophoneBase mic) : base(key, name)
{
Mic = mic;
VolumeLevelInput = 0;
EnableVolumeSend = false;
MinLevel = 0;
MaxLevel = 600;
MuteFeedback = new BoolFeedback(new Func<bool>(() => Mic.MuteOnFeedBack.BoolValue));
VolumeLevelFeedback = new IntFeedback(new Func<int>(() => Mic.GainFeedBack.UShortValue));
VolumeLevelScaledFeedback = new IntFeedback(new Func<int>(() => ScaleVolumeFeedback(VolumeLevelFeedback.UShortValue)));
NameFeedback = new StringFeedback(new Func<string>(() => "Microphone " + Mic.ID));
MuteOnAction = new Action(Mic.MuteOn);
MuteOffAction = new Action(Mic.MuteOff);
VolumeLevelFeedback.FireUpdate();
VolumeLevelScaledFeedback.FireUpdate();
NameFeedback.FireUpdate();
MuteFeedback.FireUpdate();
}
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new DmpsMicrophoneControllerJoinMap(joinStart);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.MicGain.JoinNumber]);
VolumeLevelScaledFeedback.LinkInputSig(trilist.UShortInput[joinMap.MicGainScaled.JoinNumber ]);
MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.MicMuteOn.JoinNumber]);
MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.MicMuteOff.JoinNumber]);
NameFeedback.LinkInputSig(trilist.StringInput[joinMap.MicName.JoinNumber]);
trilist.SetUShortSigAction(joinMap.MicGain.JoinNumber, SetVolume);
trilist.SetUShortSigAction(joinMap.MicGainScaled.JoinNumber, SetVolumeScaled);
trilist.SetBoolSigAction(joinMap.MicGainScaledSend.JoinNumber, SendScaledVolume);
trilist.SetSigTrueAction(joinMap.MicMuteOn.JoinNumber, MuteOnAction);
trilist.SetSigTrueAction(joinMap.MicMuteOff.JoinNumber, MuteOffAction);
}
public void Event(int id)
{
if (id == MicrophoneEventIds.MuteOnFeedBackEventId)
{
MuteFeedback.FireUpdate();
}
else if (id == MicrophoneEventIds.GainFeedBackEventId)
{
VolumeLevelFeedback.FireUpdate();
VolumeLevelScaledFeedback.FireUpdate();
}
}
public void SetVolumeScaled(ushort level)
{
VolumeLevelInput = (ushort)(level * (MaxLevel - MinLevel) / ushort.MaxValue + MinLevel);
if (EnableVolumeSend == true)
{
Mic.Gain.UShortValue = VolumeLevelInput;
}
}
public ushort ScaleVolumeFeedback(ushort level)
{
short signedLevel = (short)level;
return (ushort)((signedLevel - MinLevel) * ushort.MaxValue / (MaxLevel - MinLevel));
}
public void SendScaledVolume(bool pressRelease)
{
EnableVolumeSend = pressRelease;
if (pressRelease == false)
{
SetVolumeScaled(VolumeLevelInput);
}
}
#region IBasicVolumeWithFeedback Members
public void SetVolume(ushort level)
{
Mic.Gain.UShortValue = level;
}
public void MuteOn()
{
MuteOnAction();
}
public void MuteOff()
{
MuteOffAction();
}
#endregion
#region IBasicVolumeControls Members
public void VolumeUp(bool pressRelease)
{
}
public void VolumeDown(bool pressRelease)
{
}
public void MuteToggle()
{
if (MuteFeedback.BoolValue)
MuteOff();
else
MuteOn();
}
#endregion
}
}

View file

@ -25,10 +25,20 @@ namespace PepperDash.Essentials.DM
public CrestronControlSystem Dmps { get; set; } public CrestronControlSystem Dmps { get; set; }
public ISystemControl SystemControl { get; private set; } public ISystemControl SystemControl { get; private set; }
public bool? EnableRouting { get; private set; }
//Check if DMPS is a DMPS3-4K type for endpoint creation
public bool Dmps4kType { get; private set; }
//IroutingNumericEvent //IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange; public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
//Feedback for DMPS System Control
public BoolFeedback SystemPowerOnFeedback { get; private set; }
public BoolFeedback SystemPowerOffFeedback { get; private set; }
public BoolFeedback FrontPanelLockOnFeedback { get; private set; }
public BoolFeedback FrontPanelLockOffFeedback { get; private set; }
// Feedbacks for EssentialDM // Feedbacks for EssentialDM
public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; } public Dictionary<uint, IntFeedback> VideoOutputFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> AudioOutputFeedbacks { get; private set; } public Dictionary<uint, IntFeedback> AudioOutputFeedbacks { get; private set; }
@ -52,6 +62,7 @@ namespace PepperDash.Essentials.DM
public Dictionary<uint, string> InputNames { get; set; } public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; } public Dictionary<uint, string> OutputNames { get; set; }
public Dictionary<uint, DmCardAudioOutputController> VolumeControls { get; private set; } public Dictionary<uint, DmCardAudioOutputController> VolumeControls { get; private set; }
public DmpsMicrophoneController Microphones { get; private set; }
public const int RouteOffTime = 500; public const int RouteOffTime = 500;
Dictionary<PortNumberType, CTimer> RouteOffTimers = new Dictionary<PortNumberType, CTimer>(); Dictionary<PortNumberType, CTimer> RouteOffTimers = new Dictionary<PortNumberType, CTimer>();
@ -113,9 +124,39 @@ namespace PepperDash.Essentials.DM
public DmpsRoutingController(string key, string name, ISystemControl systemControl) public DmpsRoutingController(string key, string name, ISystemControl systemControl)
: base(key, name) : base(key, name)
{ {
Dmps = Global.ControlSystem; Dmps = Global.ControlSystem;
SystemControl = systemControl;
switch (systemControl.SystemControlType)
{
case eSystemControlType.Dmps34K150CSystemControl:
SystemControl = systemControl as Dmps34K150CSystemControl;
Dmps4kType = true;
SystemPowerOnFeedback = new BoolFeedback(() => { return true; });
SystemPowerOffFeedback = new BoolFeedback(() => { return false; });
break;
case eSystemControlType.Dmps34K200CSystemControl:
case eSystemControlType.Dmps34K250CSystemControl:
case eSystemControlType.Dmps34K300CSystemControl:
case eSystemControlType.Dmps34K350CSystemControl:
SystemControl = systemControl as Dmps34K300CSystemControl;
Dmps4kType = true;
SystemPowerOnFeedback = new BoolFeedback(() => { return true; });
SystemPowerOffFeedback = new BoolFeedback(() => { return false; });
break;
default:
SystemControl = systemControl as Dmps3SystemControl;
Dmps4kType = false;
SystemPowerOnFeedback = new BoolFeedback(() =>
{
return ((Dmps3SystemControl)SystemControl).SystemPowerOnFeedBack.BoolValue;
});
SystemPowerOffFeedback = new BoolFeedback(() =>
{
return ((Dmps3SystemControl)SystemControl).SystemPowerOffFeedBack.BoolValue;
});
break;
}
Debug.Console(1, this, "DMPS Type = {0}, 4K Type = {1}", systemControl.SystemControlType, Dmps4kType);
InputPorts = new RoutingPortCollection<RoutingInputPort>(); InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>(); OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@ -123,6 +164,15 @@ namespace PepperDash.Essentials.DM
TxDictionary = new Dictionary<uint, string>(); TxDictionary = new Dictionary<uint, string>();
RxDictionary = new Dictionary<uint, string>(); RxDictionary = new Dictionary<uint, string>();
FrontPanelLockOnFeedback = new BoolFeedback(() =>
{
return SystemControl.FrontPanelLockOnFeedback.BoolValue;
});
FrontPanelLockOffFeedback = new BoolFeedback(() =>
{
return SystemControl.FrontPanelLockOffFeedback.BoolValue;
});
VideoOutputFeedbacks = new Dictionary<uint, IntFeedback>(); VideoOutputFeedbacks = new Dictionary<uint, IntFeedback>();
AudioOutputFeedbacks = new Dictionary<uint, IntFeedback>(); AudioOutputFeedbacks = new Dictionary<uint, IntFeedback>();
VideoInputSyncFeedbacks = new Dictionary<uint, BoolFeedback>(); VideoInputSyncFeedbacks = new Dictionary<uint, BoolFeedback>();
@ -142,6 +192,8 @@ namespace PepperDash.Essentials.DM
SetupOutputCards(); SetupOutputCards();
SetupInputCards(); SetupInputCards();
Microphones = new DmpsMicrophoneController(Dmps);
} }
public override bool CustomActivate() public override bool CustomActivate()
@ -154,6 +206,42 @@ namespace PepperDash.Essentials.DM
// Subscribe to events // Subscribe to events
Dmps.DMInputChange += Dmps_DMInputChange; Dmps.DMInputChange += Dmps_DMInputChange;
Dmps.DMOutputChange += Dmps_DMOutputChange; Dmps.DMOutputChange += Dmps_DMOutputChange;
Dmps.DMSystemChange += Dmps_DMSystemChange;
foreach (var x in VideoOutputFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in AudioOutputFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in VideoInputSyncFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in InputEndpointOnlineFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in InputNameFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in OutputNameFeedbacks)
{
x.Value.FireUpdate();
}
foreach (var x in OutputEndpointOnlineFeedbacks)
{
x.Value.FireUpdate();
}
SystemPowerOnFeedback.FireUpdate();
SystemPowerOffFeedback.FireUpdate();
FrontPanelLockOnFeedback.FireUpdate();
FrontPanelLockOffFeedback.FireUpdate();
return base.CustomActivate(); return base.CustomActivate();
} }
@ -191,6 +279,12 @@ namespace PepperDash.Essentials.DM
} }
} }
public void SetRoutingEnable(bool enable)
{
CrestronEnvironment.Sleep(1000);
EnableRouting = enable;
}
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 DmpsRoutingControllerJoinMap(joinStart); var joinMap = new DmpsRoutingControllerJoinMap(joinStart);
@ -211,9 +305,26 @@ namespace PepperDash.Essentials.DM
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
//Link up system power only for non-4k DMPS3
if (SystemControl is Dmps3SystemControl)
{
trilist.SetBoolSigAction(joinMap.SystemPowerOn.JoinNumber, a => { if (a) { ((Dmps3SystemControl)SystemControl).SystemPowerOn(); } });
trilist.SetBoolSigAction(joinMap.SystemPowerOff.JoinNumber, a => { if (a) { ((Dmps3SystemControl)SystemControl).SystemPowerOff(); } });
}
SystemPowerOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemPowerOn.JoinNumber]);
SystemPowerOffFeedback.LinkInputSig(trilist.BooleanInput[joinMap.SystemPowerOff.JoinNumber]);
trilist.SetBoolSigAction(joinMap.FrontPanelLockOn.JoinNumber, a => { if (a) {SystemControl.FrontPanelLockOn();}});
trilist.SetBoolSigAction(joinMap.FrontPanelLockOff.JoinNumber, a => { if (a) {SystemControl.FrontPanelLockOff();}});
FrontPanelLockOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.FrontPanelLockOn.JoinNumber]);
FrontPanelLockOffFeedback.LinkInputSig(trilist.BooleanInput[joinMap.FrontPanelLockOff.JoinNumber]);
trilist.SetBoolSigAction(joinMap.EnableRouting.JoinNumber, SetRoutingEnable);
// Link up outputs // Link up outputs
LinkInputsToApi(trilist, joinMap); LinkInputsToApi(trilist, joinMap);
LinkOutputsToApi(trilist, joinMap); LinkOutputsToApi(trilist, joinMap);
} }
@ -272,6 +383,8 @@ namespace PepperDash.Essentials.DM
if (OutputNameFeedbacks[ioSlot] != null) if (OutputNameFeedbacks[ioSlot] != null)
{ {
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]); OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames.JoinNumber + ioSlotJoin]);
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputVideoNames.JoinNumber + ioSlotJoin]);
OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputAudioNames.JoinNumber + ioSlotJoin]);
} }
if (OutputVideoRouteNameFeedbacks[ioSlot] != null) if (OutputVideoRouteNameFeedbacks[ioSlot] != null)
{ {
@ -293,6 +406,14 @@ namespace PepperDash.Essentials.DM
private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap) private void LinkInputsToApi(BasicTriList trilist, DmpsRoutingControllerJoinMap joinMap)
{ {
if (Dmps4kType)
{
//DMPS-4K audio inputs 1-5 are aux inputs
for (uint i = 1; i <= 5; i++)
{
trilist.StringInput[joinMap.InputAudioNames.JoinNumber + i - 1].StringValue = String.Format("Aux Input {0}", i);
}
}
for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++) for (uint i = 1; i <= Dmps.SwitcherInputs.Count; i++)
{ {
Debug.Console(2, this, "Linking Input Card {0}", i); Debug.Console(2, this, "Linking Input Card {0}", i);
@ -300,15 +421,26 @@ namespace PepperDash.Essentials.DM
var ioSlot = i; var ioSlot = i;
var ioSlotJoin = ioSlot - 1; var ioSlotJoin = ioSlot - 1;
if (VideoInputSyncFeedbacks[ioSlot] != null) if (VideoInputSyncFeedbacks.ContainsKey(ioSlot) && VideoInputSyncFeedbacks[ioSlot] != null)
{ {
VideoInputSyncFeedbacks[ioSlot].LinkInputSig( VideoInputSyncFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]); trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber + ioSlotJoin]);
} }
if (InputNameFeedbacks[ioSlot] != null) if (InputNameFeedbacks.ContainsKey(ioSlot) && InputNameFeedbacks[ioSlot] != null)
{ {
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]); InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames.JoinNumber + ioSlotJoin]);
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputVideoNames.JoinNumber + ioSlotJoin]);
if (Dmps4kType)
{
//DMPS-4K Audio Inputs are offset by 5
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin + 5]);
}
else
{
InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputAudioNames.JoinNumber + ioSlotJoin]);
}
} }
trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s => trilist.SetStringSigAction(joinMap.InputNames.JoinNumber + ioSlotJoin, s =>
@ -333,7 +465,7 @@ namespace PepperDash.Essentials.DM
}); });
if (InputEndpointOnlineFeedbacks[ioSlot] != null) if (InputEndpointOnlineFeedbacks.ContainsKey(ioSlot) && InputEndpointOnlineFeedbacks[ioSlot] != null)
{ {
InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig( InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(
trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]); trilist.BooleanInput[joinMap.InputEndpointOnline.JoinNumber + ioSlotJoin]);
@ -384,7 +516,7 @@ namespace PepperDash.Essentials.DM
OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() => OutputNameFeedbacks[outputCard.Number] = new StringFeedback(() =>
{ {
if (outputCard.NameFeedback != null && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue)) if (outputCard.NameFeedback != null && outputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(outputCard.NameFeedback.StringValue))
{ {
Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue); Debug.Console(2, this, "Output Card {0} Name: {1}", outputCard.Number, outputCard.NameFeedback.StringValue);
return outputCard.NameFeedback.StringValue; return outputCard.NameFeedback.StringValue;
@ -430,14 +562,14 @@ namespace PepperDash.Essentials.DM
InputEndpointOnlineFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.EndpointOnlineFeedback); InputEndpointOnlineFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.EndpointOnlineFeedback);
if (inputCard.VideoDetectedFeedback != null) if (inputCard.VideoDetectedFeedback != null && inputCard.VideoDetectedFeedback.Supported)
{ {
VideoInputSyncFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.VideoDetectedFeedback.BoolValue); VideoInputSyncFeedbacks[inputCard.Number] = new BoolFeedback(() => inputCard.VideoDetectedFeedback.BoolValue);
} }
InputNameFeedbacks[inputCard.Number] = new StringFeedback(() => InputNameFeedbacks[inputCard.Number] = new StringFeedback(() =>
{ {
if (inputCard.NameFeedback != null && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue)) if (inputCard.NameFeedback != null && inputCard.NameFeedback != CrestronControlSystem.NullStringOutputSig && !string.IsNullOrEmpty(inputCard.NameFeedback.StringValue))
{ {
Debug.Console(2, this, "Input Card {0} Name: {1}", inputCard.Number, inputCard.NameFeedback.StringValue); Debug.Console(2, this, "Input Card {0} Name: {1}", inputCard.Number, inputCard.NameFeedback.StringValue);
return inputCard.NameFeedback.StringValue; return inputCard.NameFeedback.StringValue;
@ -586,7 +718,7 @@ namespace PepperDash.Essentials.DM
{ {
AddAudioOnlyOutputPort(number, "Program"); AddAudioOnlyOutputPort(number, "Program");
var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); var programOutput = new DmpsAudioOutputController(string.Format("processor-programAudioOutput"), "Program Audio Output", outputCard as Card.Dmps3ProgramOutput);
DeviceManager.AddDevice(programOutput); DeviceManager.AddDevice(programOutput);
} }
@ -598,7 +730,7 @@ namespace PepperDash.Essentials.DM
{ {
AddAudioOnlyOutputPort(number, "Aux1"); AddAudioOnlyOutputPort(number, "Aux1");
var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); var aux1Output = new DmpsAudioOutputController(string.Format("processor-aux1AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux1Output);
DeviceManager.AddDevice(aux1Output); DeviceManager.AddDevice(aux1Output);
} }
@ -607,7 +739,7 @@ namespace PepperDash.Essentials.DM
{ {
AddAudioOnlyOutputPort(number, "Aux2"); AddAudioOnlyOutputPort(number, "Aux2");
var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3OutputBase); var aux2Output = new DmpsAudioOutputController(string.Format("processor-aux2AudioOutput"), "Program Audio Output", outputCard as Card.Dmps3Aux2Output);
DeviceManager.AddDevice(aux2Output); DeviceManager.AddDevice(aux2Output);
} }
@ -719,40 +851,53 @@ namespace PepperDash.Essentials.DM
void Dmps_DMInputChange(Switch device, DMInputEventArgs args) void Dmps_DMInputChange(Switch device, DMInputEventArgs args)
{ {
//Debug.Console(2, this, "DMSwitch:{0} Input:{1} Event:{2}'", this.Name, args.Number, args.EventId.ToString()); try
switch (args.EventId)
{ {
case (DMInputEventIds.OnlineFeedbackEventId): switch (args.EventId)
{ {
Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); case (DMInputEventIds.OnlineFeedbackEventId):
InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); {
break; Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
} InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
case (DMInputEventIds.VideoDetectedEventId): break;
{ }
Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); case (DMInputEventIds.VideoDetectedEventId):
VideoInputSyncFeedbacks[args.Number].FireUpdate(); {
break; Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number);
} VideoInputSyncFeedbacks[args.Number].FireUpdate();
case (DMInputEventIds.InputNameEventId): break;
{ }
Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); case (DMInputEventIds.InputNameEventId):
InputNameFeedbacks[args.Number].FireUpdate(); {
break; Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number);
} if(InputNameFeedbacks.ContainsKey(args.Number))
{
InputNameFeedbacks[args.Number].FireUpdate();
}
break;
}
}
}
catch (Exception e)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "DMSwitch Input Change:{0} Input:{1} Event:{2}\rException: {3}", this.Name, args.Number, args.EventId.ToString(), e.ToString());
} }
} }
void Dmps_DMOutputChange(Switch device, DMOutputEventArgs args) void Dmps_DMOutputChange(Switch device, DMOutputEventArgs args)
{ {
Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString()); Debug.Console(2, this, "DMOutputChange Output: {0} EventId: {1}", args.Number, args.EventId.ToString());
if (args.EventId == DMOutputEventIds.OutputVuFeedBackEventId)
{
//Frequently called event that isn't needed
return;
}
var output = args.Number; var output = args.Number;
DMOutput outputCard = Dmps.SwitcherOutputs[output] as DMOutput; DMOutput outputCard = Dmps.SwitcherOutputs[output] as DMOutput;
if (args.EventId == DMOutputEventIds.VolumeEventId && if (args.EventId == DMOutputEventIds.VolumeEventId && VolumeControls.ContainsKey(output))
VolumeControls.ContainsKey(output))
{ {
VolumeControls[args.Number].VolumeEventFromChassis(); VolumeControls[args.Number].VolumeEventFromChassis();
} }
@ -812,6 +957,27 @@ namespace PepperDash.Essentials.DM
} }
void Dmps_DMSystemChange(Switch device, DMSystemEventArgs args)
{
switch (args.EventId)
{
case DMSystemEventIds.SystemPowerOnEventId:
case DMSystemEventIds.SystemPowerOffEventId:
{
SystemPowerOnFeedback.FireUpdate();
SystemPowerOffFeedback.FireUpdate();
break;
}
case DMSystemEventIds.FrontPanelLockOnEventId:
case DMSystemEventIds.FrontPanelLockOffEventId:
{
FrontPanelLockOnFeedback.FireUpdate();
FrontPanelLockOffFeedback.FireUpdate();
break;
}
}
}
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -829,6 +995,10 @@ namespace PepperDash.Essentials.DM
{ {
try try
{ {
if (EnableRouting == false)
{
return;
}
Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType); Debug.Console(2, this, "Attempting a DM route from input {0} to output {1} {2}", inputSelector, outputSelector, sigType);
@ -879,7 +1049,6 @@ namespace PepperDash.Essentials.DM
// NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES // NOTE THAT BITWISE COMPARISONS - TO CATCH ALL ROUTING TYPES
if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video) if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
{ {
output.VideoOut = input; output.VideoOut = input;
} }
@ -903,7 +1072,6 @@ namespace PepperDash.Essentials.DM
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput) if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{ {
output.USBRoutedTo = input; output.USBRoutedTo = input;
} }

View file

@ -61,6 +61,7 @@ namespace PepperDash.Essentials.DM
Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = rmc.Name;
if (rmc.VideoOutputResolutionFeedback != null) if (rmc.VideoOutputResolutionFeedback != null)
rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution.JoinNumber]); rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution.JoinNumber]);
if (rmc.EdidManufacturerFeedback != null) if (rmc.EdidManufacturerFeedback != null)
@ -329,7 +330,14 @@ namespace PepperDash.Essentials.DM
var parentDev = DeviceManager.GetDeviceForKey(pKey); var parentDev = DeviceManager.GetDeviceForKey(pKey);
if (parentDev is DmpsRoutingController) if (parentDev is DmpsRoutingController)
{ {
return GetDmRmcControllerForDmps(key, name, typeName, parentDev as DmpsRoutingController, props.ParentOutputNumber); if ((parentDev as DmpsRoutingController).Dmps4kType)
{
return GetDmRmcControllerForDmps4k(key, name, typeName, parentDev as DmpsRoutingController, props.ParentOutputNumber);
}
else
{
return GetDmRmcControllerForDmps(key, name, typeName, ipid, parentDev as DmpsRoutingController, props.ParentOutputNumber);
}
} }
if (!(parentDev is IDmSwitch)) if (!(parentDev is IDmSwitch))
{ {
@ -395,25 +403,47 @@ namespace PepperDash.Essentials.DM
return null; return null;
} }
private static CrestronGenericBaseDevice GetDmRmcControllerForDmps(string key, string name, string typeName, private static CrestronGenericBaseDevice GetDmRmcControllerForDmps(string key, string name, string typeName,
uint ipid, DmpsRoutingController controller, uint num)
{
Func<string, string, uint, DMOutput, CrestronGenericBaseDevice> dmpsHandler;
if (ChassisDict.TryGetValue(typeName.ToLower(), out dmpsHandler))
{
var output = controller.Dmps.SwitcherOutputs[num] as DMOutput;
if (output != null)
{
return dmpsHandler(key, name, ipid, output);
}
Debug.Console(0, Debug.ErrorLogLevel.Error,
"Cannot attach DM-RMC of type '{0}' to output {1} on DMPS chassis. Output is not a DM Output.",
typeName, num);
return null;
}
Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot create DM-RMC of type '{0}' to output {1} on DMPS chassis", typeName, num);
return null;
}
private static CrestronGenericBaseDevice GetDmRmcControllerForDmps4k(string key, string name, string typeName,
DmpsRoutingController controller, uint num) DmpsRoutingController controller, uint num)
{ {
Func<string, string, DMOutput, CrestronGenericBaseDevice> dmpsHandler; Func<string, string, DMOutput, CrestronGenericBaseDevice> dmps4kHandler;
if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out dmpsHandler)) if (ChassisCpu3Dict.TryGetValue(typeName.ToLower(), out dmps4kHandler))
{ {
var output = controller.Dmps.SwitcherOutputs[num] as DMOutput; var output = controller.Dmps.SwitcherOutputs[num] as DMOutput;
if (output != null) if (output != null)
{ {
return dmpsHandler(key, name, output); return dmps4kHandler(key, name, output);
} }
Debug.Console(0, Debug.ErrorLogLevel.Error, Debug.Console(0, Debug.ErrorLogLevel.Error,
"Cannot attach DM-RMC of type '{0}' to output {1} on DMPS chassis. Output is not a DM Output.", "Cannot attach DM-RMC of type '{0}' to output {1} on DMPS-4K chassis. Output is not a DM Output.",
typeName, num); typeName, num);
return null; return null;
} }
Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot create DM-RMC of type '{0}' to output {1} on DMPS chassis", typeName, num); Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot create DM-RMC of type '{0}' to output {1} on DMPS-4K chassis", typeName, num);
return null; return null;
} }

View file

@ -36,7 +36,7 @@ namespace PepperDash.Essentials.DM
var ipid = props.Control.IpIdInt; var ipid = props.Control.IpIdInt;
var pKey = props.ParentDeviceKey.ToLower(); var pKey = props.ParentDeviceKey.ToLower();
if (pKey == "processor") if (pKey == "processor")
{ {
// Catch constructor failures, mainly dues to IPID // Catch constructor failures, mainly dues to IPID
try try
@ -65,99 +65,135 @@ namespace PepperDash.Essentials.DM
{ {
Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e); Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e);
} }
return null;
} }
else
{
var parentDev = DeviceManager.GetDeviceForKey(pKey);
if (!(parentDev is IDmSwitch))
{
Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a DM Chassis.",
key, pKey);
return null;
}
var parentDev = DeviceManager.GetDeviceForKey(pKey);
DMInput dmInput;
bool isCpu3 = false;
if (parentDev is IDmSwitch)
{
// Get the Crestron chassis and link stuff up // Get the Crestron chassis and link stuff up
var switchDev = (parentDev as IDmSwitch); var switchDev = (parentDev as IDmSwitch);
var chassis = switchDev.Chassis; var chassis = switchDev.Chassis;
var num = props.ParentInputNumber; //Check that the input is within range of this chassis' possible inputs
if (num <= 0 || num > chassis.NumberOfInputs) var num = props.ParentInputNumber;
{ if (num <= 0 || num > chassis.NumberOfInputs)
Debug.Console(0, "Cannot create DM device '{0}'. Input number '{1}' is out of range", {
key, num); Debug.Console(0, "Cannot create DM device '{0}'. Input number '{1}' is out of range",
return null; key, num);
} return null;
else }
switchDev.TxDictionary.Add(num, key);
dmInput = chassis.Inputs[num];
//Determine if IpId is needed for this chassis type
if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 ||
chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps ||
chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps ||
chassis is DmMd128x128 || chassis is DmMd64x64)
{ {
var controller = (parentDev as IDmSwitch); isCpu3 = true;
controller.TxDictionary.Add(num, key);
} }
// Catch constructor failures, mainly dues to IPID }
try else if(parentDev is DmpsRoutingController)
{ {
// Must use different constructor for CPU3 chassis types. No IPID // Get the DMPS chassis and link stuff up
if (chassis is DmMd8x8Cpu3 || chassis is DmMd16x16Cpu3 || var dmpsDev = (parentDev as DmpsRoutingController);
chassis is DmMd32x32Cpu3 || chassis is DmMd8x8Cpu3rps || var chassis = dmpsDev.Dmps;
chassis is DmMd16x16Cpu3rps || chassis is DmMd32x32Cpu3rps||
chassis is DmMd128x128 || chassis is DmMd64x64) //Check that the input is within range of this chassis' possible inputs
{ var num = props.ParentInputNumber;
if (typeName.StartsWith("dmtx200")) if (num <= 0 || num > chassis.SwitcherInputs.Count)
return new DmTx200Controller(key, name, new DmTx200C2G(chassis.Inputs[num])); {
if (typeName.StartsWith("dmtx201c")) Debug.Console(0, "Cannot create DMPS device '{0}'. Input number '{1}' is out of range",
return new DmTx201CController(key, name, new DmTx201C(chassis.Inputs[num])); key, num);
if (typeName.StartsWith("dmtx201s")) return null;
return new DmTx201SController(key, name, new DmTx201S(chassis.Inputs[num])); }
if (typeName.StartsWith("dmtx4k100"))
return new DmTx4k100Controller(key, name, new DmTx4K100C1G(chassis.Inputs[num])); dmpsDev.TxDictionary.Add(num, key);
if (typeName.StartsWith("dmtx4kz100"))
return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(chassis.Inputs[num])); try
if (typeName.StartsWith("dmtx4k202")) {
return new DmTx4k202CController(key, name, new DmTx4k202C(chassis.Inputs[num])); dmInput = chassis.SwitcherInputs[num] as DMInput;
if (typeName.StartsWith("dmtx4kz202")) }
return new DmTx4kz202CController(key, name, new DmTx4kz202C(chassis.Inputs[num])); catch
if (typeName.StartsWith("dmtx4k302")) {
return new DmTx4k302CController(key, name, new DmTx4k302C(chassis.Inputs[num])); Debug.Console(0, "Cannot create DMPS device '{0}'. Input number '{1}' is not a DM input", key, num);
if (typeName.StartsWith("dmtx4kz302")) return null;
return new DmTx4kz302CController(key, name, new DmTx4kz302C(chassis.Inputs[num])); }
if (typeName.StartsWith("dmtx401")) }
return new DmTx401CController(key, name, new DmTx401C(chassis.Inputs[num]));
if (typeName.StartsWith("hdbasettx")) else
return new HDBaseTTxController(key, name, new HDTx3CB(chassis.Inputs[num])); {
} Debug.Console(0, "Cannot create DM device '{0}'. '{1}' is not a processor, DM Chassis or DMPS.", key, pKey);
else return null;
{
if (typeName.StartsWith("dmtx200"))
return new DmTx200Controller(key, name, new DmTx200C2G(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx201c"))
return new DmTx201CController(key, name, new DmTx201C(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx201s"))
return new DmTx201SController(key, name, new DmTx201S(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx4k100"))
return new DmTx4k100Controller(key, name, new DmTx4K100C1G(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx4kz100"))
return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx4k202"))
return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx4kz202"))
return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx4k302"))
return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx4kz302"))
return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("dmtx401"))
return new DmTx401CController(key, name, new DmTx401C(ipid, chassis.Inputs[num]));
if (typeName.StartsWith("hdbasettx"))
return new HDBaseTTxController(key, name, new HDTx3CB(ipid, chassis.Inputs[num]));
}
}
catch (Exception e)
{
Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e);
}
} }
return null; try
{
// Must use different constructor for CPU3 or DMPS3-4K types. No IPID
if (isCpu3 || Global.ControlSystemIsDmps4kType)
{
if (typeName.StartsWith("dmtx200"))
return new DmTx200Controller(key, name, new DmTx200C2G(dmInput));
if (typeName.StartsWith("dmtx201c"))
return new DmTx201CController(key, name, new DmTx201C(dmInput));
if (typeName.StartsWith("dmtx201s"))
return new DmTx201SController(key, name, new DmTx201S(dmInput));
if (typeName.StartsWith("dmtx4k100"))
return new DmTx4k100Controller(key, name, new DmTx4K100C1G(dmInput));
if (typeName.StartsWith("dmtx4kz100"))
return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(dmInput));
if (typeName.StartsWith("dmtx4k202"))
return new DmTx4k202CController(key, name, new DmTx4k202C(dmInput));
if (typeName.StartsWith("dmtx4kz202"))
return new DmTx4kz202CController(key, name, new DmTx4kz202C(dmInput));
if (typeName.StartsWith("dmtx4k302"))
return new DmTx4k302CController(key, name, new DmTx4k302C(dmInput));
if (typeName.StartsWith("dmtx4kz302"))
return new DmTx4kz302CController(key, name, new DmTx4kz302C(dmInput));
if (typeName.StartsWith("dmtx401"))
return new DmTx401CController(key, name, new DmTx401C(dmInput));
if (typeName.StartsWith("hdbasettx"))
return new HDBaseTTxController(key, name, new HDTx3CB(dmInput));
}
else
{
if (typeName.StartsWith("dmtx200"))
return new DmTx200Controller(key, name, new DmTx200C2G(ipid, dmInput));
if (typeName.StartsWith("dmtx201c"))
return new DmTx201CController(key, name, new DmTx201C(ipid, dmInput));
if (typeName.StartsWith("dmtx201s"))
return new DmTx201SController(key, name, new DmTx201S(ipid, dmInput));
if (typeName.StartsWith("dmtx4k100"))
return new DmTx4k100Controller(key, name, new DmTx4K100C1G(ipid, dmInput));
if (typeName.StartsWith("dmtx4kz100"))
return new DmTx4kz100Controller(key, name, new DmTx4kz100C1G(ipid, dmInput));
if (typeName.StartsWith("dmtx4k202"))
return new DmTx4k202CController(key, name, new DmTx4k202C(ipid, dmInput));
if (typeName.StartsWith("dmtx4kz202"))
return new DmTx4kz202CController(key, name, new DmTx4kz202C(ipid, dmInput));
if (typeName.StartsWith("dmtx4k302"))
return new DmTx4k302CController(key, name, new DmTx4k302C(ipid, dmInput));
if (typeName.StartsWith("dmtx4kz302"))
return new DmTx4kz302CController(key, name, new DmTx4kz302C(ipid, dmInput));
if (typeName.StartsWith("dmtx401"))
return new DmTx401CController(key, name, new DmTx401C(ipid, dmInput));
if (typeName.StartsWith("hdbasettx"))
return new HDBaseTTxController(key, name, new HDTx3CB(ipid, dmInput));
}
}
catch (Exception e)
{
Debug.Console(0, "[{0}] WARNING: Cannot create DM-TX device: {1}", key, e);
}
return null;
} }
} }
@ -185,11 +221,12 @@ namespace PepperDash.Essentials.DM
protected DmTxControllerBase(string key, string name, EndpointTransmitterBase hardware) protected DmTxControllerBase(string key, string name, EndpointTransmitterBase hardware)
: base(key, name, hardware) : base(key, name, hardware)
{ {
// if wired to a chassis, skip registration step in base class // if wired to a chassis or DMPS, skip registration step in base class
if (hardware.DMInput != null) if (hardware.DMInput != null || (Global.ControlSystemIsDmpsType && hardware.DMInput != null))
{ {
this.PreventRegistration = true; this.PreventRegistration = true;
} }
AddToFeedbackList(ActiveVideoInputFeedback); AddToFeedbackList(ActiveVideoInputFeedback);
} }
@ -226,6 +263,7 @@ namespace PepperDash.Essentials.DM
tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber]); tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus.JoinNumber]);
tx.AnyVideoInput.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution.JoinNumber]); tx.AnyVideoInput.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution.JoinNumber]);
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)tx.HdcpSupportCapability; trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)tx.HdcpSupportCapability;
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = tx.Name;
bool hdcpTypeSimple; bool hdcpTypeSimple;

View file

@ -93,6 +93,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="AirMedia\AirMediaPropertiesConfig.cs" /> <Compile Include="AirMedia\AirMediaPropertiesConfig.cs" />
<Compile Include="AirMedia\AirMediaController.cs" /> <Compile Include="AirMedia\AirMediaController.cs" />
<Compile Include="Chassis\DmpsMicrophoneController.cs" />
<Compile Include="Chassis\DmBladeChassisController.cs" /> <Compile Include="Chassis\DmBladeChassisController.cs" />
<Compile Include="Chassis\DmCardAudioOutput.cs" /> <Compile Include="Chassis\DmCardAudioOutput.cs" />
<Compile Include="Chassis\DmChassisController.cs" /> <Compile Include="Chassis\DmChassisController.cs" />

View file

@ -29,6 +29,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
{ {
[JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)]
public eCameraControlMode ControlMode { get; protected set; } public eCameraControlMode ControlMode { get; protected set; }
#region IRoutingOutputs Members #region IRoutingOutputs Members
@ -37,6 +38,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
#endregion #endregion
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
public bool CanPan public bool CanPan
{ {
get get
@ -44,7 +46,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan; return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan;
} }
} }
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
public bool CanTilt public bool CanTilt
{ {
get get
@ -52,7 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt; return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt;
} }
} }
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
public bool CanZoom public bool CanZoom
{ {
get get
@ -60,7 +62,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom; return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom;
} }
} }
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
public bool CanFocus public bool CanFocus
{ {
get get
@ -216,21 +218,11 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
var presetsCamera = cameraDevice as IHasCameraPresets; var presetsCamera = cameraDevice as IHasCameraPresets;
presetsCamera.PresetsListHasChanged += new EventHandler<EventArgs>((o, a) => presetsCamera.PresetsListHasChanged += new EventHandler<EventArgs>((o, a) =>
{ {
for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++) SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
{
int tempNum = i - 1;
string label = "";
var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i));
if (preset != null)
label = preset.Description;
trilist.SetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum), label);
}
}); });
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
for (int i = 0; i < joinMap.NumberOfPresets.JoinNumber; i++) for (int i = 0; i < joinMap.NumberOfPresets.JoinNumber; i++)
{ {
int tempNum = i; int tempNum = i;
@ -246,10 +238,35 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
presetsCamera.PresetStore(tempNum, label); presetsCamera.PresetStore(tempNum, label);
}); });
} }
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine)
{ return; }
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
};
}
}
private void SendCameraPresetNamesToApi(IHasCameraPresets presetsCamera, CameraControllerJoinMap joinMap, BasicTriList trilist)
{
for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++)
{
int tempNum = i - 1;
string label = "";
var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i));
if (preset != null)
label = preset.Description;
trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label);
} }
} }
} }
public class CameraPreset : PresetBase public class CameraPreset : PresetBase
{ {
public CameraPreset(int id, string description, bool isDefined, bool isDefinable) public CameraPreset(int id, string description, bool isDefined, bool isDefinable)

View file

@ -57,6 +57,11 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
void CameraMuteToggle(); void CameraMuteToggle();
} }
public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute
{
event EventHandler VideoUnmuteRequested;
}
public class CameraSelectedEventArgs : EventArgs public class CameraSelectedEventArgs : EventArgs
{ {
public CameraBase SelectedCamera { get; private set; } public CameraBase SelectedCamera { get; private set; }

View file

@ -525,6 +525,15 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public event EventHandler<EventArgs> PresetsListHasChanged; public event EventHandler<EventArgs> PresetsListHasChanged;
protected void OnPresetsListHasChanged()
{
var handler = PresetsListHasChanged;
if (handler == null)
return;
handler.Invoke(this, EventArgs.Empty);
}
public List<CameraPreset> Presets { get; private set; } public List<CameraPreset> Presets { get; private set; }
public void PresetSelect(int preset) public void PresetSelect(int preset)
@ -537,6 +546,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SavePreset(preset); SavePreset(preset);
} }
#endregion #endregion
#region IHasCameraFocusControl Members #region IHasCameraFocusControl Members

View file

@ -12,34 +12,40 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{ {
public class CodecActiveCallItem public class CodecActiveCallItem
{ {
[JsonProperty("name")] [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; } public string Name { get; set; }
[JsonProperty("number")] [JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)]
public string Number { get; set; } public string Number { get; set; }
[JsonProperty("type")] [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public eCodecCallType Type { get; set; } public eCodecCallType Type { get; set; }
[JsonProperty("status")] [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public eCodecCallStatus Status { get; set; } public eCodecCallStatus Status { get; set; }
[JsonProperty("direction")] [JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public eCodecCallDirection Direction { get; set; } public eCodecCallDirection Direction { get; set; }
[JsonProperty("id")] [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string Id { get; set; } public string Id { get; set; }
[JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)]
public bool IsOnHold { get; set; }
[JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)]
public TimeSpan Duration { get; set; }
//public object CallMetaData { get; set; } //public object CallMetaData { get; set; }
/// <summary> /// <summary>
/// Returns true when this call is any status other than /// Returns true when this call is any status other than
/// Unknown, Disconnected, Disconnecting /// Unknown, Disconnected, Disconnecting
/// </summary> /// </summary>
[JsonProperty("isActiveCall")] [JsonProperty("isActiveCall", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActiveCall public bool IsActiveCall
{ {
get get

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.Codec
{
public interface IHasCallHold
{
/// <summary>
/// Put the specified call on hold
/// </summary>
/// <param name="activeCall"></param>
void HoldCall(CodecActiveCallItem activeCall);
/// <summary>
/// Resume the specified call
/// </summary>
/// <param name="activeCall"></param>
void ResumeCall(CodecActiveCallItem activeCall);
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Codec
{
/// <summary>
/// Describes a device that has Do Not Disturb mode capability
/// </summary>
public interface IHasDoNotDisturbMode
{
/// <summary>
/// Indictes whether Do Not Disturb mode is on (Activated)
/// </summary>
BoolFeedback DoNotDisturbModeIsOnFeedback { get; }
/// <summary>
/// Activates Do Not Disturb mode
/// </summary>
void ActivateDoNotDisturbMode();
/// <summary>
/// Deactivates Do Not Disturb mode
/// </summary>
void DeactivateDoNotDisturbMode();
/// <summary>
/// Toggles Do Not Disturb mode
/// </summary>
void ToggleDoNotDisturbMode();
}
public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode
{
/// <summary>
/// Activates Do Not Disturb mode with a timeout
/// </summary>
/// <param name="timeout"></param>
void ActivateDoNotDisturbMode(int timeout);
}
}

View file

@ -23,9 +23,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public enum eCodecOccurrenceType public enum eCodecOccurrenceType
{ {
Unknown = 0, Unknown = 0,
Placed, Placed = 1,
Received, Received = 2,
NoAnswer NoAnswer = 3,
} }
/// <summary> /// <summary>

View file

@ -65,8 +65,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{ {
/// <summary> /// <summary>
/// Represents the contents of the directory /// Represents the contents of the directory
/// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data
/// </summary> /// </summary>
[JsonProperty("directoryResults")] [JsonIgnore]
public List<DirectoryItem> CurrentDirectoryResults { get; private set; } public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
[JsonProperty("contacts")] [JsonProperty("contacts")]

View file

@ -99,7 +99,7 @@ namespace PepperDash.Essentials.Devices.Displays
WarmupTime = 10000; WarmupTime = 10000;
CooldownTime = 8000; CooldownTime = 8000;
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet); CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet, true);
DeviceManager.AddDevice(CommunicationMonitor); DeviceManager.AddDevice(CommunicationMonitor);
VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80, VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,

View file

@ -108,6 +108,8 @@
<Compile Include="Codec\eCodecCallStatus.cs" /> <Compile Include="Codec\eCodecCallStatus.cs" />
<Compile Include="Codec\eMeetingPrivacy.cs" /> <Compile Include="Codec\eMeetingPrivacy.cs" />
<Compile Include="Codec\iCodecAudio.cs" /> <Compile Include="Codec\iCodecAudio.cs" />
<Compile Include="Codec\IHasCallHold.cs" />
<Compile Include="Codec\IHasDoNotDisturb.cs" />
<Compile Include="Codec\IHasExternalSourceSwitching.cs" /> <Compile Include="Codec\IHasExternalSourceSwitching.cs" />
<Compile Include="ImageProcessors\TVOneCorio.cs" /> <Compile Include="ImageProcessors\TVOneCorio.cs" />
<Compile Include="ImageProcessors\TVOneCorioPropertiesConfig.cs" /> <Compile Include="ImageProcessors\TVOneCorioPropertiesConfig.cs" />
@ -117,6 +119,7 @@
<Compile Include="ImageProcessors\AnalogWay\AnalogWayLiveCorePropertiesConfig.cs" /> <Compile Include="ImageProcessors\AnalogWay\AnalogWayLiveCorePropertiesConfig.cs" />
<Compile Include="SoftCodec\BlueJeansPc.cs" /> <Compile Include="SoftCodec\BlueJeansPc.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoCamera.cs" /> <Compile Include="VideoCodec\CiscoCodec\CiscoCamera.cs" />
<Compile Include="VideoCodec\CiscoCodec\CiscoCodecJoinMap.cs" />
<Compile Include="VideoCodec\CiscoCodec\RoomPresets.cs" /> <Compile Include="VideoCodec\CiscoCodec\RoomPresets.cs" />
<Compile Include="Cameras\CameraControl.cs" /> <Compile Include="Cameras\CameraControl.cs" />
<Compile Include="Display\PanasonicThDisplay.cs" /> <Compile Include="Display\PanasonicThDisplay.cs" />
@ -127,7 +130,9 @@
<Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" /> <Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" /> <Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" /> <Compile Include="VideoCodec\Interfaces\IHasSelfviewSize.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStandbyMode.cs" />
<Compile Include="VideoCodec\Interfaces\IHasStartMeeting.cs" /> <Compile Include="VideoCodec\Interfaces\IHasStartMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IJoinCalls.cs" />
<Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" /> <Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" />
<Compile Include="Codec\iHasCallFavorites.cs" /> <Compile Include="Codec\iHasCallFavorites.cs" />
<Compile Include="Codec\iHasCallHistory.cs" /> <Compile Include="Codec\iHasCallHistory.cs" />

View file

@ -41,12 +41,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void PanLeft() public void PanLeft()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId));
} }
public void PanRight() public void PanRight()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId));
} }
public void PanStop() public void PanStop()
@ -60,12 +60,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void TiltDown() public void TiltDown()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId));
} }
public void TiltUp() public void TiltUp()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId));
} }
public void TiltStop() public void TiltStop()
@ -79,12 +79,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public void ZoomIn() public void ZoomIn()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId));
} }
public void ZoomOut() public void ZoomOut()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId));
} }
public void ZoomStop() public void ZoomStop()
@ -97,7 +97,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
void Stop() void Stop()
{ {
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId)); ParentCodec.EnqueueCommand(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId));
} }
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
@ -116,7 +116,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
/// <summary> /// <summary>
/// The ID of the camera on the codec /// The ID of the camera on the codec
/// </summary> /// </summary>
protected uint CameraId { get; private set; } public uint CameraId { get; private set; }
/// <summary> /// <summary>
/// Valid range 1-15 /// Valid range 1-15
@ -202,7 +202,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed));
isPanning = true; isPanning = true;
} }
} }
@ -211,14 +211,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed));
isPanning = true; isPanning = true;
} }
} }
public void PanStop() public void PanStop()
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId));
isPanning = false; isPanning = false;
} }
@ -232,7 +232,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed));
isTilting = true; isTilting = true;
} }
} }
@ -241,14 +241,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed));
isTilting = true; isTilting = true;
} }
} }
public void TiltStop() public void TiltStop()
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId));
isTilting = false; isTilting = false;
} }
@ -260,7 +260,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed));
isZooming = true; isZooming = true;
} }
} }
@ -269,14 +269,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed));
isZooming = true; isZooming = true;
} }
} }
public void ZoomStop() public void ZoomStop()
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId));
isZooming = false; isZooming = false;
} }
@ -288,7 +288,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId));
isFocusing = true; isFocusing = true;
} }
} }
@ -297,20 +297,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
if (!isMoving) if (!isMoving)
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId));
isFocusing = true; isFocusing = true;
} }
} }
public void FocusStop() public void FocusStop()
{ {
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId));
isFocusing = false; isFocusing = false;
} }
public void TriggerAutoFocus() public void TriggerAutoFocus()
{ {
ParentCodec.SendText(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId)); ParentCodec.EnqueueCommand(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId));
} }
#endregion #endregion

View file

@ -0,0 +1,205 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges.JoinMaps;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{
public class CiscoCodecJoinMap : VideoCodecControllerJoinMap
{
#region Digital
[JoinName("PresentationLocalOnly")]
public JoinDataComplete PresentationLocalOnly = new JoinDataComplete(
new JoinData
{
JoinNumber = 205,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Presentation Local Only Feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PresentationLocalRemote")]
public JoinDataComplete PresentationLocalRemote = new JoinDataComplete(
new JoinData
{
JoinNumber = 206,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Presentation Local and Remote Feedback",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivateDoNotDisturbMode")]
public JoinDataComplete ActivateDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 241,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Activates Do Not Disturb Mode. FB High if active.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DeactivateDoNotDisturbMode")]
public JoinDataComplete DeactivateDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 242,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Deactivates Do Not Disturb Mode. FB High if deactivated.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ToggleDoNotDisturbMode")]
public JoinDataComplete ToggleDoNotDisturbMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 243,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Toggles Do Not Disturb Mode.",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivateStandby")]
public JoinDataComplete ActivateStandby = new JoinDataComplete(
new JoinData
{
JoinNumber = 246,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Activates Standby Mode. FB High if active.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DeactivateStandby")]
public JoinDataComplete DeactivateStandby = new JoinDataComplete(
new JoinData
{
JoinNumber = 247,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Deactivates Standby Mode. FB High if deactivated.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivateHalfWakeMode")]
public JoinDataComplete ActivateHalfWakeMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 248,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Activates Half Wake Mode. FB High if active.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("EnteringStandbyMode")]
public JoinDataComplete EnteringStandbyMode = new JoinDataComplete(
new JoinData
{
JoinNumber = 249,
JoinSpan = 1
},
new JoinMetadata
{
Description = "High to indicate that the codec is entering standby mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
#endregion
#region Analog
[JoinName("RingtoneVolume")]
public JoinDataComplete RingtoneVolume = new JoinDataComplete(
new JoinData
{
JoinNumber = 21,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Ringtone volume set/FB. Valid values are 0 - 100 in increments of 5 (5, 10, 15, 20, etc.)",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("PresentationSource")]
public JoinDataComplete PresentationSource = new JoinDataComplete(
new JoinData
{
JoinNumber = 201,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Presentation set/FB. Valid values are 0 - 6 depending on the codec model.",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Analog
});
#endregion
#region Serials
[JoinName("CommandToDevice")]
public JoinDataComplete CommandToDevice = new JoinDataComplete(
new JoinData
{
JoinNumber = 5,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Sends a serial command to the device. Do not include the delimiter, it will be added automatically.",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
#endregion
public CiscoCodecJoinMap(uint joinStart)
: base(joinStart, typeof(CiscoCodecJoinMap))
{
}
public CiscoCodecJoinMap(uint joinStart, Type type)
: base(joinStart, type)
{
}
}
}

View file

@ -52,6 +52,14 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("UiBranding")] [JsonProperty("UiBranding")]
public BrandingLogoProperties UiBranding { get; set; } public BrandingLogoProperties UiBranding { get; set; }
[JsonProperty("cameraInfo")]
public List<CameraInfo> CameraInfo { get; set; }
public CiscoSparkCodecPropertiesConfig()
{
CameraInfo = new List<CameraInfo>();
}
} }
public class SharingProperties public class SharingProperties
@ -68,4 +76,14 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("brandingUrl")] [JsonProperty("brandingUrl")]
public string BrandingUrl { get; set; } public string BrandingUrl { get; set; }
} }
/// <summary>
/// Describes configuration information for the near end cameras
/// </summary>
public class CameraInfo
{
public int CameraNumber { get; set; }
public string Name { get; set; }
public int SourceId { get; set; }
}
} }

View file

@ -26,6 +26,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
void CodecRoomPresetSelect(int preset); void CodecRoomPresetSelect(int preset);
void CodecRoomPresetStore(int preset, string description); void CodecRoomPresetStore(int preset, string description);
void SelectFarEndPreset(int preset);
} }
public static class RoomPresets public static class RoomPresets

View file

@ -112,16 +112,46 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; } public string Value { get; set; }
} }
public class RingVolume public class RingVolume : ValueProperty
{ {
public string valueSpaceRef { get; set; } public string valueSpaceRef { get; set; }
public string Value { get; set; }
string _Value;
/// <summary>
/// Sets Value and triggers the action when set
/// </summary>
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
public int Volume
{
get
{
return Int32.Parse(_Value);
}
}
} }
public class SoundsAndAlerts public class SoundsAndAlerts
{ {
public RingTone RingTone { get; set; } public RingTone RingTone { get; set; }
public RingVolume RingVolume { get; set; } public RingVolume RingVolume { get; set; }
public SoundsAndAlerts()
{
RingVolume = new RingVolume();
}
} }
public class Audio public class Audio
@ -131,6 +161,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Microphones Microphones { get; set; } public Microphones Microphones { get; set; }
public Output Output { get; set; } public Output Output { get; set; }
public SoundsAndAlerts SoundsAndAlerts { get; set; } public SoundsAndAlerts SoundsAndAlerts { get; set; }
public Audio()
{
SoundsAndAlerts = new SoundsAndAlerts();
}
} }
public class DefaultMode public class DefaultMode
@ -340,6 +376,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Delay Delay { get; set; } public Delay Delay { get; set; }
public Mode9 Mode { get; set; } public Mode9 Mode { get; set; }
public Mute2 Mute { get; set; } public Mute2 Mute { get; set; }
public AutoAnswer()
{
Mode = new Mode9();
Delay = new Delay();
Mute = new Mute2();
}
} }
public class Protocol public class Protocol
@ -440,6 +483,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public MaxTotalTransmitCallRate MaxTotalTransmitCallRate { get; set; } public MaxTotalTransmitCallRate MaxTotalTransmitCallRate { get; set; }
public MaxTransmitCallRate MaxTransmitCallRate { get; set; } public MaxTransmitCallRate MaxTransmitCallRate { get; set; }
public MultiStream MultiStream { get; set; } public MultiStream MultiStream { get; set; }
public Conference()
{
AutoAnswer = new AutoAnswer();
}
} }
public class LoginName public class LoginName
@ -690,6 +738,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Assignment Assignment { get; set; } public Assignment Assignment { get; set; }
public Gateway Gateway { get; set; } public Gateway Gateway { get; set; }
public SubnetMask SubnetMask { get; set; } public SubnetMask SubnetMask { get; set; }
public IPv4()
{
Address = new Address4();
}
} }
public class Address5 public class Address5
@ -841,6 +894,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public RemoteAccess RemoteAccess { get; set; } public RemoteAccess RemoteAccess { get; set; }
public Speed Speed { get; set; } public Speed Speed { get; set; }
public VLAN VLAN { get; set; } public VLAN VLAN { get; set; }
public Network()
{
IPv4 = new IPv4();
}
} }
public class Mode19 public class Mode19
@ -1797,11 +1855,23 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public UserInterface UserInterface { get; set; } public UserInterface UserInterface { get; set; }
public UserManagement UserManagement { get; set; } public UserManagement UserManagement { get; set; }
public Video2 Video { get; set; } public Video2 Video { get; set; }
public Configuration()
{
Audio = new Audio();
Conference = new Conference();
Network = new List<Network>();
}
} }
public class RootObject public class RootObject
{ {
public Configuration Configuration { get; set; } public Configuration Configuration { get; set; }
public RootObject()
{
Configuration = new Configuration();
}
} }
} }
} }

View file

@ -12,28 +12,28 @@ using PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
// Helper Classes for Proerties
public abstract class ValueProperty
{
/// <summary>
/// Triggered when Value is set
/// </summary>
public Action ValueChangedAction { get; set; }
protected void OnValueChanged()
{
var a = ValueChangedAction;
if (a != null)
a();
}
}
/// <summary> /// <summary>
/// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
/// </summary> /// </summary>
public class CiscoCodecStatus public class CiscoCodecStatus
{ {
// Helper Classes for Proerties
public abstract class ValueProperty
{
/// <summary>
/// Triggered when Value is set
/// </summary>
public Action ValueChangedAction { get; set; }
protected void OnValueChanged()
{
var a = ValueChangedAction;
if (a != null)
a();
}
}
public class ConnectionStatus public class ConnectionStatus
{ {
@ -262,11 +262,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; } public string Value { get; set; }
} }
public class DectectedConnector
{
public string Value { get; set; }
public int ConnectorId
{
get
{
if(!string.IsNullOrEmpty(Value))
{
return Convert.ToUInt16(Value);
}
else
return -1;
}
}
}
public class Camera public class Camera
{ {
public string id { get; set; } public string id { get; set; }
public Capabilities Capabilities { get; set; } public Capabilities Capabilities { get; set; }
public Connected Connected { get; set; } public Connected Connected { get; set; }
public DectectedConnector DetectedConnector { get; set; }
public Flip Flip { get; set; } public Flip Flip { get; set; }
public HardwareID HardwareID { get; set; } public HardwareID HardwareID { get; set; }
public MacAddress MacAddress { get; set; } public MacAddress MacAddress { get; set; }
@ -275,6 +294,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Position Position { get; set; } public Position Position { get; set; }
public SerialNumber SerialNumber { get; set; } public SerialNumber SerialNumber { get; set; }
public SoftwareID SoftwareID { get; set; } public SoftwareID SoftwareID { get; set; }
public Camera()
{
Manufacturer = new Manufacturer();
Model = new Model();
DetectedConnector = new DectectedConnector();
}
} }
public class Availability : ValueProperty public class Availability : ValueProperty
@ -298,11 +324,34 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
} }
} }
public class CallStatus : ValueProperty
{
string _Value;
public bool BoolValue { get; private set; }
public string Value
{
get
{
return _Value;
}
set
{
// If the incoming value is "Active" it sets the BoolValue true, otherwise sets it false
_Value = value;
BoolValue = value == "Connected";
OnValueChanged();
}
}
}
public class Status2 : ValueProperty public class Status2 : ValueProperty
{ {
string _Value; string _Value;
public bool BoolValue { get; private set; } public bool BoolValue { get; private set; }
public string Value public string Value
{ {
get get
@ -440,9 +489,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public CallId CallId { get; set; } public CallId CallId { get; set; }
} }
public class DoNotDisturb public class DoNotDisturb : ValueProperty
{ {
public string Value { get; set; } string _Value;
public bool BoolValue { get; private set; }
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
// If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "On" || value == "Active";
OnValueChanged();
}
}
} }
public class Mode public class Mode
@ -541,9 +607,47 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
} }
} }
public class SendingMode public class SendingMode : ValueProperty
{ {
public string Value { get; set; } string _Value;
/// <summary>
/// Sets Value and triggers the action when set
/// </summary>
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
public bool LocalOnly
{
get
{
if(string.IsNullOrEmpty(_Value))
return false;
return _Value.ToLower() == "localonly";
}
}
public bool LocalRemote
{
get
{
if(string.IsNullOrEmpty(_Value))
return false;
return _Value.ToLower() == "localremote";
}
}
} }
public class LocalInstance public class LocalInstance
@ -556,6 +660,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public LocalInstance() public LocalInstance()
{ {
Source = new Source2(); Source = new Source2();
SendingMode = new SendingMode();
} }
} }
@ -600,6 +705,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Conference2() public Conference2()
{ {
Presentation = new Presentation(); Presentation = new Presentation();
DoNotDisturb = new DoNotDisturb();
} }
} }
@ -863,6 +969,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Address4 Address { get; set; } public Address4 Address { get; set; }
public Gateway Gateway { get; set; } public Gateway Gateway { get; set; }
public SubnetMask SubnetMask { get; set; } public SubnetMask SubnetMask { get; set; }
public IPv4()
{
Address = new Address4();
}
} }
public class Address5 public class Address5
@ -905,6 +1016,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public IPv4 IPv4 { get; set; } public IPv4 IPv4 { get; set; }
public IPv6 IPv6 { get; set; } public IPv6 IPv6 { get; set; }
public VLAN VLAN { get; set; } public VLAN VLAN { get; set; }
public Network()
{
IPv4 = new IPv4();
}
} }
public class CurrentAddress public class CurrentAddress
@ -1380,12 +1496,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public class State : ValueProperty public class State : ValueProperty
{ {
string _value;
public bool BoolValue { get; private set; } public bool BoolValue { get; private set; }
public string Value // Valid values are Standby/EnteringStandby/Halfwake/Off public string Value // Valid values are Standby/EnteringStandby/Halfwake/Off
{ {
get { return _value; }
set set
{ {
_value = value;
// If the incoming value is "On" it sets the BoolValue true, otherwise sets it false // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "On" || value == "Standby"; BoolValue = value == "On" || value == "Standby";
OnValueChanged(); OnValueChanged();
@ -1927,9 +2047,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; } public string Value { get; set; }
} }
public class Duration public class Duration : ValueProperty
{ {
public string Value { get; set; } private string _Value;
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnValueChanged();
}
}
public TimeSpan DurationValue
{
get
{
return new TimeSpan(0, 0, Int32.Parse(_Value));
}
}
} }
public class FacilityServiceId public class FacilityServiceId
@ -1942,9 +2083,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public string Value { get; set; } public string Value { get; set; }
} }
public class PlacedOnHold public class PlacedOnHold : ValueProperty
{ {
public string Value { get; set; } public bool BoolValue { get; private set; }
public string Value
{
set
{
// If the incoming value is "True" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "True";
OnValueChanged();
}
}
} }
public class Protocol public class Protocol
@ -1985,13 +2136,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
public Protocol Protocol { get; set; } public Protocol Protocol { get; set; }
public ReceiveCallRate ReceiveCallRate { get; set; } public ReceiveCallRate ReceiveCallRate { get; set; }
public RemoteNumber RemoteNumber { get; set; } public RemoteNumber RemoteNumber { get; set; }
public Status2 Status { get; set; } public CallStatus Status { get; set; }
public TransmitCallRate TransmitCallRate { get; set; } public TransmitCallRate TransmitCallRate { get; set; }
public Call() public Call()
{ {
CallType = new CallType(); CallType = new CallType();
Status = new Status2(); Status = new CallStatus();
Duration = new Duration();
} }
} }
@ -2091,6 +2243,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
Conference = new Conference2(); Conference = new Conference2();
SystemUnit = new SystemUnit(); SystemUnit = new SystemUnit();
Video = new Video(); Video = new Video();
Conference = new Conference2();
Network = new List<Network>();
} }
} }

View file

@ -42,9 +42,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public Boolean WaitingForHost { get; private set; } public Boolean WaitingForHost { get; private set; }
[JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsLocked { get; private set; } public Boolean IsLocked { get; private set; }
[JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)]
public Boolean IsRecording { get; private set; }
public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked) public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording)
{ {
Id = id; Id = id;
Name = name; Name = name;
@ -55,6 +57,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
IsSharingMeeting = isSharingMeeting; IsSharingMeeting = isSharingMeeting;
WaitingForHost = waitingForHost; WaitingForHost = waitingForHost;
IsLocked = isLocked; IsLocked = isLocked;
IsRecording = isRecording;
} }
} }

View file

@ -15,4 +15,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
void StopRecording(); void StopRecording();
void ToggleRecording(); void ToggleRecording();
} }
public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording
{
BoolFeedback RecordConsentPromptIsVisible { get; }
/// <summary>
/// Used to agree or disagree to the meeting being recorded when prompted
/// </summary>
/// <param name="agree"></param>
void RecordingPromptAcknowledgement(bool agree);
}
} }

View file

@ -24,6 +24,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary> /// </summary>
/// <param name="participant"></param> /// <param name="participant"></param>
void SetParticipantAsHost(int userId); void SetParticipantAsHost(int userId);
/// <summary>
/// Admits a participant from the waiting room
/// </summary>
/// <param name="userId"></param>
void AdmitParticipantFromWaitingRoom(int userId);
} }
/// <summary> /// <summary>

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
/// <summary>
/// Describes a device that has Standby Mode capability
/// </summary>
public interface IHasStandbyMode
{
BoolFeedback StandbyIsOnFeedback { get; }
void StandbyActivate();
void StandbyDeactivate();
}
/// <summary>
/// Describes a device that has Half Waek Mode capability
/// </summary>
public interface IHasHalfWakeMode : IHasStandbyMode
{
BoolFeedback HalfWakeModeIsOnFeedback { get; }
BoolFeedback EnteringStandbyModeFeedback { get; }
void HalfwakeActivate();
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Devices.Common.Codec;
namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
public interface IJoinCalls
{
void JoinCall(CodecActiveCallItem activeCall);
void JoinAllCalls();
}
}

View file

@ -431,8 +431,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
m.MinutesBeforeMeeting = 5; m.MinutesBeforeMeeting = 5;
m.Id = i.ToString(); m.Id = i.ToString();
m.Organizer = "Employee " + 1; m.Organizer = "Employee " + 1;
m.StartTime = DateTime.Now.AddMinutes(6).AddHours(i); m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i);
m.EndTime = DateTime.Now.AddHours(i).AddMinutes(16); m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50);
m.Title = "Meeting " + i; m.Title = "Meeting " + i;
m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); m.Calls.Add(new Call() { Number = i + "meeting@fake.com"});
_CodecSchedule.Meetings.Add(m); _CodecSchedule.Meetings.Add(m);
@ -602,6 +602,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn); CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn);
SupportsCameraAutoMode = true;
CameraAutoModeIsOnFeedback.FireUpdate(); CameraAutoModeIsOnFeedback.FireUpdate();
DeviceManager.AddDevice(internalCamera); DeviceManager.AddDevice(internalCamera);
@ -609,7 +611,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
NearEndPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco NearEndPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco
NearEndPresets = PropertiesConfig.Presets; if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0)
{
NearEndPresets = PropertiesConfig.Presets;
}
else
{
for (int i = 1; i <= NearEndPresets.Capacity; i++)
{
var label = string.Format("Near End Preset {0}", i);
NearEndPresets.Add(new CodecRoomPreset(i, label, true, false));
}
}
FarEndRoomPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco FarEndRoomPresets = new List<CodecRoomPreset>(15); // Fix the capacity to emulate Cisco
@ -751,6 +764,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
SetConfig(Config); SetConfig(Config);
} }
public void SelectFarEndPreset(int i)
{
Debug.Console(1, this, "Selecting Far End Preset: {0}", i);
}
#endregion #endregion
protected override void CustomSetConfig(DeviceConfig config) protected override void CustomSetConfig(DeviceConfig config)

View file

@ -18,5 +18,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
[JsonProperty("presets")] [JsonProperty("presets")]
public List<CodecRoomPreset> Presets { get; set; } public List<CodecRoomPreset> Presets { get; set; }
public MockVcPropertiesConfig()
{
Favorites = new List<CodecActiveCallItem>();
Presets = new List<CodecRoomPreset>();
}
} }
} }

View file

@ -25,7 +25,7 @@ using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Devices.Common.VideoCodec namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs,
IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode
{ {
private const int XSigEncoding = 28591; private const int XSigEncoding = 28591;
protected const int MaxParticipants = 50; protected const int MaxParticipants = 50;
@ -152,6 +152,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
public abstract void AcceptCall(CodecActiveCallItem call); public abstract void AcceptCall(CodecActiveCallItem call);
public abstract void RejectCall(CodecActiveCallItem call); public abstract void RejectCall(CodecActiveCallItem call);
public abstract void SendDtmf(string s); public abstract void SendDtmf(string s);
public virtual void SendDtmf(string s, CodecActiveCallItem call) { }
#endregion #endregion
@ -259,10 +260,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary> /// </summary>
public virtual void ListCalls() public virtual void ListCalls()
{ {
Debug.Console(1, this, "Active Calls:");
var sb = new StringBuilder(); var sb = new StringBuilder();
foreach (var c in ActiveCalls) foreach (var c in ActiveCalls)
{ {
sb.AppendFormat("{0} {1} -- {2} {3}\n", c.Id, c.Number, c.Name, c.Status); sb.AppendFormat("id: {0} number: {1} -- name: {2} status: {3} onHold: {4}\r\n", c.Id, c.Number, c.Name, c.Status, c.IsOnHold);
} }
Debug.Console(1, this, "\n{0}\n", sb.ToString()); Debug.Console(1, this, "\n{0}\n", sb.ToString());
} }
@ -328,15 +331,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
LinkVideoCodecVolumeToApi(trilist, joinMap); LinkVideoCodecVolumeToApi(trilist, joinMap);
LinkVideoCodecInfoToApi(trilist, joinMap);
// Register for this event to link any functions that require the codec to be ready first
codec.IsReadyChange += (o, a) =>
{
if (codec is IHasCodecCameras)
{
LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap);
}
};
if (codec is ICommunicationMonitor) if (codec is ICommunicationMonitor)
{ {
LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap); LinkVideoCodecCommMonitorToApi(codec as ICommunicationMonitor, trilist, joinMap);
} }
if (codec is IHasCodecCameras)
{
LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap);
}
if (codec is IHasCodecSelfView) if (codec is IHasCodecSelfView)
{ {
@ -390,6 +400,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap);
} }
if (codec is IHasCallHistory)
{
LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap);
}
trilist.OnlineStatusChange += (device, args) => trilist.OnlineStatusChange += (device, args) =>
{ {
if (!args.DeviceOnLine) return; if (!args.DeviceOnLine) return;
@ -411,7 +426,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
if (codec is IHasCameraAutoMode) if (codec is IHasCameraAutoMode)
{ {
trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, true); trilist.SetBool(joinMap.CameraSupportsAutoMode.JoinNumber, SupportsCameraAutoMode);
(codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate(); (codec as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.FireUpdate();
} }
@ -436,6 +451,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
(codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate();
} }
if (codec is IHasCallHistory)
{
UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap);
}
SharingContentIsOnFeedback.FireUpdate(); SharingContentIsOnFeedback.FireUpdate();
trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall);
@ -444,6 +464,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}; };
} }
private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled);
trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled);
trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress);
trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber);
trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias);
trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id);
trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri);
trilist.OnlineStatusChange += (o, a) =>
{
if (a.DeviceOnLine)
{
trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled);
trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled);
trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress);
trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber);
trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias);
trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id);
trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri);
}
};
}
private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]); codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]);
@ -645,37 +690,37 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{ {
if (meetingIndex >= maxParticipants * offset) break; if (meetingIndex >= maxParticipants * offset) break;
Debug.Console(2, this, // Debug.Console(2, this,
@"Updating Participant on xsig: //@"Updating Participant on xsig:
Name: {0} (s{9}) //Name: {0} (s{9})
AudioMute: {1} (d{10}) //AudioMute: {1} (d{10})
VideoMute: {2} (d{11}) //VideoMute: {2} (d{11})
CanMuteVideo: {3} (d{12}) //CanMuteVideo: {3} (d{12})
CanUMuteVideo: {4} (d{13}) //CanUMuteVideo: {4} (d{13})
IsHost: {5} (d{14}) //IsHost: {5} (d{14})
HandIsRaised: {6} (d{15}) //HandIsRaised: {6} (d{15})
IsPinned: {7} (d{16}) //IsPinned: {7} (d{16})
ScreenIndexIsPinnedTo: {8} (a{17}) //ScreenIndexIsPinnedTo: {8} (a{17})
", //",
participant.Name, // participant.Name,
participant.AudioMuteFb, // participant.AudioMuteFb,
participant.VideoMuteFb, // participant.VideoMuteFb,
participant.CanMuteVideo, // participant.CanMuteVideo,
participant.CanUnmuteVideo, // participant.CanUnmuteVideo,
participant.IsHost, // participant.IsHost,
participant.HandIsRaisedFb, // participant.HandIsRaisedFb,
participant.IsPinnedFb, // participant.IsPinnedFb,
participant.ScreenIndexIsPinnedToFb, // participant.ScreenIndexIsPinnedToFb,
stringIndex + 1, // stringIndex + 1,
digitalIndex + 1, // digitalIndex + 1,
digitalIndex + 2, // digitalIndex + 2,
digitalIndex + 3, // digitalIndex + 3,
digitalIndex + 4, // digitalIndex + 4,
digitalIndex + 5, // digitalIndex + 5,
digitalIndex + 6, // digitalIndex + 6,
digitalIndex + 7, // digitalIndex + 7,
analogIndex + 1 // analogIndex + 1
); // );
//digitals //digitals
@ -947,16 +992,31 @@ ScreenIndexIsPinnedTo: {8} (a{17})
codec.CurrentDirectoryResultIsNotDirectoryRoot.LinkComplementInputSig( codec.CurrentDirectoryResultIsNotDirectoryRoot.LinkComplementInputSig(
trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]); trilist.BooleanInput[joinMap.DirectoryIsRoot.JoinNumber]);
trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot);
trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory); trilist.SetStringSigAction(joinMap.DirectorySearchString.JoinNumber, codec.SearchDirectory);
trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i)); trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap));
// Report feedback for number of contact methods for selected contact
trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot); trilist.SetSigFalseAction(joinMap.DirectoryRoot.JoinNumber, codec.SetCurrentDirectoryToRoot);
trilist.SetSigFalseAction(joinMap.DirectoryFolderBack.JoinNumber, codec.GetDirectoryParentFolderContents); trilist.SetSigFalseAction(joinMap.DirectoryFolderBack.JoinNumber, codec.GetDirectoryParentFolderContents);
if (codec.DirectoryRoot != null)
{
trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)codec.DirectoryRoot.CurrentDirectoryResults.Count);
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.DirectoryEntries.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
}
codec.DirectoryResultReturned += (sender, args) => codec.DirectoryResultReturned += (sender, args) =>
{ {
trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)args.Directory.CurrentDirectoryResults.Count); trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)args.Directory.CurrentDirectoryResults.Count);
@ -967,6 +1027,8 @@ ScreenIndexIsPinnedTo: {8} (a{17})
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); var directoryXSig = UpdateDirectoryXSig(args.Directory, !codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue);
Debug.Console(2, this, "Directory XSig Length: {0}", directoryXSig.Length);
trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig);
}; };
@ -981,40 +1043,154 @@ ScreenIndexIsPinnedTo: {8} (a{17})
}; };
} }
private void SelectDirectoryEntry(IHasDirectory codec, ushort i)
private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
var entry = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; if (i < 1 || i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return;
if (entry is DirectoryFolder) _selectedDirectoryItem = codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1];
if (_selectedDirectoryItem is DirectoryFolder)
{ {
codec.GetDirectoryFolderContents(entry.FolderId); codec.GetDirectoryFolderContents(_selectedDirectoryItem.FolderId);
return; trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0);
trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name);
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty);
trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber);
return;
} }
var dialableEntry = entry as IInvitableContact; // not a folder. Clear this value
trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty);
if (dialableEntry != null) var selectedContact = _selectedDirectoryItem as DirectoryContact;
{ if (selectedContact != null)
Dial(dialableEntry); {
return; trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, selectedContact.Name);
}
var entryToDial = entry as DirectoryContact; }
if (entryToDial == null) return; // Allow auto dial of selected line. Always dials first contact method
if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber))
{
var invitableEntry = _selectedDirectoryItem as IInvitableContact;
Dial(entryToDial.ContactMethods[0].Number); if (invitableEntry != null)
{
Dial(invitableEntry);
return;
}
var entryToDial = _selectedDirectoryItem as DirectoryContact;
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, selectedContact.ContactMethods[0].Number);
if (entryToDial == null) return;
Dial(entryToDial.ContactMethods[0].Number);
return;
}
else
{
// If auto dial is disabled...
var entryToDial = _selectedDirectoryItem as DirectoryContact;
if (entryToDial == null)
{
// Clear out values and actions from last selected item
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0);
trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty);
trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber);
return;
}
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count);
// Update the action to dial the selected contact method
trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) =>
{
if (u < 1 || u > entryToDial.ContactMethods.Count) return;
trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number));
});
// Sets DirectoryDialSelectedLine join action to dial first contact method
trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number));
var clearBytes = XSigHelpers.ClearOutputs();
trilist.SetString(joinMap.ContactMethods.JoinNumber,
Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length));
var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial);
trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig);
}
} }
/// <summary>
/// Generates the XSig data representing the available contact methods for the selected DirectoryContact
/// </summary>
/// <param name="contact"></param>
/// <returns></returns>
private string UpdateContactMethodsXSig(DirectoryContact contact)
{
const int maxMethods = 10;
const int maxStrings = 3;
const int offset = maxStrings;
var stringIndex = 0;
var arrayIndex = 0;
// Create a new token array and set the size to the number of methods times the total number of signals
var tokenArray = new XSigToken[maxMethods * offset];
Debug.Console(2, this, "Creating XSIG token array with size {0}", maxMethods * offset);
// TODO: Add code to generate XSig data
foreach (var method in contact.ContactMethods)
{
if (arrayIndex >= maxMethods * offset)
break;
//serials
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number);
tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString());
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString());
arrayIndex += offset;
stringIndex += maxStrings;
}
while (arrayIndex < maxMethods)
{
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty);
tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty);
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty);
arrayIndex += offset;
stringIndex += maxStrings;
}
return GetXSigString(tokenArray);
}
private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot)
{ {
var contactIndex = 1; var contactIndex = 1;
var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count]; var tokenArray = new XSigToken[directory.CurrentDirectoryResults.Count];
Debug.Console(2, this, "Is root {0} Directory Count: {1}", isRoot, directory.CurrentDirectoryResults.Count);
foreach (var entry in directory.CurrentDirectoryResults) foreach (var entry in directory.CurrentDirectoryResults)
{ {
var arrayIndex = contactIndex - 1; var arrayIndex = contactIndex - 1;
Debug.Console(2, this, "Entry Name: {0}, Folder ID: {1}", entry.Name, entry.FolderId);
if (entry is DirectoryFolder && entry.ParentFolderId == "root") if (entry is DirectoryFolder && entry.ParentFolderId == "root")
{ {
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name)); tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, String.Format("[+] {0}", entry.Name));
@ -1024,8 +1200,6 @@ ScreenIndexIsPinnedTo: {8} (a{17})
continue; continue;
} }
if (isRoot && String.IsNullOrEmpty(entry.FolderId)) continue;
tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name); tokenArray[arrayIndex] = new XSigSerialToken(contactIndex, entry.Name);
contactIndex++; contactIndex++;
@ -1039,8 +1213,34 @@ ScreenIndexIsPinnedTo: {8} (a{17})
trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber, trilist.SetSigFalseAction(joinMap.ManualDial.JoinNumber,
() => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue)); () => Dial(trilist.StringOutput[joinMap.CurrentDialString.JoinNumber].StringValue));
//End All calls for now //End All calls
trilist.SetSigFalseAction(joinMap.EndCall.JoinNumber, EndAllCalls); trilist.SetSigFalseAction(joinMap.EndAllCalls.JoinNumber, EndAllCalls);
//End a specific call, specified by index. Maximum 8 calls supported
for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++)
{
var callIndex = i;
trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () =>
{
if (callIndex < 0 || callIndex >= ActiveCalls.Count)
{
Debug.Console(2, this, "Cannot end call. No call found at index: {0}", callIndex);
return;
}
var call = ActiveCalls[callIndex];
if (call != null)
{
EndCall(call);
}
else
{
Debug.Console(0, this, "[End Call] Unable to find call at index '{0}'", i);
}
});
}
trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall);
@ -1052,30 +1252,112 @@ ScreenIndexIsPinnedTo: {8} (a{17})
Debug.Console(1, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming); Debug.Console(1, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming);
trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing); trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing);
if (args.CallItem.Direction == eCodecCallDirection.Incoming) if (args.CallItem.Direction == eCodecCallDirection.Incoming)
{ {
trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem));
trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem));
} trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name);
trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number);
}
else
{
trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty);
trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty);
}
trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig());
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
}; };
trilist.OnlineStatusChange += (device, args) => var joinCodec = this as IJoinCalls;
{ if (joinCodec != null)
if (!args.DeviceOnLine) return; {
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
// TODO [ ] Issue #868 for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC"); {
UpdateCallStatusXSig(); trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
}; {
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.Console(0, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
var holdCodec = this as IHasCallHold;
if (holdCodec != null)
{
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{
foreach (var call in ActiveCalls)
{
holdCodec.HoldCall(call);
}
});
for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++)
{
var index = i;
trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.Console(0, this, "[Hold Call] Unable to find call at index '{0}'", i);
}
});
trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () =>
{
if (index < 0 || index >= ActiveCalls.Count) return;
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.Console(0, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
// TODO [ ] Issue #868
trilist.SetString(joinMap.CurrentCallData.JoinNumber, "\xFC");
UpdateCallStatusXSig();
};
} }
private string UpdateCallStatusXSig() private string UpdateCallStatusXSig()
{ {
const int maxCalls = 8; const int maxCalls = 8;
const int maxStrings = 5; const int maxStrings = 6;
const int offset = 6; const int maxDigitals = 2;
const int offset = maxStrings + maxDigitals;
var stringIndex = 0; var stringIndex = 0;
var digitalIndex = maxStrings * maxCalls; var digitalIndex = maxStrings * maxCalls;
var arrayIndex = 0; var arrayIndex = 0;
@ -1087,7 +1369,8 @@ ScreenIndexIsPinnedTo: {8} (a{17})
if (arrayIndex >= maxCalls * offset) if (arrayIndex >= maxCalls * offset)
break; break;
//digitals //digitals
tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold);
//serials //serials
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty);
@ -1095,6 +1378,12 @@ ScreenIndexIsPinnedTo: {8} (a{17})
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString());
tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, call.Type.ToString());
tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, call.Status.ToString());
if(call.Duration != null)
{
// May need to verify correct string format here
var dur = string.Format("{0:c}", call.Duration);
tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur);
}
arrayIndex += offset; arrayIndex += offset;
stringIndex += maxStrings; stringIndex += maxStrings;
@ -1103,14 +1392,17 @@ ScreenIndexIsPinnedTo: {8} (a{17})
while (digitalIndex < maxCalls) while (digitalIndex < maxCalls)
{ {
//digitals //digitals
tokenArray[arrayIndex] = new XSigDigitalToken(digitalIndex + 1, false); tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false);
tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false);
//serials
//serials
tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty);
tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty);
tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty);
tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, String.Empty); tokenArray[arrayIndex + 4] = new XSigSerialToken(stringIndex + 4, String.Empty);
tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, String.Empty); tokenArray[arrayIndex + 5] = new XSigSerialToken(stringIndex + 5, String.Empty);
tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, String.Empty);
arrayIndex += offset; arrayIndex += offset;
stringIndex += maxStrings; stringIndex += maxStrings;
@ -1122,25 +1414,61 @@ ScreenIndexIsPinnedTo: {8} (a{17})
private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmf("0")); trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmf("1")); trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmf("2")); trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmf("3")); trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmf("4")); trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmf("5")); trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmf("6")); trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmf("7")); trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmf("8")); trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmf("9")); trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmf("*")); trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap));
trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmf("#")); trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap));
} }
/// <summary>
/// Sends the specified string as a DTMF command.
/// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine
/// Whther to send to a specific call index or to the last connected call
/// </summary>
/// <param name="s"></param>
/// <param name="trilist"></param>
/// <param name="joinMap"></param>
private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber))
{
SendDtmf(s);
}
else
{
var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber);
if (callIndex > 0 && callIndex <= 8)
{
var call = ActiveCalls[callIndex - 1];
if (call != null && call.IsActiveCall)
{
SendDtmf(s, call);
}
else
{
Debug.Console(0, this, "Warning: No call found at index {0} or call is not active.", callIndex);
}
}
else
{
Debug.Console(0, this, "Warning: Invalid call index specified. Please use a value of 1-8.");
}
}
}
private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
trilist.SetSigFalseAction(joinMap.CameraLayout.JoinNumber, codec.LocalLayoutToggle); trilist.SetSigFalseAction(joinMap.CameraLayout.JoinNumber, codec.LocalLayoutToggle);
codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CameraLayoutStringFb.JoinNumber]); codec.LocalLayoutFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentLayoutStringFb.JoinNumber]);
} }
private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
@ -1271,18 +1599,81 @@ ScreenIndexIsPinnedTo: {8} (a{17})
else camera.ZoomStop(); else camera.ZoomStop();
}); });
trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (b) camera.FocusNear();
else camera.FocusStop();
});
trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
if (b) camera.FocusFar();
else camera.FocusStop();
});
trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (camera == null) return;
camera.TriggerAutoFocus();
});
// Camera count
trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count);
// Camera names
for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++)
{
//Check the count first
if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null)
{
trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name);
}
else
{
trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, "");
}
}
//Camera Select //Camera Select
trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) => trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) =>
{ {
if (codec.SelectedCamera == null) return; if (i > 0 && i <= codec.Cameras.Count)
{
codec.SelectCamera(codec.Cameras[i].Key); codec.SelectCamera(codec.Cameras[i - 1].Key);
}
else
{
Debug.Console(0, this, "Unable to select. No camera found at index {0}", i);
}
}); });
// Set initial selected camera feedback
if (codec.SelectedCamera != null)
{
trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key));
}
codec.CameraSelected += (sender, args) => codec.CameraSelected += (sender, args) =>
{ {
var i = (ushort)codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); var i = (ushort)codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key);
trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1));
if (codec is IHasCodecRoomPresets) if (codec is IHasCodecRoomPresets)
{ {
return; return;
@ -1325,10 +1716,16 @@ ScreenIndexIsPinnedTo: {8} (a{17})
trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) => trilist.SetUShortSigAction(joinMap.CameraPresetSelect.JoinNumber, (i) =>
{ {
presetCodec.CodecRoomPresetSelect(i); presetCodec.CodecRoomPresetSelect(i);
trilist.SetUshort(joinMap.CameraPresetSelect.JoinNumber, i);
}); });
// Far End Presets
trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) =>
{
presetCodec.SelectFarEndPreset(i);
});
trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber,
() => () =>
{ {
@ -1347,7 +1744,96 @@ ScreenIndexIsPinnedTo: {8} (a{17})
}; };
} }
private string SetCameraPresetNames(IEnumerable<CodecRoomPreset> presets) // Following fields only used for Bridging
private int _selectedRecentCallItemIndex;
private CodecCallHistory.CallHistoryEntry _selectedRecentCallItem;
private DirectoryItem _selectedDirectoryItem;
private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
codec.CallHistory.RecentCallsListHasChanged += (o, a) =>
{
UpdateCallHistory(codec, trilist, joinMap);
};
// Selected item action and feedback
trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) =>
{
if (u == 0 || u > codec.CallHistory.RecentCalls.Count)
{
Debug.Console(2, this, "Recent Call History index out of range");
return;
}
_selectedRecentCallItemIndex = (int)(u - 1);
trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u);
var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex];
if (_selectedRecentCallItem != null)
{
trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name);
trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number);
trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem));
trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number));
}
else
{
trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty);
trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty);
trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber);
trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber);
}
});
}
private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
// Clear out selected item
_selectedRecentCallItemIndex = 0;
_selectedRecentCallItem = null;
trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0);
trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty);
trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty);
trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber);
//
trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count);
// Update the call history joins
var maxItems = joinMap.RecentCallNamesStart.JoinSpan;
// Create history
uint index = 0;
for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++)
{
trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name);
trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString());
trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType);
//i++;
index = i;
}
//foreach(var item in codec.CallHistory.RecentCalls)
//{
// trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name);
// trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString());
// trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType);
// i++;
//}
// Clears existing items
for (uint j = index; j < maxItems; j++)
{
trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty);
trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty);
trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0);
}
}
private string SetCameraPresetNames(IEnumerable<CodecRoomPreset> presets)
{ {
return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); return SetCameraPresetNames(presets.Select(p => p.Description).ToList());
} }

View file

@ -31,10 +31,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected void NotifyPropertyChanged(string propertyName) protected void NotifyPropertyChanged(string propertyName)
{ {
if (PropertyChanged != null) var handler = PropertyChanged;
{ if (handler != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); {
} handler(this, new PropertyChangedEventArgs(propertyName));
}
else
{
Debug.Console(2, "PropertyChanged event is NULL");
}
} }
#endregion #endregion
@ -778,13 +783,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
set set
{ {
//Debug.Console(2, "************************************setting value of meetingIsBeingRecorded to: {0}", value);
if (value != _meetingIsBeingRecorded) if (value != _meetingIsBeingRecorded)
{ {
_meetingIsBeingRecorded = value; _meetingIsBeingRecorded = value;
//Debug.Console(2, "********************************set value of meetingIsBeingRecorded to: {0}", _meetingIsBeingRecorded);
NotifyPropertyChanged("meetingIsBeingRecorded"); NotifyPropertyChanged("meetingIsBeingRecorded");
} }
} }
} }
public CallRecordInfo()
{
Debug.Console(2, Debug.ErrorLogLevel.Notice, "********************************************* CallRecordInfo() ******************************************");
}
} }
} }

View file

@ -24,16 +24,30 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor,
IRouting, IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode, IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMuteWithUnmuteReqeust, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin, IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting,
IHasMeetingLock, IHasMeetingRecording IHasMeetingLock, IHasMeetingRecordingWithPrompt
{ {
public event EventHandler VideoUnmuteRequested;
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; } public uint DefaultMeetingDurationMin { get; private set; }
private const string Delimiter = "\x0D\x0A"; /// <summary>
/// CR LF CR LF Delimits an echoed response to a command
/// </summary>
private const string EchoDelimiter = "\x0D\x0A\x0D\x0A";
private const string SendDelimiter = "\x0D";
/// <summary>
/// CR LF } CR LF Delimits a JSON response
/// </summary>
private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A";
private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" };
//"echo off\x0D\x0A\x0A\x0D\x0A"
private readonly GenericQueue _receiveQueue; private readonly GenericQueue _receiveQueue;
//private readonly CrestronQueue<string> _receiveQueue; //private readonly CrestronQueue<string> _receiveQueue;
@ -59,7 +73,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString()); _props = JsonConvert.DeserializeObject<ZoomRoomPropertiesConfig>(config.Properties.ToString());
_receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 512); _receiveQueue = new GenericQueue(Key + "-rxQueue", Thread.eThreadPriority.MediumPriority, 2048);
Communication = comm; Communication = comm;
@ -71,7 +85,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
else else
{ {
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000,
"zStatus SystemUnit\r"); "zStatus SystemUnit" + SendDelimiter);
} }
DeviceManager.AddDevice(CommunicationMonitor); DeviceManager.AddDevice(CommunicationMonitor);
@ -86,23 +100,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted;
_syncState.FirstJsonResponseReceived += (o, a) => SetUpSyncQueries();
PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync");
PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; PhonebookSyncState.InitialSyncCompleted += (o, a) => ResubscribeForAddedContacts();
PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true};
PortGather.LineReceived += Port_LineReceived; PortGather.LineReceived += Port_LineReceived;
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this); eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this);
Output1 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, Output1 = new RoutingOutputPort(RoutingPortNames.HdmiOut1,
eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this); eRoutingPortConnectionType.Hdmi, null, this);
Output2 = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, Output2 = new RoutingOutputPort(RoutingPortNames.HdmiOut2,
eRoutingSignalType.Video, eRoutingSignalType.Video,
eRoutingPortConnectionType.DisplayPort, null, this); eRoutingPortConnectionType.DisplayPort, null, this);
Output3 = new RoutingOutputPort(RoutingPortNames.HdmiOut3,
eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this);
SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc); SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc);
CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc); CameraIsOffFeedback = new BoolFeedback(CameraIsOffFeedbackFunc);
@ -152,6 +174,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable ); MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable );
MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded ); MeetingIsRecordingFeedback = new BoolFeedback(() => Status.Call.CallRecordInfo.meetingIsBeingRecorded );
RecordConsentPromptIsVisible = new BoolFeedback(() => _recordConsentPromptIsVisible);
SetUpRouting();
} }
public CommunicationGather PortGather { get; private set; } public CommunicationGather PortGather { get; private set; }
@ -281,6 +307,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public RoutingInputPort CodecOsdIn { get; private set; } public RoutingInputPort CodecOsdIn { get; private set; }
public RoutingOutputPort Output1 { get; private set; } public RoutingOutputPort Output1 { get; private set; }
public RoutingOutputPort Output2 { get; private set; } public RoutingOutputPort Output2 { get; private set; }
public RoutingOutputPort Output3 { get; private set; }
#region ICommunicationMonitor Members #region ICommunicationMonitor Members
@ -326,6 +353,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key); Debug.Console(1, this, "Selected Camera with key: '{0}'", camera.Key);
SelectedCamera = camera; SelectedCamera = camera;
if (CameraIsMutedFeedback.BoolValue)
{
CameraMuteOff();
}
} }
else else
{ {
@ -384,10 +416,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
_currentDirectoryResult = value; _currentDirectoryResult = value;
Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0}", Debug.Console(2, this, "CurrentDirectoryResult Updated. ResultsFolderId: {0} Contact Count: {1}",
_currentDirectoryResult.ResultsFolderId); _currentDirectoryResult.ResultsFolderId, _currentDirectoryResult.CurrentDirectoryResults.Count);
CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate();
OnDirectoryResultReturned(_currentDirectoryResult); OnDirectoryResultReturned(_currentDirectoryResult);
} }
@ -468,25 +498,63 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void SyncState_InitialSyncCompleted(object sender, EventArgs e) private void SyncState_InitialSyncCompleted(object sender, EventArgs e)
{ {
SetUpRouting();
SetIsReady(); SetIsReady();
} }
/// <summary>
/// Handles subscriptions to Status.Call and sub objects. Needs to be called whenever Status.Call is constructed
/// </summary>
private void SetUpCallFeedbackActions() private void SetUpCallFeedbackActions()
{ {
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate; Status.Call.Sharing.PropertyChanged -= HandleSharingStateUpdate;
Status.Call.Sharing.PropertyChanged += HandleSharingStateUpdate;
Status.Call.PropertyChanged += (o, a) => Status.Call.PropertyChanged -= HandleCallStateUpdate;
{ Status.Call.PropertyChanged += HandleCallStateUpdate;
if (a.PropertyName == "Info")
{ Status.Call.CallRecordInfo.PropertyChanged -= HandleCallRecordInfoStateUpdate;
Debug.Console(1, this, "Updating Call Status"); Status.Call.CallRecordInfo.PropertyChanged += HandleCallRecordInfoStateUpdate;
UpdateCallStatus();
}
};
} }
private void HandleCallRecordInfoStateUpdate(object sender, PropertyChangedEventArgs a)
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
var meetingInfo = new MeetingInfo(MeetingInfo.Id,
MeetingInfo.Name,
MeetingInfo.Host,
MeetingInfo.Password,
GetSharingStatus(),
GetIsHostMyself(),
MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo;
}
}
private void HandleCallStateUpdate(object sender, PropertyChangedEventArgs a)
{
switch (a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
}
private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a) private void HandleSharingStateUpdate(object sender, PropertyChangedEventArgs a)
{ {
if (a.PropertyName != "State") if (a.PropertyName != "State")
@ -504,19 +572,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
var sharingStatus = GetSharingStatus(); var sharingStatus = GetSharingStatus();
MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue); MeetingInfo = new MeetingInfo("", "", "", "", sharingStatus, GetIsHostMyself(), true, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
return; return;
} }
var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None", var meetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, Participants.Host != null ? Participants.Host.Name : "None",
MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue); MeetingInfo.Password, GetSharingStatus(), GetIsHostMyself(), MeetingInfo.IsSharingMeeting, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(1, this, "Error processing state property update. {0}", e.Message); Debug.Console(1, this, "Error processing state property update. {0}", e.Message);
Debug.Console(2, this, e.StackTrace); Debug.Console(2, this, e.StackTrace);
MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue); MeetingInfo = new MeetingInfo("", "", "", "", "None", false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
} }
} }
@ -525,6 +593,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// </summary> /// </summary>
private void SetUpFeedbackActions() private void SetUpFeedbackActions()
{ {
// Set these up initially.
SetUpCallFeedbackActions();
Configuration.Audio.Output.PropertyChanged += (o, a) => Configuration.Audio.Output.PropertyChanged += (o, a) =>
{ {
if (a.PropertyName == "Volume") if (a.PropertyName == "Volume")
@ -619,7 +690,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
MeetingInfo.IsHost, MeetingInfo.IsHost,
MeetingInfo.IsSharingMeeting, MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost, MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
); );
} }
}; };
@ -652,41 +724,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
}; };
Status.Call.Sharing.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "State")
{
SharingContentIsOnFeedback.FireUpdate();
ReceivingContent.FireUpdate();
}
};
Status.Call.PropertyChanged += (o, a) =>
{
switch(a.PropertyName)
{
case "Info":
{
Debug.Console(1, this, "Updating Call Status");
UpdateCallStatus();
break;
}
case "Status":
{
UpdateCallStatus();
break;
}
}
};
Status.Call.CallRecordInfo.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "meetingIsBeingRecorded")
{
MeetingIsRecordingFeedback.FireUpdate();
}
};
Status.Sharing.PropertyChanged += (o, a) => Status.Sharing.PropertyChanged += (o, a) =>
{ {
@ -718,7 +755,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(), GetIsHostMyself(),
MeetingInfo.IsSharingMeeting, MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost, MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue); MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
break; break;
} }
@ -904,7 +942,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "Sending: '{0}'", command); Debug.Console(1, this, "Sending: '{0}'", command);
} }
Communication.SendText(command + Delimiter); Communication.SendText(command + SendDelimiter);
} }
/// <summary> /// <summary>
@ -914,13 +952,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="args"></param> /// <param name="args"></param>
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{ {
//if (CommDebuggingIsOn) //Debug.Console(0, this, "Port_LineReceived");
// Debug.Console(1, this, "Gathered: '{0}'", args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); if (args.Delimiter != JsonDelimiter)
{
// Debug.Console(0, this,
//@"Non JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
ProcessNonJsonResponse(args.Text);
return;
}
else
{
// Debug.Console(0, this,
//@"JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, DeserializeResponse));
//_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage));
}
} }
/// <summary> /// <summary>
/// Queues the initial queries to be sent upon connection /// Queues the initial queries to be sent upon connection
/// </summary> /// </summary>
@ -979,6 +1032,93 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.StartSync(); _syncState.StartSync();
} }
private void SetupSession()
{
// disable echo of commands
SendText("echo off");
// switch to json format
// set feedback exclusions
// Currently the feedback exclusions don't work when using the API in JSON response mode
// But leave these here in case the API gets updated in the future
// These may work as of 5.9.4
// In 5.9.4 we're getting sent an AddedContact message for every contact in the phonebook on connect, which is redunant and way too much data
// We want to exclude these messages right away until after we've retrieved the entire phonebook and then we can re-enable them
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
SendText("zStatus SystemUnit");
}
/// <summary>
/// Removes the feedback exclusion for added contacts
/// </summary>
private void ResubscribeForAddedContacts()
{
SendText("zFeedback Register Op: in Path: /Event/Phonebook/AddedContact");
}
/// <summary>
/// Processes non-JSON responses as their are received
/// </summary>
/// <param name="response"></param>
private void ProcessNonJsonResponse(string response)
{
if (response.Contains("client_loop: send disconnect: Broken pipe"))
{
Debug.Console(1, this, Debug.ErrorLogLevel.Error,
"Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected.");
return;
}
if (!_syncState.InitialSyncComplete)
{
if(response.ToLower().Contains("*r login successful"))
{
_syncState.LoginResponseReceived();
SendText("format json");
SetupSession();
}
//switch (response.Trim().ToLower()) // remove the whitespace
//{
// case "*r login successful":
// {
// _syncState.LoginMessageReceived();
// //// Fire up a thread to send the intial commands.
// //CrestronInvoke.BeginInvoke(o =>
// //{
// // disable echo of commands
// SendText("echo off");
// // switch to json format
// SendText("format json");
// // set feedback exclusions
// // Currently the feedback exclusions don't work when using the API in JSON response mode
// // But leave these here in case the API gets updated in the future
// // These may work as of 5.9.4
// if (_props.DisablePhonebookAutoDownload)
// {
// SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
// }
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
// //});
// break;
// }
//}
}
}
/// <summary> /// <summary>
/// Processes messages as they are dequeued /// Processes messages as they are dequeued
/// </summary> /// </summary>
@ -1006,7 +1146,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter);
if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + EchoDelimiter)
// Check for the beginning of a new JSON message // Check for the beginning of a new JSON message
{ {
_jsonFeedbackMessageIsIncoming = true; _jsonFeedbackMessageIsIncoming = true;
@ -1023,7 +1163,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
return; return;
} }
if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + EchoDelimiter)
// Check for the end of a JSON message // Check for the end of a JSON message
{ {
_jsonMessage.Append(message); _jsonMessage.Append(message);
@ -1068,7 +1208,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
case "*r login successful": case "*r login successful":
{ {
_syncState.LoginMessageReceived(); _syncState.LoginResponseReceived();
// Fire up a thread to send the intial commands. // Fire up a thread to send the intial commands.
@ -1090,7 +1230,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist"); SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
Thread.Sleep(100); Thread.Sleep(100);
if (!_props.DisablePhonebookAutoDownload) if (_props.DisablePhonebookAutoDownload)
{ {
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact"); SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
} }
@ -1121,6 +1261,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var message = JObject.Parse(trimmedResponse); var message = JObject.Parse(trimmedResponse);
if (!_syncState.FirstJsonResponseWasReceived)
{
_syncState.ReceivedFirstJsonResponse();
}
var eType = var eType =
(eZoomRoomResponseType) (eZoomRoomResponseType)
Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true); Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true);
@ -1129,7 +1274,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var responseObj = message[topKey]; var responseObj = message[topKey];
Debug.Console(1, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString()); Debug.Console(1, this, "{0} Response Received. topKey: '{1}'\n{2}", eType, topKey, responseObj.ToString().Replace("\n", CrestronEnvironment.NewLine));
switch (eType) switch (eType)
{ {
@ -1182,6 +1327,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// This result will always be the complete contents of the directory and never // This result will always be the complete contents of the directory and never
// A subset of the results via a search // A subset of the results via a search
// Clear out any existing data
Status.Phonebook = new zStatus.Phonebook();
JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook); JsonConvert.PopulateObject(responseObj.ToString(), Status.Phonebook);
var directoryResults = var directoryResults =
@ -1195,10 +1343,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count); PhonebookSyncState.SetNumberOfContacts(Status.Phonebook.Contacts.Count);
} }
if (directoryResults.ResultsFolderId != "root") directoryResults.ResultsFolderId = "root";
{
directoryResults.ResultsFolderId = "root";
}
DirectoryRoot = directoryResults; DirectoryRoot = directoryResults;
@ -1308,7 +1453,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(), GetIsHostMyself(),
MeetingInfo.IsSharingMeeting, MeetingInfo.IsSharingMeeting,
MeetingInfo.WaitingForHost, MeetingInfo.WaitingForHost,
MeetingIsLockedFeedback.BoolValue); MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue);
MeetingInfo = meetingInfo; MeetingInfo = meetingInfo;
PrintCurrentCallParticipants(); PrintCurrentCallParticipants();
@ -1485,7 +1631,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "videounmuterequest": case "videounmuterequest":
{ {
// TODO: notify room of a request to unmute video var handler = VideoUnmuteRequested;
if (handler != null)
{
handler(this, null);
}
break; break;
} }
case "meetingneedspassword": case "meetingneedspassword":
@ -1517,14 +1669,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null) if (MeetingInfo == null)
{ {
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
UpdateCallStatus(); UpdateCallStatus();
break; break;
} }
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), false, false, true, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
UpdateCallStatus(); UpdateCallStatus();
@ -1534,12 +1686,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (MeetingInfo == null) if (MeetingInfo == null)
{ {
MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "", MeetingInfo = new MeetingInfo("Waiting For Host", "Waiting For Host", "Waiting For Host", "",
GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), false, false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break; break;
} }
MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password, MeetingInfo = new MeetingInfo(MeetingInfo.Id, MeetingInfo.Name, MeetingInfo.Host, MeetingInfo.Password,
GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue); GetSharingStatus(), GetIsHostMyself(), false, false, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break; break;
} }
@ -1548,12 +1700,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// TODO: notify user that host has disabled unmuting video // TODO: notify user that host has disabled unmuting video
break; break;
} }
case "updatedcallrecordinfo": case "updatecallrecordinfo":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo); JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.CallRecordInfo);
break; break;
} }
case "recordingconsent":
{
_recordConsentPromptIsVisible = responseObj["isShow"].Value<bool>();
RecordConsentPromptIsVisible.FireUpdate();
break;
}
case "phonecallstatus": case "phonecallstatus":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall); JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall);
@ -1623,7 +1781,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (result.Success) if (result.Success)
{ {
MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue); MeetingInfo = new MeetingInfo("", "", "", "", "", true, true, MeetingInfo.WaitingForHost, MeetingIsLockedFeedback.BoolValue, MeetingIsRecordingFeedback.BoolValue);
break; break;
} }
@ -1642,19 +1800,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
case "login": case "login":
{ {
_syncState.LoginMessageReceived(); _syncState.LoginResponseReceived();
if (!_syncState.InitialQueryMessagesWereSent) SetupSession();
{
SetUpSyncQueries();
}
JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); JsonConvert.PopulateObject(responseObj.ToString(), Status.Login);
break; break;
} }
case "systemunit": case "systemunit":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit);
break; break;
@ -1720,6 +1876,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
case "video camera line": case "video camera line":
{ {
Status.Cameras.Clear();
JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras); JsonConvert.PopulateObject(responseObj.ToString(), Status.Cameras);
if (!_syncState.CamerasHaveBeenSetUp) if (!_syncState.CamerasHaveBeenSetUp)
@ -1824,12 +1982,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
// If not crrently in a meeting, intialize the call object // If not crrently in a meeting, intialize the call object
if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING) if (callStatus != zStatus.eCallStatus.IN_MEETING && callStatus != zStatus.eCallStatus.CONNECTING_MEETING)
{ {
//Debug.Console(1, this, "[UpdateCallStatus] Creating new Status.Call object");
Status.Call = new zStatus.Call {Status = callStatus}; Status.Call = new zStatus.Call {Status = callStatus};
// Resubscribe to all property change events after Status.Call is reconstructed
SetUpCallFeedbackActions();
OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected}); OnCallStatusChange(new CodecActiveCallItem() {Status = eCodecCallStatus.Disconnected});
SetUpCallFeedbackActions();
} }
if (ActiveCalls.Count == 0) if (ActiveCalls.Count == 0)
@ -1969,7 +2126,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
GetIsHostMyself(), GetIsHostMyself(),
!String.Equals(Status.Call.Info.meeting_type,"NORMAL"), !String.Equals(Status.Call.Info.meeting_type,"NORMAL"),
false, false,
MeetingIsLockedFeedback.BoolValue MeetingIsLockedFeedback.BoolValue,
MeetingIsRecordingFeedback.BoolValue
); );
} }
// TODO [ ] Issue #868 // TODO [ ] Issue #868
@ -1984,6 +2142,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
false, false,
false, false,
false, false,
false,
false false
); );
} }
@ -2209,6 +2368,21 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="joinMap"></param> /// <param name="joinMap"></param>
public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap) public void LinkZoomRoomToApi(BasicTriList trilist, ZoomRoomJoinMap joinMap)
{ {
var recordingCodec = this as IHasMeetingRecordingWithPrompt;
if (recordingCodec != null)
{
trilist.SetSigFalseAction(joinMap.StartRecording.JoinNumber, () => recordingCodec.StartRecording());
trilist.SetSigFalseAction(joinMap.StopRecording.JoinNumber, () => recordingCodec.StopRecording());
recordingCodec.MeetingIsRecordingFeedback.LinkInputSig(trilist.BooleanInput[joinMap.StartRecording.JoinNumber]);
recordingCodec.MeetingIsRecordingFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.StopRecording.JoinNumber]);
trilist.SetSigFalseAction(joinMap.RecordingPromptAgree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(true));
trilist.SetSigFalseAction(joinMap.RecordingPromptDisagree.JoinNumber, () => recordingCodec.RecordingPromptAcknowledgement(false));
recordingCodec.RecordConsentPromptIsVisible.LinkInputSig(trilist.BooleanInput[joinMap.RecordConsentPromptIsVisible.JoinNumber]);
}
var layoutsCodec = this as IHasZoomRoomLayouts; var layoutsCodec = this as IHasZoomRoomLayouts;
if (layoutsCodec != null) if (layoutsCodec != null)
{ {
@ -2297,28 +2471,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]); layoutSizeCodec.SelfviewPipSizeFeedback.LinkInputSig(trilist.StringInput[joinMap.GetSetSelfviewPipSize.JoinNumber]);
} }
PasswordRequired += (device, args) =>
{
if (args.LoginAttemptCancelled)
{
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, false);
return;
}
if (!string.IsNullOrEmpty(args.Message))
{
trilist.SetString(joinMap.PasswordPromptMessage.JoinNumber, args.Message);
}
if (args.LoginAttemptFailed)
{
trilist.SetBool(joinMap.PasswordLoginFailed.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.ShowPasswordPrompt.JoinNumber, true);
};
MeetingInfoChanged += (device, args) => MeetingInfoChanged += (device, args) =>
{ {
trilist.SetString(joinMap.MeetingInfoId.JoinNumber, args.Info.Id); trilist.SetString(joinMap.MeetingInfoId.JoinNumber, args.Info.Id);
@ -2575,27 +2727,27 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
try try
{ {
Debug.Console(2, this, "OnDirectoryResultReturned"); Debug.Console(2, this, "OnDirectoryResultReturned. Result has {0} contacts", result.Contacts.Count);
var directoryResult = new CodecDirectory(); var directoryResult = result;
// If result is Root, create a copy and filter out contacts whose parent folder is not root // If result is Root, create a copy and filter out contacts whose parent folder is not root
if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) //if (!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue)
{ //{
Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display"); // Debug.Console(2, this, "Filtering DirectoryRoot to remove contacts for display");
directoryResult.ResultsFolderId = result.ResultsFolderId; // directoryResult.ResultsFolderId = result.ResultsFolderId;
directoryResult.AddFoldersToDirectory(result.Folders); // directoryResult.AddFoldersToDirectory(result.Folders);
directoryResult.AddContactsToDirectory( // directoryResult.AddContactsToDirectory(
result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList()); // result.Contacts.Where((c) => c.ParentFolderId == result.ResultsFolderId).ToList());
} //}
else //else
{ //{
directoryResult = result; // directoryResult = result;
} //}
Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0}", Debug.Console(2, this, "Updating directoryResult. IsOnRoot: {0} Contact Count: {1}",
!CurrentDirectoryResultIsNotDirectoryRoot.BoolValue); !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue, directoryResult.Contacts.Count);
// This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology // This will return the latest results to all UIs. Multiple indendent UI Directory browsing will require a different methodology
var handler = DirectoryResultReturned; var handler = DirectoryResultReturned;
@ -2607,6 +2759,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue
}); });
} }
CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate();
} }
catch (Exception e) catch (Exception e)
{ {
@ -2637,14 +2791,19 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
continue; continue;
} }
var camera = new ZoomRoomCamera(cam.id, cam.Name, this); var existingCam = Cameras.FirstOrDefault((c) => c.Key.Equals(cam.id));
Cameras.Add(camera); if (existingCam == null)
{
var camera = new ZoomRoomCamera(cam.id, cam.Name, this);
if (cam.Selected) Cameras.Add(camera);
{
SelectedCamera = camera; if (cam.Selected)
} {
SelectedCamera = camera;
}
}
} }
if (IsInCall) if (IsInCall)
@ -2677,6 +2836,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SendText(string.Format("zCommand Call HostChange Id: {0}", userId)); SendText(string.Format("zCommand Call HostChange Id: {0}", userId));
} }
public void AdmitParticipantFromWaitingRoom(int userId)
{
SendText(string.Format("zCommand Call Admit Participant Id: {0}", userId));
}
#endregion #endregion
#region IHasParticipantAudioMute Members #region IHasParticipantAudioMute Members
@ -3060,7 +3224,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
handler(this, new LayoutInfoChangedEventArgs() handler(this, new LayoutInfoChangedEventArgs()
{ {
AvailableLayouts = AvailableLayouts, AvailableLayouts = AvailableLayouts,
CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),LocalLayoutFeedback.StringValue, true), CurrentSelectedLayout = (zConfiguration.eLayoutStyle)Enum.Parse(typeof(zConfiguration.eLayoutStyle),string.IsNullOrEmpty(LocalLayoutFeedback.StringValue) ? "None" : LocalLayoutFeedback.StringValue , true),
LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue, LayoutViewIsOnFirstPage = LayoutViewIsOnFirstPageFeedback.BoolValue,
LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue, LayoutViewIsOnLastPage = LayoutViewIsOnLastPageFeedback.BoolValue,
CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue, CanSwapContentWithThumbnail = CanSwapContentWithThumbnailFeedback.BoolValue,
@ -3287,18 +3451,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#endregion #endregion
#region IHasMeetingRecording Members #region IHasMeetingRecordingWithPrompt Members
public BoolFeedback MeetingIsRecordingFeedback { get; private set; } public BoolFeedback MeetingIsRecordingFeedback { get; private set; }
bool _recordConsentPromptIsVisible;
public BoolFeedback RecordConsentPromptIsVisible { get; private set; }
public void RecordingPromptAcknowledgement(bool agree)
{
var command = string.Format("zCommand Agree Recording: {0}", agree ? "on" : "off");
//Debug.Console(2, this, "Sending agree: {0} {1}", agree, command);
SendText(command);
}
public void StartRecording() public void StartRecording()
{ {
SendText(string.Format("Command Call Record Enable: on")); SendText(string.Format("zCommand Call Record Enable: on"));
} }
public void StopRecording() public void StopRecording()
{ {
SendText(string.Format("Command Call Record Enable: off")); SendText(string.Format("zCommand Call Record Enable: off"));
} }
public void ToggleRecording() public void ToggleRecording()
@ -3437,7 +3612,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
public bool LoginMessageWasReceived { get; private set; } public bool LoginResponseWasReceived { get; private set; }
public bool FirstJsonResponseWasReceived { get; private set; }
public bool InitialQueryMessagesWereSent { get; private set; } public bool InitialQueryMessagesWereSent { get; private set; }
@ -3453,6 +3630,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public event EventHandler<EventArgs> InitialSyncCompleted; public event EventHandler<EventArgs> InitialSyncCompleted;
public event EventHandler FirstJsonResponseReceived;
public void StartSync() public void StartSync()
{ {
DequeueQueries(); DequeueQueries();
@ -3475,13 +3654,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncQueries.Enqueue(query); _syncQueries.Enqueue(query);
} }
public void LoginMessageReceived() public void LoginResponseReceived()
{ {
LoginMessageWasReceived = true; LoginResponseWasReceived = true;
Debug.Console(1, this, "Login Message Received."); Debug.Console(1, this, "Login Rsponse Received.");
CheckSyncStatus(); CheckSyncStatus();
} }
public void ReceivedFirstJsonResponse()
{
FirstJsonResponseWasReceived = true;
Debug.Console(1, this, "First JSON Response Received.");
var handler = FirstJsonResponseReceived;
if (handler != null)
{
handler(this, null);
}
CheckSyncStatus();
}
public void InitialQueryMessagesSent() public void InitialQueryMessagesSent()
{ {
InitialQueryMessagesWereSent = true; InitialQueryMessagesWereSent = true;
@ -3506,7 +3698,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public void CodecDisconnected() public void CodecDisconnected()
{ {
_syncQueries.Clear(); _syncQueries.Clear();
LoginMessageWasReceived = false; LoginResponseWasReceived = false;
FirstJsonResponseWasReceived = false;
InitialQueryMessagesWereSent = false; InitialQueryMessagesWereSent = false;
LastQueryResponseWasReceived = false; LastQueryResponseWasReceived = false;
CamerasHaveBeenSetUp = false; CamerasHaveBeenSetUp = false;
@ -3515,7 +3708,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void CheckSyncStatus() private void CheckSyncStatus()
{ {
if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && if (LoginResponseWasReceived && FirstJsonResponseWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived &&
CamerasHaveBeenSetUp) CamerasHaveBeenSetUp)
{ {
InitialSyncComplete = true; InitialSyncComplete = true;

View file

@ -7,6 +7,8 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Devices.Common.Cameras; using PepperDash.Essentials.Devices.Common.Cameras;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public enum eZoomRoomCameraState public enum eZoomRoomCameraState
@ -34,7 +36,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
protected ZoomRoom ParentCodec { get; private set; } protected ZoomRoom ParentCodec { get; private set; }
public int Id = 0; // ID of near end selected camara is always 0 [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public int? Id = 0; // ID of near end selected camara is always 0
private int ContinueTime = 10; // number of milliseconds between issuing continue commands private int ContinueTime = 10; // number of milliseconds between issuing continue commands

View file

@ -297,6 +297,76 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("StartRecording")]
public JoinDataComplete StartRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 241,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to start the Meeting Recording. FB high if meeting is currently recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("StopRecording")]
public JoinDataComplete StopRecording = new JoinDataComplete(
new JoinData
{
JoinNumber = 242,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to stop the Meeting Recording. FB high if meeting is currently NOT recording",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordConsentPromptIsVisible")]
public JoinDataComplete RecordConsentPromptIsVisible = new JoinDataComplete(
new JoinData
{
JoinNumber = 243,
JoinSpan = 1
},
new JoinMetadata
{
Description = "When high, indicates that the recording consent prompt is visible on the ZoomRoom UI",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptAgree")]
public JoinDataComplete RecordingPromptAgree = new JoinDataComplete(
new JoinData
{
JoinNumber = 244,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to agree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RecordingPromptDisagree")]
public JoinDataComplete RecordingPromptDisagree = new JoinDataComplete(
new JoinData
{
JoinNumber = 245,
JoinSpan = 1
},
new JoinMetadata
{
Description = "Pulse to disagree to consent for meeting recording",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
//[JoinName("ParticipantAudioMuteToggleStart")] //[JoinName("ParticipantAudioMuteToggleStart")]
//public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( //public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete(
// new JoinData // new JoinData

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
@ -11,21 +11,31 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public class ZoomRoomPropertiesConfig public class ZoomRoomPropertiesConfig
{ {
[JsonProperty("communicationMonitorProperties")]
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
[JsonProperty("disablePhonebookAutoDownload")]
public bool DisablePhonebookAutoDownload { get; set; } public bool DisablePhonebookAutoDownload { get; set; }
[JsonProperty("supportsCameraAutoMode")]
public bool SupportsCameraAutoMode { get; set; } public bool SupportsCameraAutoMode { get; set; }
[JsonProperty("supportsCameraOff")]
public bool SupportsCameraOff { get; set; } public bool SupportsCameraOff { get; set; }
//if true, the layouts will be set automatically when sharing starts/ends or a call is joined //if true, the layouts will be set automatically when sharing starts/ends or a call is joined
[JsonProperty("autoDefaultLayouts")]
public bool AutoDefaultLayouts { get; set; } public bool AutoDefaultLayouts { get; set; }
/* This layout will be selected when Sharing starts (either from Far end or locally)*/ /* This layout will be selected when Sharing starts (either from Far end or locally)*/
[JsonProperty("defaultSharingLayout")]
public string DefaultSharingLayout { get; set; } public string DefaultSharingLayout { get; set; }
//This layout will be selected when a call is connected and no content is being shared //This layout will be selected when a call is connected and no content is being shared
[JsonProperty("defaultCallLayout")]
public string DefaultCallLayout { get; set; } public string DefaultCallLayout { get; set; }
[JsonProperty("minutesBeforeMeetingStart")]
public int MinutesBeforeMeetingStart { get; set; } public int MinutesBeforeMeetingStart { get; set; }
} }
} }

View file

@ -1,3 +1,3 @@
<packages> <packages>
<package id="PepperDashCore" version="1.1.0" targetFramework="net35" allowedVersions="[1.0,2.0)"/> <package id="PepperDashCore" version="1.1.1" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
</packages> </packages>