Compare commits

..

7 Commits

Author SHA1 Message Date
aknous
b0a68f38f5 feat: adds bypassPackageCheck to github workflow 2025-03-18 13:18:07 -04:00
aknous
46887579e4 feat: simplifies IHasOsd ShowWebView method signature 2025-03-18 12:35:13 -04:00
Andrew Welker
b095d926d2 Merge branch 'development' into feature-2.0.0/IHasOsd 2025-03-12 13:29:00 -05:00
aknous
7cebf861cc build(force-patch): force rebuild 2025-03-12 14:14:11 -04:00
aknous
2e0b003118 build(force-patch): force build 2025-03-12 13:31:54 -04:00
aknous
bada7e3a25 feat: renames interface 2025-03-12 11:00:44 -04:00
aknous
67a7422cd0 feat: adds IHasOSD interface 2025-03-11 23:33:59 -04:00
113 changed files with 1654 additions and 15233 deletions

View File

@@ -9,14 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PepperDash.Essentials.Core", "src\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj", "{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Control", "Mobile Control", "{B24989D7-32B5-48D5-9AE1-5F3B17D25206}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDash.Essentials.MobileControl", "src\PepperDash.Essentials.MobileControl\PepperDash.Essentials.MobileControl.csproj", "{F6D362DE-2256-44B1-927A-8CE4705D839A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepperDash.Essentials.MobileControl.Messengers", "src\PepperDash.Essentials.MobileControl.Messengers\PepperDash.Essentials.MobileControl.Messengers.csproj", "{B438694F-8FF7-464A-9EC8-10427374471F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Essentials", "Essentials", "{AD98B742-8D85-481C-A69D-D8D8ABED39EA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug 4.7.2|Any CPU = Debug 4.7.2|Any CPU
@@ -42,29 +34,10 @@ Global
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B}.Release|Any CPU.Build.0 = Release|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug 4.7.2|Any CPU.ActiveCfg = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug 4.7.2|Any CPU.Build.0 = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6D362DE-2256-44B1-927A-8CE4705D839A}.Release|Any CPU.Build.0 = Release|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug 4.7.2|Any CPU.ActiveCfg = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug 4.7.2|Any CPU.Build.0 = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B438694F-8FF7-464A-9EC8-10427374471F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{53E204B7-97DD-441D-A96C-721DF014DF82} = {AD98B742-8D85-481C-A69D-D8D8ABED39EA}
{CB3B11BA-625C-4D35-B663-FDC5BE9A230E} = {AD98B742-8D85-481C-A69D-D8D8ABED39EA}
{3D192FED-8FFC-4CB5-B5F7-BA307ABA254B} = {AD98B742-8D85-481C-A69D-D8D8ABED39EA}
{F6D362DE-2256-44B1-927A-8CE4705D839A} = {B24989D7-32B5-48D5-9AE1-5F3B17D25206}
{B438694F-8FF7-464A-9EC8-10427374471F} = {B24989D7-32B5-48D5-9AE1-5F3B17D25206}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6907A4BF-7201-47CF-AAB1-3597F3B8E1C3}
EndGlobalSection

View File

@@ -60,4 +60,4 @@ For detailed documentation, see the [Wiki](https://github.com/PepperDash/Essenti
## How-To (Getting Started)
See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started)
See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started)

View File

@@ -0,0 +1,85 @@
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
/// <summary>
/// Wrapper class for CEN-IO-COM-Xxx expander module
/// </summary>
[Description("Wrapper class for the CEN-IO-COM-102 & CEN-IO-COM-202 expander module")]
public class CenIoComController : CrestronGenericBaseDevice, IComPorts
{
private readonly CenIoCom _cenIoCom;
public CenIoComController(string key, string name, CenIoCom cenIo)
:base(key, name, cenIo)
{
_cenIoCom = cenIo;
}
#region Implementation of IComPorts
public CrestronCollection<ComPort> ComPorts
{
get { return _cenIoCom.ComPorts; }
}
public int NumberOfComPorts
{
get { return _cenIoCom.NumberOfComPorts; }
}
#endregion
}
public class CenIoCom102ControllerFactory : EssentialsDeviceFactory<CenIoComController>
{
private const string CenIoCom102Type = "ceniocom102";
private const string CenIoCom202Type = "ceniocom202";
public CenIoCom102ControllerFactory()
{
TypeNames = new List<string> { CenIoCom102Type, CenIoCom202Type };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new CEN-IO-COM-Xxx Device");
var control = CommFactory.GetControlPropertiesConfig(dc);
if (control == null)
{
Debug.Console(1, "Factory failed to create a new CEN-IO-COM-Xxx Device, control properties not found");
return null;
}
var ipid = control.IpIdInt;
if (ipid < 2)
{
Debug.Console(1, "Factory failed to create a new CEN-IO-COM-Xxx Device, invalid IP-ID found");
return null;
}
switch (dc.Type)
{
case CenIoCom102Type:
{
return new CenIoComController(dc.Key, dc.Name, new CenIoCom102(ipid, Global.ControlSystem));
}
case CenIoCom202Type:
{
return new CenIoComController(dc.Key, dc.Name, new CenIoCom202(ipid, Global.ControlSystem));
}
default:
{
Debug.Console(1, "Factory failed to create a new CEN-IO-COM-Xxx Device, invalid type '{0}'", dc.Type);
return null;
}
}
}
}
}

View File

@@ -0,0 +1,185 @@
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_DM.Chassis
{
public class HdPsXxxAnalogAuxMixerController : IKeyed,
IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback
{
public string Key { get; private set; }
private readonly HdPsXxxAnalogAuxMixer _mixer;
public HdPsXxxAnalogAuxMixerController(string parent, uint mixer, HdPsXxx chassis)
{
Key = string.Format("{0}-analogMixer{1}", parent, mixer);
_mixer = chassis.AnalogAuxiliaryMixer[mixer];
_mixer.AuxMixerPropertyChange += OnAuxMixerPropertyChange;
_mixer.AuxiliaryMuteControl.MuteAndVolumeControlPropertyChange += OnMuteAndVolumeControlPropertyChange;
VolumeLevelFeedback = new IntFeedback(() => VolumeLevel);
MuteFeedback = new BoolFeedback(() => IsMuted);
}
#region Volume
private void OnAuxMixerPropertyChange(object sender, GenericEventArgs args)
{
Debug.Console(2, this, "OnAuxMixerPropertyChange: {0} > Index-{1}, EventId-{2}", sender.ToString(), args.Index, args.EventId);
switch (args.EventId)
{
case MuteAndVolumeContorlEventIds.VolumeFeedbackEventId:
{
VolumeLevel = _mixer.VolumeFeedback.ShortValue;
break;
}
case MuteAndVolumeContorlEventIds.MuteOnEventId:
case MuteAndVolumeContorlEventIds.MuteOffEventId:
{
IsMuted = _mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue;
break;
}
default:
{
Debug.Console(1, this, "OnAuxMixerPropertyChange: {0} > Index-{1}, EventId-{2} - unhandled eventId", sender.ToString(), args.Index, args.EventId);
break;
}
}
}
private const ushort CrestronLevelMin = 0;
private const ushort CrestronLevelMax = 65535;
private const int DeviceLevelMin = -800;
private const int DeviceLevelMax = 200;
private const int RampTime = 5000;
private int _volumeLevel;
public int VolumeLevel
{
get { return _volumeLevel; }
private set
{
var level = value;
_volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin);
Debug.Console(1, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel);
VolumeLevelFeedback.FireUpdate();
}
}
public IntFeedback VolumeLevelFeedback { get; private set; }
public void SetVolume(ushort level)
{
var levelScaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin);
Debug.Console(1, this, "SetVolume: level-'{0}', levelScaled-'{1}'", level, levelScaled);
_mixer.Volume.ShortValue = (short)levelScaled;
}
public void VolumeUp(bool pressRelease)
{
if (pressRelease)
{
_mixer.Volume.CreateSignedRamp(DeviceLevelMax, RampTime);
}
else
{
_mixer.Volume.StopRamp();
}
}
public void VolumeDown(bool pressRelease)
{
if (pressRelease)
{
_mixer.Volume.CreateSignedRamp(DeviceLevelMin, RampTime);
}
else
{
_mixer.Volume.StopRamp();
}
}
#endregion
#region Mute
private void OnMuteAndVolumeControlPropertyChange(MuteControl device, GenericEventArgs args)
{
Debug.Console(2, this, "OnMuteAndVolumeControlPropertyChange: {0} > Index-{1}, EventId-{2}", device.ToString(), args.Index, args.EventId);
switch (args.EventId)
{
case MuteAndVolumeContorlEventIds.VolumeFeedbackEventId:
{
VolumeLevel = _mixer.VolumeFeedback.ShortValue;
break;
}
case MuteAndVolumeContorlEventIds.MuteOnEventId:
case MuteAndVolumeContorlEventIds.MuteOffEventId:
{
IsMuted = _mixer.AuxiliaryMuteControl.MuteOnFeedback.BoolValue;
break;
}
default:
{
Debug.Console(1, this, "OnMuteAndVolumeControlPropertyChange: {0} > Index-{1}, EventId-{2} - unhandled eventId", device.ToString(), args.Index, args.EventId);
break;
}
}
}
private bool _isMuted;
public bool IsMuted
{
get { return _isMuted; }
set
{
_isMuted = value;
Debug.Console(1, this, "IsMuted: _isMuted-'{0}'", _isMuted);
MuteFeedback.FireUpdate();
}
}
public BoolFeedback MuteFeedback { get; private set; }
public void MuteOn()
{
_mixer.AuxiliaryMuteControl.MuteOn();
}
public void MuteOff()
{
_mixer.AuxiliaryMuteControl.MuteOff();
}
public void MuteToggle()
{
if (IsMuted)
MuteOff();
else
MuteOn();
}
#endregion
}
}

View File

@@ -0,0 +1,167 @@
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DM;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_DM.Chassis
{
public class HdPsXxxOutputAudioController : IKeyed,
IHasVolumeControlWithFeedback, IHasMuteControlWithFeedback
{
public string Key { get; private set; }
private readonly HdPsXxxHdmiDmLiteOutputMixer _mixer; // volume/volumeFeedback
private readonly HdPsXxxOutputPort _port; // mute/muteFeedback
public HdPsXxxOutputAudioController(string parent, uint output, HdPsXxx chassis)
{
Key = string.Format("{0}-audioOut{1}", parent, output);
_port = chassis.HdmiDmLiteOutputs[output].OutputPort;
_mixer = chassis.HdmiDmLiteOutputs[output].Mixer;
chassis.DMOutputChange += ChassisOnDmOutputChange;
VolumeLevelFeedback = new IntFeedback(() => VolumeLevel);
MuteFeedback = new BoolFeedback(() => IsMuted);
}
private void ChassisOnDmOutputChange(Switch device, DMOutputEventArgs args)
{
switch (args.EventId)
{
case (DMOutputEventIds.VolumeEventId):
{
Debug.Console(2, this, "HdPsXxxOutputAudioController: {0} > Index-{1}, Number-{3}, EventId-{2} - AudioMute/UnmuteEventId",
device.ToString(), args.Index, args.EventId, args.Number);
VolumeLevel = _mixer.VolumeFeedback.ShortValue;
break;
}
case DMOutputEventIds.MuteOnEventId:
case DMOutputEventIds.MuteOffEventId:
{
Debug.Console(2, this, "HdPsXxxOutputAudioController: {0} > Index-{1}, Number-{3}, EventId-{2} - MuteOnEventId/MuteOffEventId",
device.ToString(), args.Index, args.EventId, args.Number);
IsMuted = _port.MuteOnFeedback.BoolValue;
break;
}
default:
{
Debug.Console(1, this, "HdPsXxxOutputAudioController: {0} > Index-{1}, Number-{3}, EventId-{2} - unhandled eventId",
device.ToString(), args.Index, args.EventId, args.Number);
break;
}
}
}
#region Volume
private const ushort CrestronLevelMin = 0;
private const ushort CrestronLevelMax = 65535;
private const int DeviceLevelMin = -800;
private const int DeviceLevelMax = 200;
private const int RampTime = 5000;
private int _volumeLevel;
public int VolumeLevel
{
get { return _volumeLevel; }
private set
{
var level = value;
_volumeLevel = CrestronEnvironment.ScaleWithLimits(level, DeviceLevelMax, DeviceLevelMin, CrestronLevelMax, CrestronLevelMin);
Debug.Console(2, this, "VolumeFeedback: level-'{0}', scaled-'{1}'", level, _volumeLevel);
VolumeLevelFeedback.FireUpdate();
}
}
public IntFeedback VolumeLevelFeedback { get; private set; }
public void SetVolume(ushort level)
{
var levelScaled = CrestronEnvironment.ScaleWithLimits(level, CrestronLevelMax, CrestronLevelMin, DeviceLevelMax, DeviceLevelMin);
Debug.Console(1, this, "SetVolume: level-'{0}', levelScaled-'{1}'", level, levelScaled);
_mixer.Volume.ShortValue = (short)levelScaled;
}
public void VolumeUp(bool pressRelease)
{
if (pressRelease)
{
_mixer.Volume.CreateSignedRamp(DeviceLevelMax, RampTime);
}
else
{
_mixer.Volume.StopRamp();
}
}
public void VolumeDown(bool pressRelease)
{
if (pressRelease)
{
_mixer.Volume.CreateSignedRamp(DeviceLevelMin, RampTime);
}
else
{
_mixer.Volume.StopRamp();
}
}
#endregion
#region Mute
private bool _isMuted;
public bool IsMuted
{
get { return _isMuted; }
set
{
_isMuted = value;
Debug.Console(1, this, "IsMuted: _isMuted-'{0}'", _isMuted);
MuteFeedback.FireUpdate();
}
}
public BoolFeedback MuteFeedback { get; private set; }
public void MuteOn()
{
_port.MuteOn();
}
public void MuteOff()
{
_port.MuteOff();
}
public void MuteToggle()
{
if (IsMuted)
MuteOff();
else
MuteOn();
}
#endregion
}
}

View File

@@ -2,10 +2,10 @@
<PropertyGroup>
<Version>2.0.0-local</Version>
<InformationalVersion>$(Version)</InformationalVersion>
<Authors>PepperDash Technology</Authors>
<Company>PepperDash Technology</Company>
<Authors>PepperDash Technologies</Authors>
<Company>PepperDash Technologies</Company>
<Product>PepperDash Essentials</Product>
<Copyright>Copyright © 2025</Copyright>
<Copyright>Copyright © 2023</Copyright>
<RepositoryUrl>https://github.com/PepperDash/Essentials</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>Crestron; 4series</PackageTags>

View File

@@ -7,19 +7,17 @@ namespace PepperDash.Essentials.Core
[Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")]
public class GenericHttpClient : Device, IBasicCommunication
{
private readonly HttpClient Client;
public HttpClient Client;
public event EventHandler<GenericHttpClientEventArgs> ResponseRecived;
public GenericHttpClient(string key, string name, string hostname)
: base(key, name)
{
Client = new HttpClient
{
HostName = hostname
};
}
Client = new HttpClient();
Client.HostName = hostname;
}
/// <summary>
///
@@ -56,8 +54,9 @@ namespace PepperDash.Essentials.Core
if (responseReceived.ContentString.Length > 0)
{
ResponseRecived?.Invoke(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error));
}
if (ResponseRecived != null)
ResponseRecived(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error));
}
}
}

View File

@@ -1,8 +0,0 @@
using PepperDash.Core;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface IDisplay: IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName
{
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface IHasWebView
{
void ShowWebView(string url, string mode, string title, string target);
void HideWebView();
}
}

View File

@@ -1,4 +1,12 @@
using PepperDash.Core;
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;
namespace PepperDash.Essentials.Core
@@ -8,6 +16,22 @@ namespace PepperDash.Essentials.Core
BoolFeedback IsOnline { get; }
}
///// <summary>
///// ** WANT THIS AND ALL ITS FRIENDS TO GO AWAY **
///// Defines a class that has a list of CueAction objects, typically
///// for linking functions to user interfaces or API calls
///// </summary>
//public interface IHasCueActionList
//{
// List<CueActionPair> CueActionList { get; }
//}
//public interface IHasComPortsHardware
//{
// IComPorts ComPortsDevice { get; }
//}
/// <summary>
/// Describes a device that can have a video sync providing device attached to it
/// </summary>

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharpPro;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Devices
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public class Laptop : EssentialsDevice, IHasFeedback, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
{
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
public string IconName { get; set; }
public BoolFeedback HasPowerOnFeedback { get; private set; }
public RoutingOutputPort AnyVideoOut { get; private set; }
#region IRoutingOutputs Members
/// <summary>
/// Options: hdmi
/// </summary>
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
#endregion
public Laptop(string key, string name)
: base(key, name)
{
IconName = "Laptop";
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.None, 0, this));
}
#region IHasFeedback Members
/// <summary>
/// Passes through the VideoStatuses list
/// </summary>
public FeedbackCollection<Feedback> Feedbacks
{
get
{
var newList = new FeedbackCollection<Feedback>();
newList.AddRange(this.GetVideoStatuses().ToList());
return newList;
}
}
#endregion
#region IUsageTracking Members
public UsageTracking UsageTracker { get; set; }
#endregion
}
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public class LaptopFactory : EssentialsDeviceFactory<Laptop>
{
public LaptopFactory()
{
TypeNames = new List<string>() { "deprecated" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device");
return new Core.Devices.Laptop(dc.Key, dc.Name);
}
}
}

View File

@@ -0,0 +1,229 @@
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.Config;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
namespace PepperDash.Essentials.Core
{
[Obsolete("Please use PepperDash.Essentials.Device.Common, this will be removed in 2.1")]
public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced
{
public IrOutputPortController IrPort { get; private set; }
public ushort IrPulseTime { get; set; }
protected Func<bool> PowerIsOnFeedbackFunc
{
get { return () => _PowerIsOn; }
}
protected override Func<bool> IsCoolingDownFeedbackFunc
{
get { return () => _IsCoolingDown; }
}
protected override Func<bool> IsWarmingUpFeedbackFunc
{
get { return () => _IsWarmingUp; }
}
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
public BasicIrDisplay(string key, string name, IROutputPort port, string irDriverFilepath)
: base(key, name)
{
IrPort = new IrOutputPortController(key + "-ir", port, irDriverFilepath);
DeviceManager.AddDevice(IrPort);
IsWarmingUpFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Verbose, this, "Warming up={0}", _IsWarmingUp);
IsCoolingDownFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Verbose, this, "Cooling down={0}", _IsCoolingDown);
InputPorts.AddRange(new RoutingPortCollection<RoutingInputPort>
{
new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi1), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi2), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi3), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi4), this, false),
new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Component1), this, false),
new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Video1), this, false),
new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Antenna), this, false),
});
}
public void Hdmi1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_1, IrPulseTime);
}
public void Hdmi2()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_2, IrPulseTime);
}
public void Hdmi3()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_3, IrPulseTime);
}
public void Hdmi4()
{
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_4, IrPulseTime);
}
public void Component1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_COMPONENT_1, IrPulseTime);
}
public void Video1()
{
IrPort.Pulse(IROutputStandardCommands.IROut_VIDEO_1, IrPulseTime);
}
public void Antenna()
{
IrPort.Pulse(IROutputStandardCommands.IROut_ANTENNA, IrPulseTime);
}
#region IPower Members
public override void PowerOn()
{
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
_PowerIsOn = true;
}
public override void PowerOff()
{
_PowerIsOn = false;
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
}
public override void PowerToggle()
{
_PowerIsOn = false;
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
}
#endregion
#region IBasicVolumeControls Members
public void VolumeUp(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_PLUS, pressRelease);
}
public void VolumeDown(bool pressRelease)
{
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_MINUS, pressRelease);
}
public void MuteToggle()
{
IrPort.Pulse(IROutputStandardCommands.IROut_MUTE, 200);
}
#endregion
void StartWarmingTimer()
{
_IsWarmingUp = true;
IsWarmingUpFeedback.FireUpdate();
new CTimer(o => {
_IsWarmingUp = false;
IsWarmingUpFeedback.FireUpdate();
}, 10000);
}
void StartCoolingTimer()
{
_IsCoolingDown = true;
IsCoolingDownFeedback.FireUpdate();
new CTimer(o =>
{
_IsCoolingDown = false;
IsCoolingDownFeedback.FireUpdate();
}, 7000);
}
#region IRoutingSink Members
/// <summary>
/// Typically called by the discovery routing algorithm.
/// </summary>
/// <param name="inputSelector">A delegate containing the input selector method to call</param>
public override void ExecuteSwitch(object inputSelector)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString());
Action finishSwitch = () =>
{
var action = inputSelector as Action;
if (action != null)
action();
};
if (!_PowerIsOn)
{
PowerOn();
EventHandler<FeedbackEventArgs> oneTimer = null;
oneTimer = (o, a) =>
{
if (IsWarmingUpFeedback.BoolValue) return; // Only catch done warming
IsWarmingUpFeedback.OutputChange -= oneTimer;
finishSwitch();
};
IsWarmingUpFeedback.OutputChange += oneTimer;
}
else // Do it!
finishSwitch();
}
#endregion
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
}
}
[Obsolete("Please use PepperDash.Essentials.Device.Common, this will be removed in 2.1")]
public class BasicIrDisplayFactory : EssentialsDeviceFactory<BasicIrDisplay>
{
public BasicIrDisplayFactory()
{
TypeNames = new List<string>() { "basicirdisplay" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device");
var ir = IRPortHelper.GetIrPort(dc.Properties);
if (ir != null)
{
var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName);
display.IrPulseTime = 200; // Set default pulse time for IR commands.
return display;
}
return null;
}
}
}

View File

@@ -0,0 +1,320 @@
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.Core
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class DisplayBase : EssentialsDevice, IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking
{
public event SourceInfoChangeHandler CurrentSourceChange;
public event InputChangedEventHandler InputChanged;
public string CurrentSourceInfoKey { get; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public BoolFeedback IsCoolingDownFeedback { get; protected set; }
public BoolFeedback IsWarmingUpFeedback { get; private set; }
public UsageTracking UsageTracker { get; set; }
public uint WarmupTime { get; set; }
public uint CooldownTime { get; set; }
/// <summary>
/// Bool Func that will provide a value for the PowerIsOn Output. Must be implemented
/// by concrete sub-classes
/// </summary>
abstract protected Func<bool> IsCoolingDownFeedbackFunc { get; }
abstract protected Func<bool> IsWarmingUpFeedbackFunc { get; }
protected CTimer WarmupTimer;
protected CTimer CooldownTimer;
#region IRoutingInputs Members
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
#endregion
protected DisplayBase(string key, string name)
: base(key, name)
{
IsCoolingDownFeedback = new BoolFeedback("IsCoolingDown", IsCoolingDownFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback("IsWarmingUp", IsWarmingUpFeedbackFunc);
InputPorts = new RoutingPortCollection<RoutingInputPort>();
}
public abstract void PowerOn();
public abstract void PowerOff();
public abstract void PowerToggle();
public virtual FeedbackCollection<Feedback> Feedbacks
{
get
{
return new FeedbackCollection<Feedback>
{
IsCoolingDownFeedback,
IsWarmingUpFeedback
};
}
}
public RoutingInputPort CurrentInputPort => throw new NotImplementedException();
public abstract void ExecuteSwitch(object selector);
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge)
{
var joinMap = new DisplayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<DisplayControllerJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.LogMessage(LogEventLevel.Information,this,"Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
LinkDisplayToApi(displayDevice, trilist, joinMap);
}
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, DisplayControllerJoinMap joinMap)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.LogMessage(LogEventLevel.Information, "Linking to Display: {0}", displayDevice.Name);
trilist.StringInput[joinMap.Name.JoinNumber].StringValue = displayDevice.Name;
var commMonitor = displayDevice as ICommunicationMonitor;
if (commMonitor != null)
{
commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
}
var inputNumber = 0;
var inputKeys = new List<string>();
var inputNumberFeedback = new IntFeedback(() => inputNumber);
// Two way feedbacks
var twoWayDisplay = displayDevice as TwoWayDisplayBase;
if (twoWayDisplay != null)
{
trilist.SetBool(joinMap.IsTwoWayDisplay.JoinNumber, true);
twoWayDisplay.CurrentInputFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Information, "CurrentInputFeedback_OutputChange {0}", a.StringValue);
inputNumberFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputSelect.JoinNumber]);
}
// Power Off
trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () =>
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOff();
});
var twoWayDisplayDevice = displayDevice as TwoWayDisplayBase;
if (twoWayDisplayDevice != null)
{
twoWayDisplayDevice.PowerIsOnFeedback.OutputChange += (o, a) =>
{
if (!a.BoolValue)
{
inputNumber = 102;
inputNumberFeedback.FireUpdate();
}
else
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
}
};
twoWayDisplayDevice.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]);
twoWayDisplayDevice.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]);
}
// PowerOn
trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () =>
{
inputNumber = 0;
inputNumberFeedback.FireUpdate();
displayDevice.PowerOn();
});
for (int i = 0; i < displayDevice.InputPorts.Count; i++)
{
if (i < joinMap.InputNamesOffset.JoinSpan)
{
inputKeys.Add(displayDevice.InputPorts[i].Key);
var tempKey = inputKeys.ElementAt(i);
trilist.SetSigTrueAction((ushort)(joinMap.InputSelectOffset.JoinNumber + i),
() => displayDevice.ExecuteSwitch(displayDevice.InputPorts[tempKey].Selector));
Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Digital Join {0} to Input: {1}",
joinMap.InputSelectOffset.JoinNumber + i, displayDevice.InputPorts[tempKey].Key.ToString());
trilist.StringInput[(ushort)(joinMap.InputNamesOffset.JoinNumber + i)].StringValue = displayDevice.InputPorts[i].Key.ToString();
}
else
Debug.LogMessage(LogEventLevel.Information, displayDevice, "Device has {0} inputs. The Join Map allows up to {1} inputs. Discarding inputs {2} - {3} from bridge.",
displayDevice.InputPorts.Count, joinMap.InputNamesOffset.JoinSpan, i + 1, displayDevice.InputPorts.Count);
}
Debug.LogMessage(LogEventLevel.Verbose, displayDevice, "Setting Input Select Action on Analog Join {0}", joinMap.InputSelect);
trilist.SetUShortSigAction(joinMap.InputSelect.JoinNumber, (a) =>
{
if (a == 0)
{
displayDevice.PowerOff();
inputNumber = 0;
}
else if (a > 0 && a < displayDevice.InputPorts.Count && a != inputNumber)
{
displayDevice.ExecuteSwitch(displayDevice.InputPorts.ElementAt(a - 1).Selector);
inputNumber = a;
}
else if (a == 102)
{
displayDevice.PowerToggle();
}
if (twoWayDisplay != null)
inputNumberFeedback.FireUpdate();
});
var volumeDisplay = displayDevice as IBasicVolumeControls;
if (volumeDisplay == null) return;
trilist.SetBoolSigAction(joinMap.VolumeUp.JoinNumber, volumeDisplay.VolumeUp);
trilist.SetBoolSigAction(joinMap.VolumeDown.JoinNumber, volumeDisplay.VolumeDown);
trilist.SetSigTrueAction(joinMap.VolumeMute.JoinNumber, volumeDisplay.MuteToggle);
var volumeDisplayWithFeedback = volumeDisplay as IBasicVolumeWithFeedback;
if (volumeDisplayWithFeedback == null) return;
trilist.SetSigTrueAction(joinMap.VolumeMuteOn.JoinNumber, volumeDisplayWithFeedback.MuteOn);
trilist.SetSigTrueAction(joinMap.VolumeMuteOff.JoinNumber, volumeDisplayWithFeedback.MuteOff);
trilist.SetUShortSigAction(joinMap.VolumeLevel.JoinNumber, volumeDisplayWithFeedback.SetVolume);
volumeDisplayWithFeedback.VolumeLevelFeedback.LinkInputSig(trilist.UShortInput[joinMap.VolumeLevel.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMute.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VolumeMuteOn.JoinNumber]);
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
}
}
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback
{
public StringFeedback CurrentInputFeedback { get; private set; }
abstract protected Func<string> CurrentInputFeedbackFunc { get; }
public BoolFeedback PowerIsOnFeedback { get; protected set; }
abstract protected Func<bool> PowerIsOnFeedbackFunc { get; }
// public static MockDisplay DefaultDisplay
// {
// get
// {
// if (_DefaultDisplay == null)
// _DefaultDisplay = new MockDisplay("default", "Default Display");
// return _DefaultDisplay;
// }
//}
//static MockDisplay _DefaultDisplay;
public TwoWayDisplayBase(string key, string name)
: base(key, name)
{
CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc);
WarmupTime = 7000;
CooldownTime = 15000;
PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc);
Feedbacks.Add(CurrentInputFeedback);
Feedbacks.Add(PowerIsOnFeedback);
PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange;
}
void PowerIsOnFeedback_OutputChange(object sender, EventArgs e)
{
if (UsageTracker != null)
{
if (PowerIsOnFeedback.BoolValue)
UsageTracker.StartDeviceUsage();
else
UsageTracker.EndDeviceUsage();
}
}
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
protected void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
}
}

View File

@@ -9,7 +9,6 @@ using Crestron.SimplSharpPro.Fusion;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Serilog.Events;
using System;
using System.Collections.Generic;
@@ -20,7 +19,7 @@ namespace PepperDash.Essentials.Core.Fusion
{
public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider
{
private readonly EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap;
protected EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap;
private const string RemoteOccupancyXml = "<Occupancy><Type>Local</Type><State>{0}</State></Occupancy>";
private readonly bool _guidFileExists;
@@ -30,15 +29,15 @@ namespace PepperDash.Essentials.Core.Fusion
protected StringSigData CurrentRoomSourceNameSig;
private readonly FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
public FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
protected FusionOccupancySensorAsset FusionOccSensor;
private readonly FusionRemoteOccupancySensor FusionRemoteOccSensor;
protected FusionRemoteOccupancySensor FusionRemoteOccSensor;
protected FusionRoom FusionRoom;
protected Dictionary<int, FusionAsset> FusionStaticAssets;
private readonly long PushNotificationTimeout = 5000;
private readonly IEssentialsRoom Room;
private readonly long SchedulePollInterval = 300000;
public long PushNotificationTimeout = 5000;
protected IEssentialsRoom Room;
public long SchedulePollInterval = 300000;
private Event _currentMeeting;
private RoomSchedule _currentSchedule;
@@ -86,7 +85,7 @@ namespace PepperDash.Essentials.Core.Fusion
#region Default Display Source Sigs
private readonly BooleanSigData[] _source = new BooleanSigData[10];
private BooleanSigData[] _source = new BooleanSigData[10];
#endregion
@@ -152,8 +151,9 @@ namespace PepperDash.Essentials.Core.Fusion
ReadGuidFile(guidFilePath);
}
var occupancyRoom = Room as IRoomOccupancy;
if (Room is IRoomOccupancy occupancyRoom)
if (occupancyRoom != null)
{
if (occupancyRoom.RoomOccupancy != null)
{
@@ -367,7 +367,8 @@ namespace PepperDash.Essentials.Core.Fusion
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName,
eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
if (Room is IHasCurrentSourceInfoChange hasCurrentSourceInfoChange)
var hasCurrentSourceInfoChange = Room as IHasCurrentSourceInfoChange;
if (hasCurrentSourceInfoChange != null)
{
hasCurrentSourceInfoChange.CurrentSourceChange += Room_CurrentSourceInfoChange;
}
@@ -376,7 +377,8 @@ namespace PepperDash.Essentials.Core.Fusion
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction(Room.PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() =>
{
if (Room is IRunRouteAction runRouteAction)
var runRouteAction = Room as IRunRouteAction;
if (runRouteAction != null)
{
runRouteAction.RunRouteAction("roomOff", Room.SourceListKey);
}
@@ -658,7 +660,7 @@ namespace PepperDash.Essentials.Core.Fusion
var extendTime = _currentMeeting.dtEnd - DateTime.Now;
var extendMinutesRaw = extendTime.TotalMinutes;
extendMinutes += (int) Math.Round(extendMinutesRaw);
extendMinutes = extendMinutes + (int) Math.Round(extendMinutesRaw);
}
@@ -899,7 +901,12 @@ namespace PepperDash.Essentials.Core.Fusion
}
}
}
RoomInfoChange?.Invoke(this, new EventArgs());
var handler = RoomInfoChange;
if (handler != null)
{
handler(this, new EventArgs());
}
CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation);
}
@@ -1007,7 +1014,12 @@ namespace PepperDash.Essentials.Core.Fusion
}
// Fire Schedule Change Event
ScheduleChange?.Invoke(this, new ScheduleChangeEventArgs { Schedule = _currentSchedule });
var handler = ScheduleChange;
if (handler != null)
{
handler(this, new ScheduleChangeEventArgs {Schedule = _currentSchedule});
}
}
}
}
@@ -1079,7 +1091,7 @@ namespace PepperDash.Essentials.Core.Fusion
}
}
var laptops = dict.Where(d => d.Value.SourceDevice is IRoutingSource);
var laptops = dict.Where(d => d.Value.SourceDevice is Devices.Laptop);
i = 1;
foreach (var kvp in laptops)
{
@@ -1111,7 +1123,9 @@ namespace PepperDash.Essentials.Core.Fusion
/// <param name="e"></param>
protected void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e)
{
if (!(sender is UsageTracking deviceTracker))
var deviceTracker = sender as UsageTracking;
if (deviceTracker == null)
{
return;
}
@@ -1154,7 +1168,8 @@ namespace PepperDash.Essentials.Core.Fusion
// And respond to selection in Fusion
sigD.OutputSig.SetSigFalseAction(() =>
{
if (Room is IRunRouteAction runRouteAction)
var runRouteAction = Room as IRunRouteAction;
if (runRouteAction != null)
{
runRouteAction.RunRouteAction(routeKey, Room.SourceListKey);
}
@@ -1198,11 +1213,12 @@ namespace PepperDash.Essentials.Core.Fusion
//uint attrNum = Convert.ToUInt32(keyNum);
// Check for UI devices
if (dev is IHasBasicTriListWithSmartObject uiDev)
var uiDev = dev as IHasBasicTriListWithSmartObject;
if (uiDev != null)
{
if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
{
attrNum += touchpanelNum;
attrNum = attrNum + touchpanelNum;
if (attrNum > JoinMap.XpanelOnlineStart.JoinSpan)
{
@@ -1215,7 +1231,7 @@ namespace PepperDash.Essentials.Core.Fusion
}
else
{
attrNum += xpanelNum;
attrNum = attrNum + xpanelNum;
if (attrNum > JoinMap.TouchpanelOnlineStart.JoinSpan)
{
@@ -1229,9 +1245,9 @@ namespace PepperDash.Essentials.Core.Fusion
}
//else
if (dev is IDisplay)
if (dev is DisplayBase)
{
attrNum += displayNum;
attrNum = attrNum + displayNum;
if (attrNum > JoinMap.DisplayOnlineStart.JoinSpan)
{
continue;
@@ -1273,21 +1289,23 @@ namespace PepperDash.Essentials.Core.Fusion
{
//Setup Display Usage Monitoring
var displays = DeviceManager.AllDevices.Where(d => d is IDisplay);
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
// Consider updating this in multiple display systems
foreach (var display in displays.Cast<IDisplay>())
foreach (var display in displays.Cast<DisplayBase>())
{
display.UsageTracker = new UsageTracking(display as Device) {UsageIsTracked = true};
display.UsageTracker = new UsageTracking(display) {UsageIsTracked = true};
display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
}
if (!(Room is IHasDefaultDisplay hasDefaultDisplay))
var hasDefaultDisplay = Room as IHasDefaultDisplay;
if (hasDefaultDisplay == null)
{
return;
}
if (!(hasDefaultDisplay.DefaultDisplay is IDisplay defaultDisplay))
var defaultDisplay = hasDefaultDisplay.DefaultDisplay as DisplayBase;
if (defaultDisplay == null)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Cannot link null display to Fusion because default display is null");
return;
@@ -1339,7 +1357,8 @@ namespace PepperDash.Essentials.Core.Fusion
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
if (defaultDisplay is IHasPowerControlWithFeedback defaultTwoWayDisplay)
var defaultTwoWayDisplay = defaultDisplay as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
if (defaultDisplay is IDisplayUsage)
@@ -1351,8 +1370,8 @@ namespace PepperDash.Essentials.Core.Fusion
}
// Use extension methods
dispAsset.TrySetMakeModel(defaultDisplay as Device);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay as Device);
dispAsset.TrySetMakeModel(defaultDisplay);
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
}
catch (Exception e)
{
@@ -1367,12 +1386,13 @@ namespace PepperDash.Essentials.Core.Fusion
/// <param name="display"></param>
/// <param name="displayIndex"></param>
/// a
protected virtual void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, IDisplay display)
protected virtual void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, DisplayBase display)
{
var displayName = string.Format("Display {0} - ", displayIndex);
if (!(Room is IHasDefaultDisplay hasDefaultDisplay) || display != hasDefaultDisplay.DefaultDisplay)
var hasDefaultDisplay = Room as IHasDefaultDisplay;
if (hasDefaultDisplay == null || display != hasDefaultDisplay.DefaultDisplay)
{
return;
}
@@ -1381,7 +1401,8 @@ namespace PepperDash.Essentials.Core.Fusion
eSigIoMask.InputOutputSig);
defaultDisplayVolume.OutputSig.UserObject = new Action<ushort>(b =>
{
if (!(display is IBasicVolumeWithFeedback basicVolumeWithFeedback))
var basicVolumeWithFeedback = display as IBasicVolumeWithFeedback;
if (basicVolumeWithFeedback == null)
{
return;
}
@@ -1414,7 +1435,8 @@ namespace PepperDash.Essentials.Core.Fusion
});
if (display is IHasPowerControlWithFeedback defaultTwoWayDisplay)
var defaultTwoWayDisplay = display as IHasPowerControlWithFeedback;
if (defaultTwoWayDisplay != null)
{
defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
defaultTwoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(defaultDisplayPowerOff.InputSig);
@@ -1427,7 +1449,8 @@ namespace PepperDash.Essentials.Core.Fusion
{
if (!b)
{
if (Room is IRunRouteAction runRouteAction)
var runRouteAction = Room as IRunRouteAction;
if (runRouteAction != null)
{
runRouteAction.RunRouteAction("roomOff", Room.SourceListKey);
}
@@ -1441,7 +1464,8 @@ namespace PepperDash.Essentials.Core.Fusion
_errorMessageRollUp = new StatusMonitorCollection(this);
foreach (var dev in DeviceManager.GetDevices())
{
if (dev is ICommunicationMonitor md)
var md = dev as ICommunicationMonitor;
if (md != null)
{
_errorMessageRollUp.AddMonitor(md.CommunicationMonitor);
Debug.LogMessage(LogEventLevel.Verbose, this, "Adding '{0}' to room's overall error monitor",
@@ -1507,8 +1531,9 @@ namespace PepperDash.Essentials.Core.Fusion
// Tie to method on occupancy object
//occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b));
var occRoom = Room as IRoomOccupancy;
if (Room is IRoomOccupancy occRoom)
if (occRoom != null)
{
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig);
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
@@ -1575,9 +1600,10 @@ namespace PepperDash.Essentials.Core.Fusion
// The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
// even though they all contain sigs.
var sigData = args.UserConfiguredSigDetail as BooleanSigDataFixedName;
BoolOutputSig outSig;
if (args.UserConfiguredSigDetail is BooleanSigDataFixedName sigData)
if (sigData != null)
{
outSig = sigData.OutputSig;
if (outSig.UserObject is Action<bool>)
@@ -1733,7 +1759,8 @@ namespace PepperDash.Essentials.Core.Fusion
/// </summary>
public static void TrySetMakeModel(this FusionStaticAsset asset, Device device)
{
if (device is IMakeModel mm)
var mm = device as IMakeModel;
if (mm != null)
{
asset.ParamMake.Value = mm.DeviceMake;
asset.ParamModel.Value = mm.DeviceModel;

View File

@@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Lighting
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
public List<LightingScene> LightingScenes { get; protected set; }
public LightingScene CurrentLightingScene { get; protected set; }
public IntFeedback CurrentLightingSceneFeedback { get; protected set; }
#endregion
protected LightingBase(string key, string name)
: base(key, name)
{
LightingScenes = new List<LightingScene>();
CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
}
public abstract void SelectScene(LightingScene scene);
public void SimulateSceneSelect(string sceneName)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName);
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
if (scene != null)
{
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
else
scene.IsActive = false;
}
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
{
Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
sceneIndex++;
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine) return;
sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
scene.IsActiveFeedback.FireUpdate();
sceneIndex++;
}
};
return joinMap;
}
}
public class LightingScene
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string ID { get; set; }
bool _IsActive;
[JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
IsActiveFeedback.FireUpdate();
}
}
[JsonIgnore]
public BoolFeedback IsActiveFeedback { get; set; }
public LightingScene()
{
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive));
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core.Lighting
{
public class LightingScene
{
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
public string ID { get; set; }
bool _IsActive;
[JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
IsActiveFeedback.FireUpdate();
}
}
[JsonIgnore]
public BoolFeedback IsActiveFeedback { get; set; }
public LightingScene()
{
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive));
}
}
}

View File

@@ -151,16 +151,17 @@ namespace PepperDash.Essentials.Core
{
if (MonitorBytesReceived)
{
Client.BytesReceived -= Client_BytesReceived;
Client.BytesReceived += Client_BytesReceived;
Client.BytesReceived += Client_BytesReceived;
}
else
{
Client.TextReceived -= Client_TextReceived;
Client.TextReceived += Client_TextReceived;
}
BeginPolling();
if (!IsSocket)
{
BeginPolling();
}
}
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)

View File

@@ -6,7 +6,6 @@
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AssemblyName>PepperDash_Essentials_Core</AssemblyName>
<RootNamespace>PepperDash.Essentials.Core</RootNamespace>
@@ -14,6 +13,7 @@
<PackageId>PepperDash.Essentials.Core</PackageId>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Version>2.0.0-local</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
@@ -31,7 +31,4 @@
<ItemGroup>
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
</ItemGroup>
<ItemGroup>
<Folder Include="Display\" />
</ItemGroup>
</Project>

View File

@@ -4,7 +4,6 @@ using System.Globalization;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Touchpanels
@@ -35,9 +34,9 @@ namespace PepperDash.Essentials.Core.Touchpanels
Debug.LogMessage(LogEventLevel.Information, this, "touchpanel registration response: {0}", registrationResponse);
}
_touchpanel.BaseEvent += Touchpanel_BaseEvent;
_touchpanel.ButtonStateChange += Touchpanel_ButtonStateChange;
_touchpanel.PanelStateChange += Touchpanel_PanelStateChange;
_touchpanel.BaseEvent += _touchpanel_BaseEvent;
_touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange;
_touchpanel.PanelStateChange += _touchpanel_PanelStateChange;
_buttons = buttons;
if (_buttons == null)
@@ -75,9 +74,10 @@ namespace PepperDash.Essentials.Core.Touchpanels
return;
}
TryParseInt(key, out int buttonNumber);
int buttonNumber;
TryParseInt(key, out buttonNumber);
var buttonEventTypes = config.EventTypes;
var buttonEventTypes = config.EventTypes;
BoolOutputSig enabledFb = null;
BoolOutputSig disabledFb = null;
@@ -161,10 +161,11 @@ namespace PepperDash.Essentials.Core.Touchpanels
return;
}
TryParseInt(key, out int buttonNumber);
int buttonNumber;
TryParseInt(key, out buttonNumber);
// Link up the button feedbacks to the specified device feedback
var buttonFeedback = config.Feedback;
// Link up the button feedbacks to the specified device feedback
var buttonFeedback = config.Feedback;
if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey))
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback not configured, skipping.",
@@ -176,14 +177,15 @@ namespace PepperDash.Essentials.Core.Touchpanels
try
{
if (!(DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) is Device device))
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.",
key, buttonFeedback.DeviceKey);
return;
}
var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device;
if (device == null)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.",
key, buttonFeedback.DeviceKey);
return;
}
deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName);
deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName);
if (deviceFeedback == null)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedbackName property '{1}' not found.",
@@ -222,37 +224,38 @@ namespace PepperDash.Essentials.Core.Touchpanels
}
var boolFeedback = deviceFeedback as BoolFeedback;
var intFeedback = deviceFeedback as IntFeedback;
switch (key)
{
case ("power"):
{
boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackPower);
break;
}
case ("volumeup"):
case ("volumedown"):
case ("volumefeedback"):
{
if (deviceFeedback is IntFeedback intFeedback)
{
var volumeFeedback = intFeedback;
volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph);
}
break;
}
case ("mute"):
{
boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackMute);
break;
}
default:
{
boolFeedback?.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]);
break;
}
}
}
switch (key)
{
case ("power"):
{
if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower);
break;
}
case ("volumeup"):
case ("volumedown"):
case ("volumefeedback"):
{
if (intFeedback != null)
{
var volumeFeedback = intFeedback;
volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph);
}
break;
}
case ("mute"):
{
if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute);
break;
}
default:
{
if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]);
break;
}
}
}
/// <summary>
/// Try parse int helper method
@@ -274,12 +277,12 @@ namespace PepperDash.Essentials.Core.Touchpanels
}
}
private void Touchpanel_BaseEvent(GenericBase device, BaseEventArgs args)
private void _touchpanel_BaseEvent(GenericBase device, BaseEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "BaseEvent: eventId-'{0}', index-'{1}'", args.EventId, args.Index);
}
private void Touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args)
private void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "ButtonStateChange: buttonNumber-'{0}' buttonName-'{1}', buttonState-'{2}'", args.Button.Number, args.Button.Name, args.NewButtonState);
var type = args.NewButtonState.ToString();
@@ -294,7 +297,7 @@ namespace PepperDash.Essentials.Core.Touchpanels
}
}
private void Touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args)
private void _touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "PanelStateChange: eventId-'{0}', index-'{1}'", args.EventId, args.Index);
}
@@ -307,7 +310,7 @@ namespace PepperDash.Essentials.Core.Touchpanels
/// <param name="type"></param>
public void Press(string buttonKey, string type)
{
this.LogVerbose("Press: buttonKey-'{buttonKey}', type-'{type}'", buttonKey, type);
Debug.LogMessage(LogEventLevel.Verbose, this, "Press: buttonKey-'{0}', type-'{1}'", buttonKey, type);
// TODO: In future, consider modifying this to generate actions at device activation time
// to prevent the need to dynamically call the method via reflection on each button press
@@ -322,12 +325,18 @@ namespace PepperDash.Essentials.Core.Touchpanels
public void ListButtons()
{
this.LogVerbose("MPC3 Controller {0} - Available Buttons", Key);
var line = new string('-', 35);
Debug.Console(0, this, line);
Debug.Console(0, this, "MPC3 Controller {0} - Available Butons", Key);
foreach (var button in _buttons)
{
this.LogVerbose("Key: {key}", button.Key);
Debug.Console(0, this, "Key: {0}", button.Key);
}
Debug.Console(0, this, line);
}
}

View File

@@ -119,23 +119,23 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
return;
}
if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device))
{
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.End();
var device = DeviceManager.GetDeviceForKey(body.DeviceKey) as IStreamDebugging;
if (device == null)
{
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.End();
return;
}
eStreamDebuggingSetting debugSetting;
return;
}
eStreamDebuggingSetting debugSetting;
try
{
debugSetting = (eStreamDebuggingSetting) Enum.Parse(typeof (eStreamDebuggingSetting), body.Setting, true);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception handling set debug request");
context.Response.StatusCode = 500;
context.Response.StatusDescription = "Internal Server Error";
context.Response.End();
@@ -161,7 +161,6 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception handling set debug request");
context.Response.StatusCode = 500;
context.Response.StatusDescription = "Internal Server Error";
context.Response.End();

View File

@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
{
private readonly CameraViscaPropertiesConfig PropertiesConfig;
CameraViscaPropertiesConfig PropertiesConfig;
public IBasicCommunication Communication { get; private set; }
@@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// <summary>
/// Used to store the actions to parse inquiry responses as the inquiries are sent
/// </summary>
private readonly CrestronQueue<Action<byte[]>> InquiryResponseQueue;
private CrestronQueue<Action<byte[]>> InquiryResponseQueue;
/// <summary>
/// Camera ID (Default 1)
@@ -45,7 +45,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public byte PanSpeedFast = 0x13;
public byte TiltSpeedFast = 0x13;
// private bool IsMoving;
private bool IsMoving;
private bool IsZooming;
bool _powerIsOn;
@@ -101,17 +101,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
Communication = comm;
if (comm is ISocketStatus socket)
{
// This instance uses IP control
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(Socket_ConnectionChange);
}
else
{
// This instance uses RS-232 control
}
var socket = comm as ISocketStatus;
if (socket != null)
{
// This instance uses IP control
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
else
{
// This instance uses RS-232 control
}
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; });
@@ -174,7 +175,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
}
void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
@@ -448,12 +449,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void PanLeft()
{
SendPanTiltCommand(new byte[] {0x01, 0x03}, false);
// IsMoving = true;
IsMoving = true;
}
public void PanRight()
{
SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
// IsMoving = true;
IsMoving = true;
}
public void PanStop()
{
@@ -462,12 +463,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public void TiltDown()
{
SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
// IsMoving = true;
IsMoving = true;
}
public void TiltUp()
{
SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
// IsMoving = true;
IsMoving = true;
}
public void TiltStop()
{
@@ -506,7 +507,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
{
StopSpeedTimer();
SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
// IsMoving = false;
IsMoving = false;
}
}
public void PositionHome()

View File

@@ -40,9 +40,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
private int _meetingWarningMinutes = 5;
//private Meeting _previousChangedMeeting;
private Meeting _previousChangedMeeting;
//private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown;
public int MeetingWarningMinutes
{
@@ -62,11 +62,16 @@ namespace PepperDash.Essentials.Devices.Common.Codec
set
{
_meetings = value;
MeetingsListHasChanged?.Invoke(this, new EventArgs());
var handler = MeetingsListHasChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
private readonly CTimer _scheduleChecker;
private CTimer _scheduleChecker;
public CodecScheduleAwareness()
{
@@ -94,7 +99,12 @@ namespace PepperDash.Essentials.Devices.Common.Codec
{
// Add this change type to the NotifiedChangeTypes
meeting.NotifiedChangeTypes |= changeType;
MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
var handler = MeetingEventChange;
if (handler != null)
{
handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
}
}
else
{

View File

@@ -4,7 +4,6 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Serilog.Events;
using System;
using System.Collections.Generic;
@@ -13,7 +12,12 @@ using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Devices.Common.Displays
{
public abstract class DisplayBase : EssentialsDevice, IDisplay
public abstract class DisplayBase : EssentialsDevice
, IHasFeedback
, IRoutingSinkWithSwitching
, IHasPowerControl
, IWarmingCooling
, IUsageTracking
{
private RoutingInputPort _currentInputPort;
public RoutingInputPort CurrentInputPort

View File

@@ -12,7 +12,7 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Displays
{
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string>, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback
public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs<string, string>, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback
{
public ISelectableItems<string> Inputs { get; private set; }

View File

@@ -16,6 +16,7 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Lighting
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
@@ -67,7 +68,12 @@ namespace PepperDash.Essentials.Devices.Common.Lighting
else
scene.IsActive = false;
}
LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,

View File

@@ -9,9 +9,10 @@
<OutputPath>bin\$(Configuration)\</OutputPath>
<AssemblyName>Essentials Devices Common</AssemblyName>
<RootNamespace>PepperDash.Essentials.Devices.Common</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>PepperDash Essentials Devices Common</Title>
<PackageId>PepperDash.Essentials.Devices.Common</PackageId>
<Version>2.0.0-local</Version>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>

View File

@@ -31,9 +31,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
protected const int MaxParticipants = 50;
private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs();
private readonly IHasDirectory _directoryCodec;
private readonly BasicTriList _directoryTrilist;
private readonly VideoCodecControllerJoinMap _directoryJoinmap;
private IHasDirectory _directoryCodec;
private BasicTriList _directoryTrilist;
private VideoCodecControllerJoinMap _directoryJoinmap;
protected string _timeFormatSpecifier;
protected string _dateFormatSpecifier;
@@ -216,7 +216,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// <param name="item"></param>
protected virtual void OnCallStatusChange(CodecActiveCallItem item)
{
CallStatusChange?.Invoke(this, new CodecCallStatusItemChangeEventArgs(item));
var handler = CallStatusChange;
if (handler != null)
{
handler(this, new CodecCallStatusItemChangeEventArgs(item));
}
PrivacyModeIsOnFeedback.FireUpdate();
@@ -248,8 +252,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
try
{
IsReady = true;
IsReadyChange?.Invoke(this, new EventArgs());
}
var h = IsReadyChange;
if (h != null)
{
h(this, new EventArgs());
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Error in SetIsReady() : {0}", e);
@@ -301,7 +309,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
joinMap.SetCustomJoinData(customJoins);
}
bridge?.AddJoinMap(Key, joinMap);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
LinkVideoCodecToApi(codec, trilist, joinMap);
@@ -519,10 +530,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
var autoCodec = codec as IHasCameraAutoMode;
if (!(codec is IHasCameraAutoMode autoCodec)) return;
if (autoCodec == null) return;
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue);
};
@@ -536,10 +548,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
var autoModeCodec = codec as IHasCameraAutoMode;
if (!(codec is IHasCameraAutoMode autoModeCodec)) return;
if (autoModeCodec == null) return;
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue);
}
@@ -636,7 +649,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
var p = participant;
if (index > MaxParticipants) break;
if (this is IHasParticipantAudioMute audioMuteCodec)
var audioMuteCodec = this as IHasParticipantAudioMute;
if (audioMuteCodec != null)
{
trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index,
() => audioMuteCodec.ToggleAudioForParticipant(p.UserId));
@@ -645,7 +659,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
() => audioMuteCodec.ToggleVideoForParticipant(p.UserId));
}
if (this is IHasParticipantPinUnpin pinCodec)
var pinCodec = this as IHasParticipantPinUnpin;
if (pinCodec != null)
{
trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index,
() => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo));
@@ -1074,25 +1089,29 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
// Allow auto dial of selected line. Always dials first contact method
if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber))
{
if (_selectedDirectoryItem is IInvitableContact invitableEntry)
var invitableEntry = _selectedDirectoryItem as IInvitableContact;
if (invitableEntry != null)
{
Dial(invitableEntry);
return;
}
var entryToDial = _selectedDirectoryItem as DirectoryContact;
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber,
trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber,
selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty);
if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) return;
if (entryToDial == null) return;
Dial(entryToDial.ContactMethods[0].Number);
}
else
{
// If auto dial is disabled...
var entryToDial = _selectedDirectoryItem as DirectoryContact;
if (!(_selectedDirectoryItem is DirectoryContact entryToDial))
if (entryToDial == null)
{
// Clear out values and actions from last selected item
trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0);
@@ -1277,76 +1296,78 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count);
};
if (this is IJoinCalls joinCodec)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
var joinCodec = this as IJoinCalls;
if (joinCodec != null)
{
trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls());
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++)
{
trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () =>
{
var call = ActiveCalls[i];
if (call != null)
{
joinCodec.JoinCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i);
}
});
}
}
if (this is IHasCallHold holdCodec)
{
trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () =>
{
foreach (var call in ActiveCalls)
{
holdCodec.HoldCall(call);
}
});
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;
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;
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.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i);
}
});
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.HoldCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, 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;
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.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
var call = ActiveCalls[index];
if (call != null)
{
holdCodec.ResumeCall(call);
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i);
}
});
}
}
trilist.OnlineStatusChange += (device, args) =>
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
@@ -1484,45 +1505,48 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) =>
{
if (codec is IHasCameraOff offCodec)
{
if (offCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
var offCodec = codec as IHasCameraOff;
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
if (offCodec != null)
{
if (offCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
};
var offModeCodec = codec as IHasCameraOff;
if (codec is IHasCameraOff offModeCodec)
{
if (offModeCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
if (offModeCodec != null)
{
if (offModeCodec.CameraIsOffFeedback.BoolValue)
{
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
return;
}
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue);
trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false);
}
@@ -1541,58 +1565,64 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.CameraTiltUp.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (camera == null) return;
if (b) camera.TiltUp();
if (b) camera.TiltUp();
else camera.TiltStop();
});
trilist.SetBoolSigAction(joinMap.CameraTiltDown.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (camera == null) return;
if (b) camera.TiltDown();
if (b) camera.TiltDown();
else camera.TiltStop();
});
trilist.SetBoolSigAction(joinMap.CameraPanLeft.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (camera == null) return;
if (b) camera.PanLeft();
if (b) camera.PanLeft();
else camera.PanStop();
});
trilist.SetBoolSigAction(joinMap.CameraPanRight.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (camera == null) return;
if (b) camera.PanRight();
if (b) camera.PanRight();
else camera.PanStop();
});
trilist.SetBoolSigAction(joinMap.CameraZoomIn.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (camera == null) return;
if (b) camera.ZoomIn();
if (b) camera.ZoomIn();
else camera.ZoomStop();
});
trilist.SetBoolSigAction(joinMap.CameraZoomOut.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraPtzControl;
if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return;
if (camera == null) return;
if (b) camera.ZoomOut();
if (b) camera.ZoomOut();
else camera.ZoomStop();
});
@@ -1600,8 +1630,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return;
if (camera == null) return;
if (b) camera.FocusNear();
else camera.FocusStop();
@@ -1610,8 +1641,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return;
if (camera == null) return;
if (b) camera.FocusFar();
else camera.FocusStop();
@@ -1620,8 +1652,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () =>
{
if (codec.SelectedCamera == null) return;
var camera = codec.SelectedCamera as IHasCameraFocusControl;
if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return;
if (camera == null) return;
camera.TriggerAutoFocus();
});
@@ -1740,6 +1773,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
// 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)
@@ -1786,7 +1820,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
// 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);
@@ -1895,8 +1929,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
{
if (value == true)
{
InitialSyncCompleted?.Invoke(this, new EventArgs());
}
var handler = InitialSyncCompleted;
if (handler != null)
{
handler(this, new EventArgs());
}
}
_InitialSyncComplete = value;
}
}

View File

@@ -1,31 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class SourceSelectMessageContent
{
[JsonProperty("sourceListItemKey")]
public string SourceListItemKey { get; set; }
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
}
public class DirectRoute
{
[JsonProperty("sourceKey")]
public string SourceKey { get; set; }
[JsonProperty("destinationKey")]
public string DestinationKey { get; set; }
[JsonProperty("signalType")]
public eRoutingSignalType SignalType { get; set; }
}
/// <summary>
///
/// </summary>
/// <param name="b"></param>
public delegate void PressAndHoldAction(bool b);
}

View File

@@ -1,60 +0,0 @@
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.AppServer;
using PepperDash.Essentials.AppServer.Messengers;
using System.Linq;
using DisplayBase = PepperDash.Essentials.Devices.Common.Displays.DisplayBase;
namespace PepperDash.Essentials.Room.MobileControl
{
public class DisplayBaseMessenger : MessengerBase
{
private readonly DisplayBase display;
public DisplayBaseMessenger(string key, string messagePath, DisplayBase device) : base(key, messagePath, device)
{
display = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
/*AddAction("/powerOn", (id, content) => display.PowerOn());
AddAction("/powerOff", (id, content) => display.PowerOff());
AddAction("/powerToggle", (id, content) => display.PowerToggle());*/
AddAction("/inputSelect", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var inputPort = display.InputPorts.FirstOrDefault(i => i.Key == s.Value);
if (inputPort == null)
{
this.LogWarning("No input named {inputName} found for {deviceKey}", s, display.Key);
return;
}
display.ExecuteSwitch(inputPort.Selector);
});
AddAction("/inputs", (id, content) =>
{
var inputsList = display.InputPorts.Select(p => p.Key).ToList();
var messageObject = new MobileControlMessage
{
Type = MessagePath + "/inputs",
Content = JToken.FromObject(new
{
inputKeys = inputsList,
})
};
AppServerController.SendMessageObject(messageObject);
});
}
}
}

View File

@@ -1,29 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IChannelMessenger : MessengerBase
{
private readonly IChannel channelDevice;
public IChannelMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
channelDevice = device as IChannel;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/chanUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelUp(b)));
AddAction("/chanDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelDown(b)));
AddAction("/lastChan", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.LastChannel(b)));
AddAction("/guide", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Guide(b)));
AddAction("/info", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Info(b)));
AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Exit(b)));
}
}
}

View File

@@ -1,25 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IColorMessenger : MessengerBase
{
private readonly IColor colorDevice;
public IColorMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
colorDevice = device as IColor;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/red", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Red(b)));
AddAction("/green", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Green(b)));
AddAction("/yellow", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Yellow(b)));
AddAction("/blue", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Blue(b)));
}
}
}

View File

@@ -1,29 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IDPadMessenger : MessengerBase
{
private readonly IDPad dpadDevice;
public IDPadMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
dpadDevice = device as IDPad;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/up", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Up(b)));
AddAction("/down", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Down(b)));
AddAction("/left", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Left(b)));
AddAction("/right", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Right(b)));
AddAction("/select", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Select(b)));
AddAction("/menu", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Menu(b)));
AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Exit(b)));
}
}
}

View File

@@ -1,24 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IDvrMessenger : MessengerBase
{
private readonly IDvr dvrDevice;
public IDvrMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
dvrDevice = device as IDvr;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/dvrlist", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.DvrList(b)));
AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.Record(b)));
}
}
}

View File

@@ -1,24 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class IHasPowerMessenger : MessengerBase
{
private readonly IHasPowerControl powerDevice;
public IHasPowerMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
powerDevice = device as IHasPowerControl;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/powerOn", (id, content) => powerDevice?.PowerOn());
AddAction("/powerOff", (id, content) => powerDevice?.PowerOff());
AddAction("/powerToggle", (id, content) => powerDevice?.PowerToggle());
}
}
}

View File

@@ -1,34 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class INumericKeypadMessenger : MessengerBase
{
private readonly INumericKeypad keypadDevice;
public INumericKeypadMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
keypadDevice = device as INumericKeypad;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/num0", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit0(b)));
AddAction("/num1", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit1(b)));
AddAction("/num2", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit2(b)));
AddAction("/num3", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit3(b)));
AddAction("/num4", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit4(b)));
AddAction("/num5", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit5(b)));
AddAction("/num6", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit6(b)));
AddAction("/num7", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit7(b)));
AddAction("/num8", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit8(b)));
AddAction("/num9", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit9(b)));
AddAction("/numDash", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton1(b)));
AddAction("/numEnter", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton2(b)));
// Deal with the Accessory functions on the numpad later
}
}
}

View File

@@ -1,39 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class ISetTopBoxControlsMessenger : MessengerBase
{
private readonly ISetTopBoxControls stbDevice;
public ISetTopBoxControlsMessenger(string key, string messagePath, IKeyName device) : base(key, messagePath, device)
{
stbDevice = device as ISetTopBoxControls;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendISetTopBoxControlsFullMessageObject());
AddAction("/dvrList", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.DvrList(b)));
AddAction("/replay", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.Replay(b)));
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
private void SendISetTopBoxControlsFullMessageObject()
{
PostStatusMessage(new SetTopBoxControlsState());
}
}
public class SetTopBoxControlsState : DeviceStateMessageBase
{
}
}

View File

@@ -1,30 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.MobileControl
{
public class ITransportMessenger : MessengerBase
{
private readonly ITransport transportDevice;
public ITransportMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
transportDevice = device as ITransport;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/play", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Play(b)));
AddAction("/pause", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Pause(b)));
AddAction("/stop", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Stop(b)));
AddAction("/prevTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapPlus(b)));
AddAction("/nextTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapMinus(b)));
AddAction("/rewind", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Rewind(b)));
AddAction("/ffwd", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.FFwd(b)));
AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Record(b)));
}
}
}

View File

@@ -1,116 +0,0 @@
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge for an AudioCodecBase device
/// </summary>
public class AudioCodecBaseMessenger : MessengerBase
{
/// <summary>
/// Device being bridged
/// </summary>
public AudioCodecBase Codec { get; private set; }
/// <summary>
/// Constuctor
/// </summary>
/// <param name="key"></param>
/// <param name="codec"></param>
/// <param name="messagePath"></param>
public AudioCodecBaseMessenger(string key, AudioCodecBase codec, string messagePath)
: base(key, messagePath, codec)
{
Codec = codec ?? throw new ArgumentNullException("codec");
codec.CallStatusChange += Codec_CallStatusChange;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject());
AddAction("/dial", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
Codec.Dial(msg.Value);
});
AddAction("/endCallById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(msg.Value);
if (call != null)
Codec.EndCall(call);
});
AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls());
AddAction("/dtmf", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
Codec.SendDtmf(msg.Value);
});
AddAction("/rejectById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(msg.Value);
if (call != null)
Codec.RejectCall(call);
});
AddAction("/acceptById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(msg.Value);
if (call != null)
Codec.AcceptCall(call);
});
}
/// <summary>
/// Helper to grab a call with string ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private CodecActiveCallItem GetCallWithId(string id)
{
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
}
private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
SendAtcFullMessageObject();
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
private void SendAtcFullMessageObject()
{
var info = Codec.CodecInfo;
PostStatusMessage(JToken.FromObject(new
{
isInCall = Codec.IsInCall,
calls = Codec.ActiveCalls,
info = new
{
phoneNumber = info.PhoneNumber
}
})
);
}
}
}

View File

@@ -1,204 +0,0 @@
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Cameras;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class CameraBaseMessenger : MessengerBase
{
/// <summary>
/// Device being bridged
/// </summary>
public CameraBase Camera { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="camera"></param>
/// <param name="messagePath"></param>
public CameraBaseMessenger(string key, CameraBase camera, string messagePath)
: base(key, messagePath, camera)
{
Camera = camera ?? throw new ArgumentNullException("camera");
if (Camera is IHasCameraPresets presetsCamera)
{
presetsCamera.PresetsListHasChanged += PresetsCamera_PresetsListHasChanged;
}
}
private void PresetsCamera_PresetsListHasChanged(object sender, EventArgs e)
{
var presetList = new List<CameraPreset>();
if (Camera is IHasCameraPresets presetsCamera)
presetList = presetsCamera.Presets;
PostStatusMessage(JToken.FromObject(new
{
presets = presetList
})
);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
if (Camera is IHasCameraPtzControl ptzCamera)
{
// Need to evaluate how to pass through these P&H actions. Need a method that takes a bool maybe?
AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.TiltUp();
return;
}
ptzCamera.TiltStop();
}));
AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.TiltDown();
return;
}
ptzCamera.TiltStop();
}));
AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.PanLeft();
return;
}
ptzCamera.PanStop();
}));
AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.PanRight();
return;
}
ptzCamera.PanStop();
}));
AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.ZoomIn();
return;
}
ptzCamera.ZoomStop();
}));
AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
ptzCamera.ZoomOut();
return;
}
ptzCamera.ZoomStop();
}));
}
if (Camera is IHasCameraAutoMode)
{
AddAction("/cameraModeAuto", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOn());
AddAction("/cameraModeManual", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOff());
}
if (Camera is IHasPowerControl)
{
AddAction("/cameraModeOff", (id, content) => (Camera as IHasPowerControl).PowerOff());
AddAction("/cameraModeManual", (id, content) => (Camera as IHasPowerControl).PowerOn());
}
if (Camera is IHasCameraPresets presetsCamera)
{
for (int i = 1; i <= 6; i++)
{
var preset = i;
AddAction("/cameraPreset" + i, (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<int>>();
presetsCamera.PresetSelect(msg.Value);
});
}
}
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
/// Helper method to update the full status of the camera
/// </summary>
private void SendCameraFullMessageObject()
{
var presetList = new List<CameraPreset>();
if (Camera is IHasCameraPresets presetsCamera)
presetList = presetsCamera.Presets;
PostStatusMessage(JToken.FromObject(new
{
cameraManualSupported = Camera is IHasCameraControls,
cameraAutoSupported = Camera is IHasCameraAutoMode,
cameraOffSupported = Camera is IHasCameraOff,
cameraMode = GetCameraMode(),
hasPresets = Camera is IHasCameraPresets,
presets = presetList
})
);
}
/// <summary>
/// Computes the current camera mode
/// </summary>
/// <returns></returns>
private string GetCameraMode()
{
string m;
if (Camera is IHasCameraAutoMode && (Camera as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.BoolValue)
m = eCameraControlMode.Auto.ToString().ToLower();
else if (Camera is IHasPowerControlWithFeedback && !(Camera as IHasPowerControlWithFeedback).PowerIsOnFeedback.BoolValue)
m = eCameraControlMode.Off.ToString().ToLower();
else
m = eCameraControlMode.Manual.ToString().ToLower();
return m;
}
}
}

View File

@@ -1,42 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceInfo;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class DeviceInfoMessenger : MessengerBase
{
private readonly IDeviceInfoProvider _deviceInfoProvider;
public DeviceInfoMessenger(string key, string messagePath, IDeviceInfoProvider device) : base(key, messagePath, device as Device)
{
_deviceInfoProvider = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
_deviceInfoProvider.DeviceInfoChanged += (o, a) =>
{
PostStatusMessage(JToken.FromObject(new
{
deviceInfo = a.DeviceInfo
}));
};
AddAction("/fullStatus", (id, context) => PostStatusMessage(new DeviceInfoStateMessage
{
DeviceInfo = _deviceInfoProvider.DeviceInfo
}));
AddAction("/update", (id, context) => _deviceInfoProvider.UpdateDeviceInfo());
}
}
public class DeviceInfoStateMessage : DeviceStateMessageBase
{
[JsonProperty("deviceInfo")]
public DeviceInfo DeviceInfo { get; set; }
}
}

View File

@@ -1,100 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Presets;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class DevicePresetsModelMessenger : MessengerBase
{
private readonly ITvPresetsProvider _presetsDevice;
public DevicePresetsModelMessenger(string key, string messagePath, ITvPresetsProvider presetsDevice)
: base(key, messagePath, presetsDevice as Device)
{
_presetsDevice = presetsDevice;
}
private void SendPresets()
{
PostStatusMessage(new PresetStateMessage
{
Favorites = _presetsDevice.TvPresets.PresetsList
});
}
private void RecallPreset(ISetTopBoxNumericKeypad device, string channel)
{
_presetsDevice.TvPresets.Dial(channel, device);
}
private void SavePresets(List<PresetChannel> presets)
{
_presetsDevice.TvPresets.UpdatePresets(presets);
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
AddAction("/presets/fullStatus", (id, content) =>
{
this.LogInformation("getting full status for client {id}", id);
try
{
SendPresets();
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception sending preset full status", this);
}
});
AddAction("/presets/recall", (id, content) =>
{
var p = content.ToObject<PresetChannelMessage>();
if (!(DeviceManager.GetDeviceForKey(p.DeviceKey) is ISetTopBoxNumericKeypad dev))
{
this.LogDebug("Unable to find device with key {0}", p.DeviceKey);
return;
}
RecallPreset(dev, p.Preset.Channel);
});
AddAction("/presets/save", (id, content) =>
{
var presets = content.ToObject<List<PresetChannel>>();
SavePresets(presets);
});
_presetsDevice.TvPresets.PresetsSaved += (p) => SendPresets();
}
#endregion
}
public class PresetChannelMessage
{
[JsonProperty("preset")]
public PresetChannel Preset;
[JsonProperty("deviceKey")]
public string DeviceKey;
}
public class PresetStateMessage : DeviceStateMessageBase
{
[JsonProperty("favorites", NullValueHandling = NullValueHandling.Ignore)]
public List<PresetChannel> Favorites { get; set; } = new List<PresetChannel>();
}
}

View File

@@ -1,172 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class DeviceVolumeMessenger : MessengerBase
{
private readonly IBasicVolumeWithFeedback _localDevice;
public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device)
: base(key, messagePath, device as IKeyName)
{
_localDevice = device;
}
private void SendStatus()
{
try
{
var messageObj = new VolumeStateMessage
{
Volume = new Volume
{
Level = _localDevice?.VolumeLevelFeedback.IntValue ?? -1,
Muted = _localDevice?.MuteFeedback.BoolValue ?? false,
HasMute = true, // assume all devices have mute for now
}
};
if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
{
messageObj.Volume.RawValue = volumeAdvanced.RawVolumeLevel.ToString();
messageObj.Volume.Units = volumeAdvanced.Units;
}
PostStatusMessage(messageObj);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception sending full status", this);
}
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendStatus());
AddAction("/level", (id, content) =>
{
var volume = content.ToObject<MobileControlSimpleContent<ushort>>();
_localDevice.SetVolume(volume.Value);
});
AddAction("/muteToggle", (id, content) =>
{
_localDevice.MuteToggle();
});
AddAction("/muteOn", (id, content) =>
{
_localDevice.MuteOn();
});
AddAction("/muteOff", (id, content) =>
{
_localDevice.MuteOff();
});
AddAction("/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume up with {value}", DeviceKey, b);
try
{
_localDevice.VolumeUp(b);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Got exception during volume up: {Exception}", null, ex);
}
}));
AddAction("/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume down with {value}", DeviceKey, b);
try
{
_localDevice.VolumeDown(b);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Got exception during volume down: {Exception}", null, ex);
}
}));
_localDevice.MuteFeedback.OutputChange += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(
new
{
volume = new
{
muted = args.BoolValue
}
})
);
};
_localDevice.VolumeLevelFeedback.OutputChange += (sender, args) =>
{
var rawValue = "";
if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
{
rawValue = volumeAdvanced.RawVolumeLevel.ToString();
}
var message = new
{
volume = new
{
level = args.IntValue,
rawValue
}
};
PostStatusMessage(JToken.FromObject(message));
};
}
#endregion
}
public class VolumeStateMessage : DeviceStateMessageBase
{
[JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)]
public Volume Volume { get; set; }
}
public class Volume
{
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
public int? Level { get; set; }
[JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasMute { get; set; }
[JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)]
public bool? Muted { get; set; }
[JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)]
public string Label { get; set; }
[JsonProperty("rawValue", NullValueHandling = NullValueHandling.Ignore)]
public string RawValue { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("units", NullValueHandling = NullValueHandling.Ignore)]
public eVolumeLevelUnits? Units { get; set; }
}
}

View File

@@ -1,25 +0,0 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class GenericMessenger : MessengerBase
{
public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device)
{
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
}
private void SendFullStatus()
{
var state = new DeviceStateMessageBase();
PostStatusMessage(state);
}
}
}

View File

@@ -1,74 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ICommunicationMonitorMessenger : MessengerBase
{
private readonly ICommunicationMonitor _communicationMonitor;
public ICommunicationMonitorMessenger(string key, string messagePath, ICommunicationMonitor device) : base(key, messagePath, device as IKeyName)
{
_communicationMonitor = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
PostStatusMessage(new CommunicationMonitorState
{
CommunicationMonitor = new CommunicationMonitorProps
{
IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline,
Status = _communicationMonitor.CommunicationMonitor.Status
}
});
});
_communicationMonitor.CommunicationMonitor.StatusChange += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(new
{
commMonitor = new CommunicationMonitorProps
{
IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline,
Status = _communicationMonitor.CommunicationMonitor.Status
}
}));
};
}
}
/// <summary>
/// Represents the state of the communication monitor
/// </summary>
public class CommunicationMonitorState : DeviceStateMessageBase
{
[JsonProperty("commMonitor", NullValueHandling = NullValueHandling.Ignore)]
public CommunicationMonitorProps CommunicationMonitor { get; set; }
}
public class CommunicationMonitorProps
{ /// <summary>
/// For devices that implement ICommunicationMonitor, reports the online status of the device
/// </summary>
[JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOnline { get; set; }
/// <summary>
/// For devices that implement ICommunicationMonitor, reports the online status of the device
/// </summary>
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public MonitorStatus Status { get; set; }
}
}

View File

@@ -1,50 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IDspPresetsMessenger : MessengerBase
{
private readonly IDspPresets device;
public IDspPresetsMessenger(string key, string messagePath, IDspPresets device)
: base(key, messagePath, device as IKeyName)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
var message = new IHasDspPresetsStateMessage
{
Presets = device.Presets
};
PostStatusMessage(message);
});
AddAction("/recallPreset", (id, content) =>
{
var presetKey = content.ToObject<string>();
if (!string.IsNullOrEmpty(presetKey))
{
device.RecallPreset(presetKey);
}
});
}
}
public class IHasDspPresetsStateMessage : DeviceStateMessageBase
{
[JsonProperty("presets")]
public Dictionary<string, IKeyName> Presets { get; set; }
}
}

View File

@@ -1,154 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IEssentialsRoomCombinerMessenger : MessengerBase
{
private readonly IEssentialsRoomCombiner _roomCombiner;
public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner)
: base(key, messagePath, roomCombiner as Device)
{
_roomCombiner = roomCombiner;
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/setAutoMode", (id, content) =>
{
_roomCombiner.SetAutoMode();
});
AddAction("/setManualMode", (id, content) =>
{
_roomCombiner.SetManualMode();
});
AddAction("/toggleMode", (id, content) =>
{
_roomCombiner.ToggleMode();
});
AddAction("/togglePartitionState", (id, content) =>
{
try
{
var partitionKey = content.ToObject<string>();
_roomCombiner.TogglePartitionState(partitionKey);
}
catch (Exception e)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this);
}
});
AddAction("/setRoomCombinationScenario", (id, content) =>
{
try
{
var scenarioKey = content.ToObject<string>();
_roomCombiner.SetRoomCombinationScenario(scenarioKey);
}
catch (Exception e)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this);
}
});
_roomCombiner.RoomCombinationScenarioChanged += (sender, args) =>
{
SendFullStatus();
};
_roomCombiner.IsInAutoModeFeedback.OutputChange += (sender, args) =>
{
var message = new
{
isInAutoMode = _roomCombiner.IsInAutoModeFeedback.BoolValue
};
PostStatusMessage(JToken.FromObject(message));
};
foreach (var partition in _roomCombiner.Partitions)
{
partition.PartitionPresentFeedback.OutputChange += (sender, args) =>
{
var message = new
{
partitions = _roomCombiner.Partitions
};
PostStatusMessage(JToken.FromObject(message));
};
}
}
private void SendFullStatus()
{
try
{
var rooms = new List<IKeyName>();
foreach (var room in _roomCombiner.Rooms)
{
rooms.Add(new RoomCombinerRoom { Key = room.Key, Name = room.Name });
}
var message = new IEssentialsRoomCombinerStateMessage
{
IsInAutoMode = _roomCombiner.IsInAutoMode,
CurrentScenario = _roomCombiner.CurrentScenario,
Rooms = rooms,
RoomCombinationScenarios = _roomCombiner.RoomCombinationScenarios,
Partitions = _roomCombiner.Partitions
};
PostStatusMessage(message);
}
catch (Exception e)
{
this.LogException(e, "Error sending full status");
}
}
private class RoomCombinerRoom : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
}
public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase
{
[JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)]
public bool IsInAutoMode { get; set; }
[JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)]
public IRoomCombinationScenario CurrentScenario { get; set; }
[JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)]
public List<IKeyName> Rooms { get; set; }
[JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)]
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; set; }
[JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)]
public List<IPartitionController> Partitions { get; set; }
}
}

View File

@@ -1,57 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHasCurrentSourceInfoMessenger : MessengerBase
{
private readonly IHasCurrentSourceInfoChange sourceDevice;
public IHasCurrentSourceInfoMessenger(string key, string messagePath, IHasCurrentSourceInfoChange device) : base(key, messagePath, device as IKeyName)
{
sourceDevice = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
var message = new CurrentSourceStateMessage
{
CurrentSourceKey = sourceDevice.CurrentSourceInfoKey,
CurrentSource = sourceDevice.CurrentSourceInfo
};
PostStatusMessage(message);
});
sourceDevice.CurrentSourceChange += (sender, e) =>
{
switch (e)
{
case ChangeType.DidChange:
{
PostStatusMessage(JToken.FromObject(new
{
currentSourceKey = string.IsNullOrEmpty(sourceDevice.CurrentSourceInfoKey) ? string.Empty : sourceDevice.CurrentSourceInfoKey,
currentSource = sourceDevice.CurrentSourceInfo
}));
break;
}
}
};
}
}
public class CurrentSourceStateMessage : DeviceStateMessageBase
{
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentSourceKey { get; set; }
[JsonProperty("currentSource")]
public SourceListItem CurrentSource { get; set; }
}
}

View File

@@ -1,52 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHasPowerControlWithFeedbackMessenger : MessengerBase
{
private readonly IHasPowerControlWithFeedback _powerControl;
public IHasPowerControlWithFeedbackMessenger(string key, string messagePath, IHasPowerControlWithFeedback powerControl)
: base(key, messagePath, powerControl as Device)
{
_powerControl = powerControl;
}
public void SendFullStatus()
{
var messageObj = new PowerControlWithFeedbackStateMessage
{
PowerState = _powerControl.PowerIsOnFeedback.BoolValue
};
PostStatusMessage(messageObj);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
_powerControl.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; ;
}
private void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs args)
{
PostStatusMessage(JToken.FromObject(new
{
powerState = args.BoolValue
})
);
}
}
public class PowerControlWithFeedbackStateMessage : DeviceStateMessageBase
{
[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)]
public bool? PowerState { get; set; }
}
}

View File

@@ -1,81 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHasScheduleAwarenessMessenger : MessengerBase
{
public IHasScheduleAwareness ScheduleSource { get; private set; }
public IHasScheduleAwarenessMessenger(string key, IHasScheduleAwareness scheduleSource, string messagePath)
: base(key, messagePath, scheduleSource as Device)
{
ScheduleSource = scheduleSource ?? throw new ArgumentNullException("scheduleSource");
ScheduleSource.CodecSchedule.MeetingsListHasChanged += new EventHandler<EventArgs>(CodecSchedule_MeetingsListHasChanged);
ScheduleSource.CodecSchedule.MeetingEventChange += new EventHandler<MeetingEventArgs>(CodecSchedule_MeetingEventChange);
}
protected override void RegisterActions()
{
AddAction("/schedule/fullStatus", (id, content) => SendFullScheduleObject());
}
private void CodecSchedule_MeetingEventChange(object sender, MeetingEventArgs e)
{
PostStatusMessage(JToken.FromObject(new MeetingChangeMessage
{
MeetingChange = new MeetingChange
{
ChangeType = e.ChangeType.ToString(),
Meeting = e.Meeting
}
})
);
}
private void CodecSchedule_MeetingsListHasChanged(object sender, EventArgs e)
{
SendFullScheduleObject();
}
/// <summary>
/// Helper method to send the full schedule data
/// </summary>
private void SendFullScheduleObject()
{
PostStatusMessage(new FullScheduleMessage
{
Meetings = ScheduleSource.CodecSchedule.Meetings,
MeetingWarningMinutes = ScheduleSource.CodecSchedule.MeetingWarningMinutes
});
}
}
public class FullScheduleMessage : DeviceStateMessageBase
{
[JsonProperty("meetings", NullValueHandling = NullValueHandling.Ignore)]
public List<Meeting> Meetings { get; set; }
[JsonProperty("meetingWarningMinutes", NullValueHandling = NullValueHandling.Ignore)]
public int MeetingWarningMinutes { get; set; }
}
public class MeetingChangeMessage
{
[JsonProperty("meetingChange", NullValueHandling = NullValueHandling.Ignore)]
public MeetingChange MeetingChange { get; set; }
}
public class MeetingChange
{
[JsonProperty("changeType", NullValueHandling = NullValueHandling.Ignore)]
public string ChangeType { get; set; }
[JsonProperty("meeting", NullValueHandling = NullValueHandling.Ignore)]
public Meeting Meeting { get; set; }
}
}

View File

@@ -1,43 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IHumiditySensorMessenger : MessengerBase
{
private readonly IHumiditySensor device;
public IHumiditySensorMessenger(string key, IHumiditySensor device, string messagePath)
: base(key, messagePath, device as Device)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
device.HumidityFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
}
private void SendFullStatus()
{
var state = new IHumiditySensorStateMessage
{
Humidity = string.Format("{0}%", device.HumidityFeedback.UShortValue)
};
PostStatusMessage(state);
}
}
public class IHumiditySensorStateMessage : DeviceStateMessageBase
{
[JsonProperty("humidity")]
public string Humidity { get; set; }
}
}

View File

@@ -1,91 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ILevelControlsMessenger : MessengerBase
{
private ILevelControls levelControlsDevice;
public ILevelControlsMessenger(string key, string messagePath, ILevelControls device) : base(key, messagePath, device as Device)
{
levelControlsDevice = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, context) =>
{
var message = new LevelControlStateMessage
{
Levels = levelControlsDevice.LevelControlPoints.ToDictionary(kv => kv.Key, kv => new Volume { Level = kv.Value.VolumeLevelFeedback.IntValue, Muted = kv.Value.MuteFeedback.BoolValue })
};
PostStatusMessage(message);
});
foreach (var levelControl in levelControlsDevice.LevelControlPoints)
{
// reassigning here just in case of lambda closure issues
var key = levelControl.Key;
var control = levelControl.Value;
AddAction($"/{key}/level", (id, content) =>
{
var request = content.ToObject<MobileControlSimpleContent<ushort>>();
control.SetVolume(request.Value);
});
AddAction($"/{key}/muteToggle", (id, content) =>
{
control.MuteToggle();
});
AddAction($"/{key}/muteOn", (id, content) => control.MuteOn());
AddAction($"/{key}/muteOff", (id, content) => control.MuteOff());
AddAction($"/{key}/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeUp(b)));
AddAction($"/{key}/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeDown(b)));
control.VolumeLevelFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new
{
levelControls = new Dictionary<string, Volume>
{
{key, new Volume{Level = a.IntValue} }
}
}));
control.MuteFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new
{
levelControls = new Dictionary<string, Volume>
{
{key, new Volume{Muted = a.BoolValue} }
}
}));
}
}
}
public class LevelControlStateMessage : DeviceStateMessageBase
{
[JsonProperty("levelControls")]
public Dictionary<string, Volume> Levels { get; set; }
}
public class LevelControlRequestMessage
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
public ushort? Level { get; set; }
}
}

View File

@@ -1,168 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Messenger for devices that implment IMatrixRouting
/// </summary>
public class IMatrixRoutingMessenger : MessengerBase
{
private readonly IMatrixRouting matrixDevice;
public IMatrixRoutingMessenger(string key, string messagePath, IMatrixRouting device) : base(key, messagePath, device as Device)
{
matrixDevice = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) =>
{
try
{
Debug.LogMessage(LogEventLevel.Verbose, "InputCount: {inputCount}, OutputCount: {outputCount}", this, matrixDevice.InputSlots.Count, matrixDevice.OutputSlots.Count);
var message = new MatrixStateMessage
{
Outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value)),
Inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value)),
};
PostStatusMessage(message);
}
catch (Exception e)
{
Debug.LogMessage(e, "Exception Getting full status: {@exception}", this, e);
}
});
AddAction("/route", (id, content) =>
{
var request = content.ToObject<MatrixRouteRequest>();
matrixDevice.Route(request.InputKey, request.OutputKey, request.RouteType);
});
foreach (var output in matrixDevice.OutputSlots)
{
var key = output.Key;
var outputSlot = output.Value;
outputSlot.OutputSlotChanged += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(new
{
outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value))
}));
};
}
foreach (var input in matrixDevice.InputSlots)
{
var key = input.Key;
var inputSlot = input.Value;
inputSlot.VideoSyncChanged += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(new
{
inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value))
}));
};
}
}
}
public class MatrixStateMessage : DeviceStateMessageBase
{
[JsonProperty("outputs")]
public Dictionary<string, RoutingOutput> Outputs;
[JsonProperty("inputs")]
public Dictionary<string, RoutingInput> Inputs;
}
public class RoutingInput
{
private IRoutingInputSlot _input;
[JsonProperty("txDeviceKey", NullValueHandling = NullValueHandling.Ignore)]
public string TxDeviceKey => _input?.TxDeviceKey;
[JsonProperty("slotNumber", NullValueHandling = NullValueHandling.Ignore)]
public int? SlotNumber => _input?.SlotNumber;
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
[JsonProperty("supportedSignalTypes", NullValueHandling = NullValueHandling.Ignore)]
public eRoutingSignalType? SupportedSignalTypes => _input?.SupportedSignalTypes;
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name => _input?.Name;
[JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOnline => _input?.IsOnline.BoolValue;
[JsonProperty("videoSyncDetected", NullValueHandling = NullValueHandling.Ignore)]
public bool? VideoSyncDetected => _input?.VideoSyncDetected;
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
public string Key => _input?.Key;
public RoutingInput(IRoutingInputSlot input)
{
_input = input;
}
}
public class RoutingOutput
{
private IRoutingOutputSlot _output;
public RoutingOutput(IRoutingOutputSlot output)
{
_output = output;
}
[JsonProperty("rxDeviceKey")]
public string RxDeviceKey => _output.RxDeviceKey;
[JsonProperty("currentRoutes")]
public Dictionary<string, RoutingInput> CurrentRoutes => _output.CurrentRoutes.ToDictionary(kvp => kvp.Key.ToString(), kvp => new RoutingInput(kvp.Value));
[JsonProperty("slotNumber")]
public int SlotNumber => _output.SlotNumber;
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
[JsonProperty("supportedSignalTypes")]
public eRoutingSignalType SupportedSignalTypes => _output.SupportedSignalTypes;
[JsonProperty("name")]
public string Name => _output.Name;
[JsonProperty("key")]
public string Key => _output.Key;
}
public class MatrixRouteRequest
{
[JsonProperty("outputKey")]
public string OutputKey { get; set; }
[JsonProperty("inputKey")]
public string InputKey { get; set; }
[JsonProperty("routeType")]
public eRoutingSignalType RouteType { get; set; }
}
}

View File

@@ -1,78 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IProjectorScreenLiftControlMessenger : MessengerBase
{
private readonly IProjectorScreenLiftControl device;
public IProjectorScreenLiftControlMessenger(string key, string messagePath, IProjectorScreenLiftControl screenLiftDevice)
: base(key, messagePath, screenLiftDevice as Device)
{
device = screenLiftDevice;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/raise", (id, content) =>
{
device.Raise();
});
AddAction("/lower", (id, content) =>
{
device.Lower();
});
device.PositionChanged += Device_PositionChanged;
}
private void Device_PositionChanged(object sender, EventArgs e)
{
var state = new
{
inUpPosition = device.InUpPosition
};
PostStatusMessage(JToken.FromObject(state));
}
private void SendFullStatus()
{
var state = new ScreenLiftStateMessage
{
InUpPosition = device.InUpPosition,
Type = device.Type,
DisplayDeviceKey = device.DisplayDeviceKey
};
PostStatusMessage(state);
}
}
public class ScreenLiftStateMessage : DeviceStateMessageBase
{
[JsonProperty("inUpPosition", NullValueHandling = NullValueHandling.Ignore)]
public bool? InUpPosition { get; set; }
[JsonProperty("displayDeviceKey", NullValueHandling = NullValueHandling.Ignore)]
public string DisplayDeviceKey { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
public eScreenLiftControlType Type { get; set; }
}
}

View File

@@ -1,84 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class RunRouteActionMessenger : MessengerBase
{
/// <summary>
/// Device being bridged
/// </summary>
public IRunRouteAction RoutingDevice { get; private set; }
public RunRouteActionMessenger(string key, IRunRouteAction routingDevice, string messagePath)
: base(key, messagePath, routingDevice as Device)
{
RoutingDevice = routingDevice ?? throw new ArgumentNullException("routingDevice");
if (RoutingDevice is IRoutingSink routingSink)
{
routingSink.CurrentSourceChange += RoutingSink_CurrentSourceChange;
}
}
private void RoutingSink_CurrentSourceChange(SourceListItem info, ChangeType type)
{
SendRoutingFullMessageObject();
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendRoutingFullMessageObject());
AddAction("/source", (id, content) =>
{
var c = content.ToObject<SourceSelectMessageContent>();
// assume no sourceListKey
var sourceListKey = string.Empty;
if (!string.IsNullOrEmpty(c.SourceListKey))
{
// Check for source list in content of message
sourceListKey = c.SourceListKey;
}
RoutingDevice.RunRouteAction(c.SourceListItemKey, sourceListKey);
});
if (RoutingDevice is IRoutingSink sinkDevice)
{
sinkDevice.CurrentSourceChange += (o, a) => SendRoutingFullMessageObject();
}
}
/// <summary>
/// Helper method to update full status of the routing device
/// </summary>
private void SendRoutingFullMessageObject()
{
if (RoutingDevice is IRoutingSink sinkDevice)
{
var sourceKey = sinkDevice.CurrentSourceInfoKey;
if (string.IsNullOrEmpty(sourceKey))
sourceKey = "none";
PostStatusMessage(new RoutingStateMessage
{
SelectedSourceKey = sourceKey
});
}
}
}
public class RoutingStateMessage : DeviceStateMessageBase
{
[JsonProperty("selectedSourceKey")]
public string SelectedSourceKey { get; set; }
}
}

View File

@@ -1,65 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ISelectableItemsMessenger<TKey> : MessengerBase
{
private static readonly JsonSerializer serializer = new JsonSerializer { Converters = { new StringEnumConverter() } };
private ISelectableItems<TKey> itemDevice;
private readonly string _propName;
public ISelectableItemsMessenger(string key, string messagePath, ISelectableItems<TKey> device, string propName) : base(key, messagePath, device as Device)
{
itemDevice = device;
_propName = propName;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, context) =>
{
SendFullStatus();
});
itemDevice.ItemsUpdated += (sender, args) =>
{
SendFullStatus();
};
itemDevice.CurrentItemChanged += (sender, args) =>
{
SendFullStatus();
};
foreach (var input in itemDevice.Items)
{
var key = input.Key;
var localItem = input.Value;
AddAction($"/{key}", (id, content) =>
{
localItem.Select();
});
localItem.ItemUpdated += (sender, args) =>
{
SendFullStatus();
};
}
}
private void SendFullStatus()
{
var stateObject = new JObject();
stateObject[_propName] = JToken.FromObject(itemDevice, serializer);
PostStatusMessage(stateObject);
}
}
}

View File

@@ -1,93 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IShutdownPromptTimerMessenger : MessengerBase
{
private readonly IShutdownPromptTimer _room;
public IShutdownPromptTimerMessenger(string key, string messagePath, IShutdownPromptTimer room)
: base(key, messagePath, room as Device)
{
_room = room;
}
protected override void RegisterActions()
{
AddAction("/status", (id, content) =>
{
SendFullStatus();
});
AddAction("/setShutdownPromptSeconds", (id, content) =>
{
var response = content.ToObject<int>();
_room.SetShutdownPromptSeconds(response);
SendFullStatus();
});
AddAction("/shutdownStart", (id, content) => _room.StartShutdown(eShutdownType.Manual));
AddAction("/shutdownEnd", (id, content) => _room.ShutdownPromptTimer.Finish());
AddAction("/shutdownCancel", (id, content) => _room.ShutdownPromptTimer.Cancel());
_room.ShutdownPromptTimer.HasStarted += (sender, args) =>
{
PostEventMessage("timerStarted");
};
_room.ShutdownPromptTimer.HasFinished += (sender, args) =>
{
PostEventMessage("timerFinished");
};
_room.ShutdownPromptTimer.WasCancelled += (sender, args) =>
{
PostEventMessage("timerCancelled");
};
_room.ShutdownPromptTimer.SecondsRemainingFeedback.OutputChange += (sender, args) =>
{
var status = new
{
secondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue,
percentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue
};
PostStatusMessage(JToken.FromObject(status));
};
}
private void SendFullStatus()
{
var status = new IShutdownPromptTimerStateMessage
{
ShutdownPromptSeconds = _room.ShutdownPromptTimer.SecondsToCount,
SecondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue,
PercentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue
};
PostStatusMessage(status);
}
}
public class IShutdownPromptTimerStateMessage : DeviceStateMessageBase
{
[JsonProperty("secondsRemaining")]
public int SecondsRemaining { get; set; }
[JsonProperty("percentageRemaining")]
public int PercentageRemaining { get; set; }
[JsonProperty("shutdownPromptSeconds")]
public int ShutdownPromptSeconds { get; set; }
}
}

View File

@@ -1,58 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.CrestronIO;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ISwitchedOutputMessenger : MessengerBase
{
private readonly ISwitchedOutput device;
public ISwitchedOutputMessenger(string key, ISwitchedOutput device, string messagePath)
: base(key, messagePath, device as Device)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/on", (id, content) =>
{
device.On();
});
AddAction("/off", (id, content) =>
{
device.Off();
});
device.OutputIsOnFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
}
private void SendFullStatus()
{
var state = new ISwitchedOutputStateMessage
{
IsOn = device.OutputIsOnFeedback.BoolValue
};
PostStatusMessage(state);
}
}
public class ISwitchedOutputStateMessage : DeviceStateMessageBase
{
[JsonProperty("isOn")]
public bool IsOn { get; set; }
}
}

View File

@@ -1,88 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ITechPasswordMessenger : MessengerBase
{
private readonly ITechPassword _room;
public ITechPasswordMessenger(string key, string messagePath, ITechPassword room)
: base(key, messagePath, room as Device)
{
_room = room;
}
protected override void RegisterActions()
{
AddAction("/status", (id, content) =>
{
SendFullStatus();
});
AddAction("/validateTechPassword", (id, content) =>
{
var password = content.Value<string>("password");
_room.ValidateTechPassword(password);
});
AddAction("/setTechPassword", (id, content) =>
{
var response = content.ToObject<SetTechPasswordContent>();
_room.SetTechPassword(response.OldPassword, response.NewPassword);
});
_room.TechPasswordChanged += (sender, args) =>
{
PostEventMessage("passwordChangedSuccessfully");
};
_room.TechPasswordValidateResult += (sender, args) =>
{
var evt = new ITechPasswordEventMessage
{
IsValid = args.IsValid
};
PostEventMessage(evt, "passwordValidationResult");
};
}
private void SendFullStatus()
{
var status = new ITechPasswordStateMessage
{
TechPasswordLength = _room.TechPasswordLength
};
PostStatusMessage(status);
}
}
public class ITechPasswordStateMessage : DeviceStateMessageBase
{
[JsonProperty("techPasswordLength", NullValueHandling = NullValueHandling.Ignore)]
public int? TechPasswordLength { get; set; }
}
public class ITechPasswordEventMessage : DeviceEventMessageBase
{
[JsonProperty("isValid", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsValid { get; set; }
}
internal class SetTechPasswordContent
{
[JsonProperty("oldPassword")]
public string OldPassword { get; set; }
[JsonProperty("newPassword")]
public string NewPassword { get; set; }
}
}

View File

@@ -1,61 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ITemperatureSensorMessenger : MessengerBase
{
private readonly ITemperatureSensor device;
public ITemperatureSensorMessenger(string key, ITemperatureSensor device, string messagePath)
: base(key, messagePath, device as Device)
{
this.device = device;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/setTemperatureUnitsToCelcius", (id, content) =>
{
device.SetTemperatureFormat(true);
});
AddAction("/setTemperatureUnitsToFahrenheit", (id, content) =>
{
device.SetTemperatureFormat(false);
});
device.TemperatureFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
device.TemperatureInCFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>((o, a) => SendFullStatus());
}
private void SendFullStatus()
{
// format the temperature to a string with one decimal place
var tempString = string.Format("{0}.{1}", device.TemperatureFeedback.UShortValue / 10, device.TemperatureFeedback.UShortValue % 10);
var state = new ITemperatureSensorStateMessage
{
Temperature = tempString,
TemperatureInCelsius = device.TemperatureInCFeedback.BoolValue
};
PostStatusMessage(state);
}
}
public class ITemperatureSensorStateMessage : DeviceStateMessageBase
{
[JsonProperty("temperature")]
public string Temperature { get; set; }
[JsonProperty("temperatureInCelsius")]
public bool TemperatureInCelsius { get; set; }
}
}

View File

@@ -1,66 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Lighting;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class ILightingScenesMessenger : MessengerBase
{
protected ILightingScenes Device { get; private set; }
public ILightingScenesMessenger(string key, ILightingScenes device, string messagePath)
: base(key, messagePath, device as Device)
{
Device = device ?? throw new ArgumentNullException("device");
Device.LightingSceneChange += new EventHandler<LightingSceneChangeEventArgs>(LightingDevice_LightingSceneChange);
}
private void LightingDevice_LightingSceneChange(object sender, LightingSceneChangeEventArgs e)
{
var state = new LightingBaseStateMessage
{
CurrentLightingScene = e.CurrentLightingScene
};
PostStatusMessage(state);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/selectScene", (id, content) =>
{
var s = content.ToObject<LightingScene>();
Device.SelectScene(s);
});
}
private void SendFullStatus()
{
var state = new LightingBaseStateMessage
{
Scenes = Device.LightingScenes,
CurrentLightingScene = Device.CurrentLightingScene
};
PostStatusMessage(state);
}
}
public class LightingBaseStateMessage : DeviceStateMessageBase
{
[JsonProperty("scenes", NullValueHandling = NullValueHandling.Ignore)]
public List<LightingScene> Scenes { get; set; }
[JsonProperty("currentLightingScene", NullValueHandling = NullValueHandling.Ignore)]
public LightingScene CurrentLightingScene { get; set; }
}
}

View File

@@ -1,288 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge
/// </summary>
public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger
{
protected IKeyName _device;
private readonly List<string> _deviceInterfaces;
private readonly Dictionary<string, Action<string, JToken>> _actions = new Dictionary<string, Action<string, JToken>>();
public string DeviceKey => _device?.Key ?? "";
/// <summary>
///
/// </summary>
public IMobileControl AppServerController { get; private set; }
public string MessagePath { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="messagePath"></param>
protected MessengerBase(string key, string messagePath)
: base(key)
{
Key = key;
if (string.IsNullOrEmpty(messagePath))
throw new ArgumentException("messagePath must not be empty or null");
MessagePath = messagePath;
}
protected MessengerBase(string key, string messagePath, IKeyName device)
: this(key, messagePath)
{
_device = device;
_deviceInterfaces = GetInterfaces(_device as Device);
}
/// <summary>
/// Gets the interfaces implmented on the device
/// </summary>
/// <param name="device"></param>
/// <returns></returns>
private List<string> GetInterfaces(Device device)
{
return device?.GetType().GetInterfaces().Select((i) => i.Name).ToList() ?? new List<string>();
}
/// <summary>
/// Registers this messenger with appserver controller
/// </summary>
/// <param name="appServerController"></param>
public void RegisterWithAppServer(IMobileControl appServerController)
{
AppServerController = appServerController ?? throw new ArgumentNullException("appServerController");
AppServerController.AddAction(this, HandleMessage);
RegisterActions();
}
private void HandleMessage(string path, string id, JToken content)
{
// replace base path with empty string. Should leave something like /fullStatus
var route = path.Replace(MessagePath, string.Empty);
if (!_actions.TryGetValue(route, out var action))
{
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Executing action for path {path}", this, path);
action(id, content);
}
protected void AddAction(string path, Action<string, JToken> action)
{
if (_actions.ContainsKey(path))
{
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Messenger {Key} already has action registered at {path}", this);
return;
}
_actions.Add(path, action);
}
public List<string> GetActionPaths()
{
return _actions.Keys.ToList();
}
protected void RemoveAction(string path)
{
if (!_actions.ContainsKey(path))
{
return;
}
_actions.Remove(path);
}
/// <summary>
/// Implemented in extending classes. Wire up API calls and feedback here
/// </summary>
/// <param name="appServerController"></param>
protected virtual void RegisterActions()
{
}
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="type"></param>
/// <param name="message"></param>
protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null)
{
try
{
if (message == null)
{
throw new ArgumentNullException("message");
}
if (_device == null)
{
throw new ArgumentNullException("device");
}
message.SetInterfaces(_deviceInterfaces);
message.Key = _device.Key;
message.Name = _device.Name;
PostStatusMessage(JToken.FromObject(message), MessagePath, clientId);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception posting status message", this);
}
}
protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null)
{
try
{
//Debug.Console(2, this, "*********************Setting DeviceStateMessageProperties on MobileControlResponseMessage");
deviceState.SetInterfaces(_deviceInterfaces);
deviceState.Key = _device.Key;
deviceState.Name = _device.Name;
deviceState.MessageBasePath = MessagePath;
PostStatusMessage(JToken.FromObject(deviceState), type, clientId);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception posting status message", this);
}
}
protected void PostStatusMessage(JToken content, string type = "", string clientId = null)
{
try
{
AppServerController?.SendMessageObject(new MobileControlMessage { Type = !string.IsNullOrEmpty(type) ? type : MessagePath, ClientId = clientId, Content = content });
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception posting status message", this);
}
}
protected void PostEventMessage(DeviceEventMessageBase message)
{
message.Key = _device.Key;
message.Name = _device.Name;
AppServerController?.SendMessageObject(new MobileControlMessage
{
Type = $"/event{MessagePath}/{message.EventType}",
Content = JToken.FromObject(message),
});
}
protected void PostEventMessage(DeviceEventMessageBase message, string eventType)
{
message.Key = _device.Key;
message.Name = _device.Name;
message.EventType = eventType;
AppServerController?.SendMessageObject(new MobileControlMessage
{
Type = $"/event{MessagePath}/{eventType}",
Content = JToken.FromObject(message),
});
}
protected void PostEventMessage(string eventType)
{
AppServerController?.SendMessageObject(new MobileControlMessage
{
Type = $"/event{MessagePath}/{eventType}",
Content = JToken.FromObject(new { }),
});
}
}
public abstract class DeviceMessageBase
{
/// <summary>
/// The device key
/// </summary>
[JsonProperty("key")]
public string Key { get; set; }
/// <summary>
/// The device name
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// The type of the message class
/// </summary>
[JsonProperty("messageType")]
public string MessageType => GetType().Name;
[JsonProperty("messageBasePath")]
public string MessageBasePath { get; set; }
}
/// <summary>
/// Base class for state messages that includes the type of message and the implmented interfaces
/// </summary>
public class DeviceStateMessageBase : DeviceMessageBase
{
/// <summary>
/// The interfaces implmented by the device sending the messsage
/// </summary>
[JsonProperty("interfaces")]
public List<string> Interfaces { get; private set; }
public void SetInterfaces(List<string> interfaces)
{
Interfaces = interfaces;
}
}
/// <summary>
/// Base class for event messages that include the type of message and an event type
/// </summary>
public abstract class DeviceEventMessageBase : DeviceMessageBase
{
/// <summary>
/// The event type
/// </summary>
[JsonProperty("eventType")]
public string EventType { get; set; }
}
}

View File

@@ -1,116 +0,0 @@
using Crestron.SimplSharp;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public static class PressAndHoldHandler
{
private const long ButtonHeartbeatInterval = 1000;
private static readonly Dictionary<string, CTimer> _pushedActions = new Dictionary<string, CTimer>();
private static readonly Dictionary<string, Action<string, Action<bool>>> _pushedActionHandlers;
static PressAndHoldHandler()
{
_pushedActionHandlers = new Dictionary<string, Action<string, Action<bool>>>
{
{"pressed", AddTimer },
{"held", ResetTimer },
{"released", StopTimer }
};
}
private static void AddTimer(string deviceKey, Action<bool> action)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to add timer for {deviceKey}", deviceKey);
if (_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} already exists", deviceKey);
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Adding timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval);
action(true);
cancelTimer = new CTimer(o =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer expired for {deviceKey}", deviceKey);
action(false);
_pushedActions.Remove(deviceKey);
}, ButtonHeartbeatInterval);
_pushedActions.Add(deviceKey, cancelTimer);
}
private static void ResetTimer(string deviceKey, Action<bool> action)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to reset timer for {deviceKey}", deviceKey);
if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey);
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Resetting timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval);
cancelTimer.Reset(ButtonHeartbeatInterval);
}
private static void StopTimer(string deviceKey, Action<bool> action)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to stop timer for {deviceKey}", deviceKey);
if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey);
return;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Stopping timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval);
action(false);
cancelTimer.Stop();
_pushedActions.Remove(deviceKey);
}
public static Action<string, Action<bool>> GetPressAndHoldHandler(string value)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting press and hold handler for {value}", value);
if (!_pushedActionHandlers.TryGetValue(value, out Action<string, Action<bool>> handler))
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Press and hold handler for {value} not found", value);
return null;
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Got handler for {value}", value);
return handler;
}
public static void HandlePressAndHold(string deviceKey, JToken content, Action<bool> action)
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Handling press and hold message of {type} for {deviceKey}", msg.Value, deviceKey);
var timerHandler = GetPressAndHoldHandler(msg.Value);
if (timerHandler == null)
{
return;
}
timerHandler(deviceKey, action);
}
}
}

View File

@@ -1,76 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class RoomEventScheduleMessenger : MessengerBase
{
private readonly IRoomEventSchedule _room;
public RoomEventScheduleMessenger(string key, string messagePath, IRoomEventSchedule room)
: base(key, messagePath, room as Device)
{
_room = room;
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
AddAction("/saveScheduledEvents", (id, content) => SaveScheduledEvents(content.ToObject<List<ScheduledEventConfig>>()));
AddAction("/status", (id, content) =>
{
var events = _room.GetScheduledEvents();
SendFullStatus(events);
});
_room.ScheduledEventsChanged += (sender, args) => SendFullStatus(args.ScheduledEvents);
}
#endregion
private void SaveScheduledEvents(List<ScheduledEventConfig> events)
{
foreach (var evt in events)
{
SaveScheduledEvent(evt);
}
}
private void SaveScheduledEvent(ScheduledEventConfig eventConfig)
{
try
{
_room.AddOrUpdateScheduledEvent(eventConfig);
}
catch (Exception ex)
{
this.LogException(ex,"Exception saving event");
}
}
private void SendFullStatus(List<ScheduledEventConfig> events)
{
var message = new RoomEventScheduleStateMessage
{
ScheduleEvents = events,
};
PostStatusMessage(message);
}
}
public class RoomEventScheduleStateMessage : DeviceStateMessageBase
{
[JsonProperty("scheduleEvents")]
public List<ScheduledEventConfig> ScheduleEvents { get; set; }
}
}

View File

@@ -1,158 +0,0 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
// ReSharper disable once InconsistentNaming
public class SIMPLAtcMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
public SIMPLAtcJoinMap JoinMap { get; private set; }
/// <summary>
///
/// </summary>
private readonly CodecActiveCallItem _currentCallItem;
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="eisc"></param>
/// <param name="messagePath"></param>
public SIMPLAtcMessenger(string key, BasicTriList eisc, string messagePath)
: base(key, messagePath)
{
_eisc = eisc;
JoinMap = new SIMPLAtcJoinMap(201);
_currentCallItem = new CodecActiveCallItem { Type = eCodecCallType.Audio, Id = "-audio-" };
}
/// <summary>
///
/// </summary>
private void SendFullStatus()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
currentCallString = _eisc.GetString(JoinMap.CurrentCallName.JoinNumber),
currentDialString = _eisc.GetString(JoinMap.CurrentDialString.JoinNumber),
isInCall = _eisc.GetString(JoinMap.HookState.JoinNumber) == "Connected"
})
);
}
/// <summary>
///
/// </summary>
/// <param name="appServerController"></param>
protected override void RegisterActions()
{
//EISC.SetStringSigAction(SCurrentDialString, s => PostStatusMessage(new { currentDialString = s }));
_eisc.SetStringSigAction(JoinMap.HookState.JoinNumber, s =>
{
_currentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
//GetCurrentCallList();
SendFullStatus();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallNumber.JoinNumber, s =>
{
_currentCallItem.Number = s;
SendCallsList();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallName.JoinNumber, s =>
{
_currentCallItem.Name = s;
SendCallsList();
});
_eisc.SetStringSigAction(JoinMap.CallDirection.JoinNumber, s =>
{
_currentCallItem.Direction = (eCodecCallDirection)Enum.Parse(typeof(eCodecCallDirection), s, true);
SendCallsList();
});
// Add press and holds using helper
//Action<string, uint> addPhAction = (s, u) =>
// AppServerController.AddAction(MessagePath + s, new PressAndHoldAction(b => _eisc.SetBool(u, b)));
// Add straight pulse calls
void addAction(string s, uint u) =>
AddAction(s, (id, content) => _eisc.PulseBool(u, 100));
addAction("/endCallById", JoinMap.EndCall.JoinNumber);
addAction("/endAllCalls", JoinMap.EndCall.JoinNumber);
addAction("/acceptById", JoinMap.IncomingAnswer.JoinNumber);
addAction("/rejectById", JoinMap.IncomingReject.JoinNumber);
var speeddialStart = JoinMap.SpeedDialStart.JoinNumber;
var speeddialEnd = JoinMap.SpeedDialStart.JoinNumber + JoinMap.SpeedDialStart.JoinSpan;
var speedDialIndex = 1;
for (uint i = speeddialStart; i < speeddialEnd; i++)
{
addAction(string.Format("/speedDial{0}", speedDialIndex), i);
speedDialIndex++;
}
// Get status
AddAction("/fullStatus", (id, content) => SendFullStatus());
// Dial on string
AddAction("/dial",
(id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.SetString(JoinMap.CurrentDialString.JoinNumber, msg.Value);
});
// Pulse DTMF
AddAction("/dtmf", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var join = JoinMap.Joins[s.Value];
if (join != null)
{
if (join.JoinNumber > 0)
{
_eisc.PulseBool(join.JoinNumber, 100);
}
}
});
}
/// <summary>
///
/// </summary>
private void SendCallsList()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
})
);
}
/// <summary>
/// Turns the
/// </summary>
/// <returns></returns>
private List<CodecActiveCallItem> GetCurrentCallList()
{
return _currentCallItem.Status == eCodecCallStatus.Disconnected
? new List<CodecActiveCallItem>()
: new List<CodecActiveCallItem> { _currentCallItem };
}
}
}

View File

@@ -1,161 +0,0 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common.Cameras;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
// ReSharper disable once InconsistentNaming
public class SIMPLCameraMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
private readonly CameraControllerJoinMap _joinMap;
public SIMPLCameraMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
: base(key, messagePath)
{
_eisc = eisc;
_joinMap = new CameraControllerJoinMap(joinStart);
_eisc.SetUShortSigAction(_joinMap.NumberOfPresets.JoinNumber, u => SendCameraFullMessageObject());
_eisc.SetBoolSigAction(_joinMap.CameraModeAuto.JoinNumber, b => PostCameraMode());
_eisc.SetBoolSigAction(_joinMap.CameraModeManual.JoinNumber, b => PostCameraMode());
_eisc.SetBoolSigAction(_joinMap.CameraModeOff.JoinNumber, b => PostCameraMode());
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject());
// Add press and holds using helper action
void addPhAction(string s, uint u) =>
AddAction(s, (id, content) => HandleCameraPressAndHold(content, b => _eisc.SetBool(u, b)));
addPhAction("/cameraUp", _joinMap.TiltUp.JoinNumber);
addPhAction("/cameraDown", _joinMap.TiltDown.JoinNumber);
addPhAction("/cameraLeft", _joinMap.PanLeft.JoinNumber);
addPhAction("/cameraRight", _joinMap.PanRight.JoinNumber);
addPhAction("/cameraZoomIn", _joinMap.ZoomIn.JoinNumber);
addPhAction("/cameraZoomOut", _joinMap.ZoomOut.JoinNumber);
void addAction(string s, uint u) =>
AddAction(s, (id, content) => _eisc.PulseBool(u, 100));
addAction("/cameraModeAuto", _joinMap.CameraModeAuto.JoinNumber);
addAction("/cameraModeManual", _joinMap.CameraModeManual.JoinNumber);
addAction("/cameraModeOff", _joinMap.CameraModeOff.JoinNumber);
var presetStart = _joinMap.PresetRecallStart.JoinNumber;
var presetEnd = _joinMap.PresetRecallStart.JoinNumber + _joinMap.PresetRecallStart.JoinSpan;
int presetId = 1;
// camera presets
for (uint i = presetStart; i <= presetEnd; i++)
{
addAction("/cameraPreset" + (presetId), i);
presetId++;
}
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
public void CustomUnregisterWithAppServer(IMobileControl appServerController)
{
appServerController.RemoveAction(MessagePath + "/fullStatus");
appServerController.RemoveAction(MessagePath + "/cameraUp");
appServerController.RemoveAction(MessagePath + "/cameraDown");
appServerController.RemoveAction(MessagePath + "/cameraLeft");
appServerController.RemoveAction(MessagePath + "/cameraRight");
appServerController.RemoveAction(MessagePath + "/cameraZoomIn");
appServerController.RemoveAction(MessagePath + "/cameraZoomOut");
appServerController.RemoveAction(MessagePath + "/cameraModeAuto");
appServerController.RemoveAction(MessagePath + "/cameraModeManual");
appServerController.RemoveAction(MessagePath + "/cameraModeOff");
_eisc.SetUShortSigAction(_joinMap.NumberOfPresets.JoinNumber, null);
_eisc.SetBoolSigAction(_joinMap.CameraModeAuto.JoinNumber, null);
_eisc.SetBoolSigAction(_joinMap.CameraModeManual.JoinNumber, null);
_eisc.SetBoolSigAction(_joinMap.CameraModeOff.JoinNumber, null);
}
/// <summary>
/// Helper method to update the full status of the camera
/// </summary>
private void SendCameraFullMessageObject()
{
var presetList = new List<CameraPreset>();
// Build a list of camera presets based on the names and count
if (_eisc.GetBool(_joinMap.SupportsPresets.JoinNumber))
{
var presetStart = _joinMap.PresetLabelStart.JoinNumber;
var presetEnd = _joinMap.PresetLabelStart.JoinNumber + _joinMap.NumberOfPresets.JoinNumber;
var presetId = 1;
for (uint i = presetStart; i < presetEnd; i++)
{
var presetName = _eisc.GetString(i);
var preset = new CameraPreset(presetId, presetName, string.IsNullOrEmpty(presetName), true);
presetList.Add(preset);
presetId++;
}
}
PostStatusMessage(JToken.FromObject(new
{
cameraMode = GetCameraMode(),
hasPresets = _eisc.GetBool(_joinMap.SupportsPresets.JoinNumber),
presets = presetList
})
);
}
/// <summary>
///
/// </summary>
private void PostCameraMode()
{
PostStatusMessage(JToken.FromObject(new
{
cameraMode = GetCameraMode()
}));
}
/// <summary>
/// Computes the current camera mode
/// </summary>
/// <returns></returns>
private string GetCameraMode()
{
string m;
if (_eisc.GetBool(_joinMap.CameraModeAuto.JoinNumber)) m = eCameraControlMode.Auto.ToString().ToLower();
else if (_eisc.GetBool(_joinMap.CameraModeManual.JoinNumber))
m = eCameraControlMode.Manual.ToString().ToLower();
else m = eCameraControlMode.Off.ToString().ToLower();
return m;
}
}
}

View File

@@ -1,127 +0,0 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SimplDirectRouteMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
public MobileControlSIMPLRunDirectRouteActionJoinMap JoinMap { get; private set; }
public Dictionary<string, DestinationListItem> DestinationList { get; set; }
public SimplDirectRouteMessenger(string key, BasicTriList eisc, string messagePath) : base(key, messagePath)
{
_eisc = eisc;
JoinMap = new MobileControlSIMPLRunDirectRouteActionJoinMap(851);
DestinationList = new Dictionary<string, DestinationListItem>();
}
#region Overrides of MessengerBase
protected override void RegisterActions()
{
Debug.Console(2, "********** Direct Route Messenger CustomRegisterWithAppServer **********");
//Audio source
_eisc.SetStringSigAction(JoinMap.SourceForDestinationAudio.JoinNumber,
s => PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = s,
})
));
AddAction("/programAudio/selectSource", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.StringInput[JoinMap.SourceForDestinationAudio.JoinNumber].StringValue = msg.Value;
});
AddAction("/fullStatus", (id, content) =>
{
foreach (var dest in DestinationList)
{
var key = dest.Key;
var item = dest.Value;
var source =
_eisc.StringOutput[(uint)(JoinMap.SourceForDestinationJoinStart.JoinNumber + item.Order)].StringValue;
UpdateSourceForDestination(source, key);
}
PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = _eisc.StringOutput[JoinMap.SourceForDestinationAudio.JoinNumber].StringValue
})
);
PostStatusMessage(JToken.FromObject(new
{
advancedSharingActive = _eisc.BooleanOutput[JoinMap.AdvancedSharingModeFb.JoinNumber].BoolValue
})
);
});
AddAction("/advancedSharingMode", (id, content) =>
{
var b = content.ToObject<MobileControlSimpleContent<bool>>();
Debug.Console(1, "Current Sharing Mode: {2}\r\nadvanced sharing mode: {0} join number: {1}", b.Value,
JoinMap.AdvancedSharingModeOn.JoinNumber,
_eisc.BooleanOutput[JoinMap.AdvancedSharingModeOn.JoinNumber].BoolValue);
_eisc.SetBool(JoinMap.AdvancedSharingModeOn.JoinNumber, b.Value);
_eisc.SetBool(JoinMap.AdvancedSharingModeOff.JoinNumber, !b.Value);
_eisc.PulseBool(JoinMap.AdvancedSharingModeToggle.JoinNumber);
});
_eisc.SetBoolSigAction(JoinMap.AdvancedSharingModeFb.JoinNumber,
(b) => PostStatusMessage(JToken.FromObject(new
{
advancedSharingActive = b
})
));
}
public void RegisterForDestinationPaths()
{
//handle routing feedback from SIMPL
foreach (var destination in DestinationList)
{
var key = destination.Key;
var dest = destination.Value;
_eisc.SetStringSigAction((uint)(JoinMap.SourceForDestinationJoinStart.JoinNumber + dest.Order),
s => UpdateSourceForDestination(s, key));
AddAction($"/{key}/selectSource", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.StringInput[(uint)(JoinMap.SourceForDestinationJoinStart.JoinNumber + dest.Order)].StringValue = s.Value;
});
}
}
#endregion
private void UpdateSourceForDestination(string sourceKey, string destKey)
{
PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = sourceKey
}), $"{MessagePath}/{destKey}/currentSource");
}
}
}

View File

@@ -1,69 +0,0 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SIMPLRouteMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
private readonly uint _joinStart;
public class StringJoin
{
/// <summary>
/// 1
/// </summary>
public const uint CurrentSource = 1;
}
public SIMPLRouteMessenger(string key, BasicTriList eisc, string messagePath, uint joinStart)
: base(key, messagePath)
{
_eisc = eisc;
_joinStart = joinStart - 1;
_eisc.SetStringSigAction(_joinStart + StringJoin.CurrentSource, SendRoutingFullMessageObject);
}
protected override void RegisterActions()
{
AddAction("/fullStatus",
(id, content) => SendRoutingFullMessageObject(_eisc.GetString(_joinStart + StringJoin.CurrentSource)));
AddAction("/source", (id, content) =>
{
var c = content.ToObject<SourceSelectMessageContent>();
_eisc.SetString(_joinStart + StringJoin.CurrentSource, c.SourceListItemKey);
});
}
public void CustomUnregisterWithAppServer(IMobileControl appServerController)
{
appServerController.RemoveAction(MessagePath + "/fullStatus");
appServerController.RemoveAction(MessagePath + "/source");
_eisc.SetStringSigAction(_joinStart + StringJoin.CurrentSource, null);
}
/// <summary>
/// Helper method to update full status of the routing device
/// </summary>
private void SendRoutingFullMessageObject(string sourceKey)
{
if (string.IsNullOrEmpty(sourceKey))
sourceKey = "none";
PostStatusMessage(JToken.FromObject(new
{
selectedSourceKey = sourceKey
})
);
}
}
}

View File

@@ -1,475 +0,0 @@
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
// ReSharper disable once InconsistentNaming
public class SIMPLVtcMessenger : MessengerBase
{
private readonly BasicTriList _eisc;
public SIMPLVtcJoinMap JoinMap { get; private set; }
private readonly CodecActiveCallItem _currentCallItem;
private CodecActiveCallItem _incomingCallItem;
private ushort _previousDirectoryLength = 701;
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="eisc"></param>
/// <param name="messagePath"></param>
public SIMPLVtcMessenger(string key, BasicTriList eisc, string messagePath)
: base(key, messagePath)
{
_eisc = eisc;
JoinMap = new SIMPLVtcJoinMap(1001);
_currentCallItem = new CodecActiveCallItem { Type = eCodecCallType.Video, Id = "-video-" };
}
/// <summary>
///
/// </summary>
/// <param name="appServerController"></param>
protected override void RegisterActions()
{
_eisc.SetStringSigAction(JoinMap.HookState.JoinNumber, s =>
{
_currentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
PostFullStatus(); // SendCallsList();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallNumber.JoinNumber, s =>
{
_currentCallItem.Number = s;
PostCallsList();
});
_eisc.SetStringSigAction(JoinMap.CurrentCallName.JoinNumber, s =>
{
_currentCallItem.Name = s;
PostCallsList();
});
_eisc.SetStringSigAction(JoinMap.CallDirection.JoinNumber, s =>
{
_currentCallItem.Direction = (eCodecCallDirection)Enum.Parse(typeof(eCodecCallDirection), s, true);
PostCallsList();
});
_eisc.SetBoolSigAction(JoinMap.IncomingCall.JoinNumber, b =>
{
if (b)
{
var ica = new CodecActiveCallItem
{
Direction = eCodecCallDirection.Incoming,
Id = "-video-incoming",
Name = _eisc.GetString(JoinMap.IncomingCallName.JoinNumber),
Number = _eisc.GetString(JoinMap.IncomingCallNumber.JoinNumber),
Status = eCodecCallStatus.Ringing,
Type = eCodecCallType.Video
};
_incomingCallItem = ica;
}
else
{
_incomingCallItem = null;
}
PostCallsList();
});
_eisc.SetStringSigAction(JoinMap.IncomingCallName.JoinNumber, s =>
{
if (_incomingCallItem != null)
{
_incomingCallItem.Name = s;
PostCallsList();
}
});
_eisc.SetStringSigAction(JoinMap.IncomingCallNumber.JoinNumber, s =>
{
if (_incomingCallItem != null)
{
_incomingCallItem.Number = s;
PostCallsList();
}
});
_eisc.SetBoolSigAction(JoinMap.CameraSupportsAutoMode.JoinNumber, b => PostStatusMessage(JToken.FromObject(new
{
cameraSupportsAutoMode = b
})));
_eisc.SetBoolSigAction(JoinMap.CameraSupportsOffMode.JoinNumber, b => PostStatusMessage(JToken.FromObject(new
{
cameraSupportsOffMode = b
})));
// Directory insanity
_eisc.SetUShortSigAction(JoinMap.DirectoryRowCount.JoinNumber, u =>
{
// The length of the list comes in before the list does.
// Splice the sig change operation onto the last string sig that will be changing
// when the directory entries make it through.
if (_previousDirectoryLength > 0)
{
_eisc.ClearStringSigAction(JoinMap.DirectoryEntriesStart.JoinNumber + _previousDirectoryLength - 1);
}
_eisc.SetStringSigAction(JoinMap.DirectoryEntriesStart.JoinNumber + u - 1, s => PostDirectory());
_previousDirectoryLength = u;
});
_eisc.SetStringSigAction(JoinMap.DirectoryEntrySelectedName.JoinNumber, s => PostStatusMessage(JToken.FromObject(new
{
directoryContactSelected = new
{
name = _eisc.GetString(JoinMap.DirectoryEntrySelectedName.JoinNumber),
}
})));
_eisc.SetStringSigAction(JoinMap.DirectoryEntrySelectedNumber.JoinNumber, s => PostStatusMessage(JToken.FromObject(new
{
directoryContactSelected = new
{
number = _eisc.GetString(JoinMap.DirectoryEntrySelectedNumber.JoinNumber),
}
})));
_eisc.SetStringSigAction(JoinMap.DirectorySelectedFolderName.JoinNumber, s => PostStatusMessage(JToken.FromObject(new
{
directorySelectedFolderName = _eisc.GetString(JoinMap.DirectorySelectedFolderName.JoinNumber)
})));
_eisc.SetSigTrueAction(JoinMap.CameraModeAuto.JoinNumber, PostCameraMode);
_eisc.SetSigTrueAction(JoinMap.CameraModeManual.JoinNumber, PostCameraMode);
_eisc.SetSigTrueAction(JoinMap.CameraModeOff.JoinNumber, PostCameraMode);
_eisc.SetBoolSigAction(JoinMap.CameraSelfView.JoinNumber, b => PostStatusMessage(JToken.FromObject(new
{
cameraSelfView = b
})));
_eisc.SetUShortSigAction(JoinMap.CameraNumberSelect.JoinNumber, u => PostSelectedCamera());
// Add press and holds using helper action
void addPhAction(string s, uint u) =>
AddAction(s, (id, content) => HandleCameraPressAndHold(content, b => _eisc.SetBool(u, b)));
addPhAction("/cameraUp", JoinMap.CameraTiltUp.JoinNumber);
addPhAction("/cameraDown", JoinMap.CameraTiltDown.JoinNumber);
addPhAction("/cameraLeft", JoinMap.CameraPanLeft.JoinNumber);
addPhAction("/cameraRight", JoinMap.CameraPanRight.JoinNumber);
addPhAction("/cameraZoomIn", JoinMap.CameraZoomIn.JoinNumber);
addPhAction("/cameraZoomOut", JoinMap.CameraZoomOut.JoinNumber);
// Add straight pulse calls using helper action
void addAction(string s, uint u) =>
AddAction(s, (id, content) => _eisc.PulseBool(u, 100));
addAction("/endCallById", JoinMap.EndCall.JoinNumber);
addAction("/endAllCalls", JoinMap.EndCall.JoinNumber);
addAction("/acceptById", JoinMap.IncomingAnswer.JoinNumber);
addAction("/rejectById", JoinMap.IncomingReject.JoinNumber);
var speeddialStart = JoinMap.SpeedDialStart.JoinNumber;
var speeddialEnd = JoinMap.SpeedDialStart.JoinNumber + JoinMap.SpeedDialStart.JoinSpan;
var speedDialIndex = 1;
for (uint i = speeddialStart; i < speeddialEnd; i++)
{
addAction(string.Format("/speedDial{0}", speedDialIndex), i);
speedDialIndex++;
}
addAction("/cameraModeAuto", JoinMap.CameraModeAuto.JoinNumber);
addAction("/cameraModeManual", JoinMap.CameraModeManual.JoinNumber);
addAction("/cameraModeOff", JoinMap.CameraModeOff.JoinNumber);
addAction("/cameraSelfView", JoinMap.CameraSelfView.JoinNumber);
addAction("/cameraLayout", JoinMap.CameraLayout.JoinNumber);
AddAction("/cameraSelect", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
SelectCamera(s.Value);
});
// camera presets
for (uint i = 0; i < 6; i++)
{
addAction("/cameraPreset" + (i + 1), JoinMap.CameraPresetStart.JoinNumber + i);
}
AddAction("/isReady", (id, content) => PostIsReady());
// Get status
AddAction("/fullStatus", (id, content) => PostFullStatus());
// Dial on string
AddAction("/dial", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
_eisc.SetString(JoinMap.CurrentDialString.JoinNumber, s.Value);
});
// Pulse DTMF
AddAction("/dtmf", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var join = JoinMap.Joins[s.Value];
if (join != null)
{
if (join.JoinNumber > 0)
{
_eisc.PulseBool(join.JoinNumber, 100);
}
}
});
// Directory madness
AddAction("/directoryRoot",
(id, content) => _eisc.PulseBool(JoinMap.DirectoryRoot.JoinNumber));
AddAction("/directoryBack",
(id, content) => _eisc.PulseBool(JoinMap.DirectoryFolderBack.JoinNumber));
AddAction("/directoryById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
// the id should contain the line number to forward to simpl
try
{
var u = ushort.Parse(s.Value);
_eisc.SetUshort(JoinMap.DirectorySelectRow.JoinNumber, u);
_eisc.PulseBool(JoinMap.DirectoryLineSelected.JoinNumber);
}
catch (Exception)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Warning,
"/directoryById request contains non-numeric ID incompatible with SIMPL bridge");
}
});
AddAction("/directorySelectContact", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
try
{
var u = ushort.Parse(s.Value);
_eisc.SetUshort(JoinMap.DirectorySelectRow.JoinNumber, u);
_eisc.PulseBool(JoinMap.DirectoryLineSelected.JoinNumber);
}
catch
{
Debug.Console(2, this, "Error parsing contact from {0} for path /directorySelectContact", s);
}
});
AddAction("/directoryDialContact",
(id, content) => _eisc.PulseBool(JoinMap.DirectoryDialSelectedLine.JoinNumber));
AddAction("/getDirectory", (id, content) =>
{
if (_eisc.GetUshort(JoinMap.DirectoryRowCount.JoinNumber) > 0)
{
PostDirectory();
}
else
{
_eisc.PulseBool(JoinMap.DirectoryRoot.JoinNumber);
}
});
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
///
/// </summary>
///
private void PostFullStatus()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
cameraMode = GetCameraMode(),
cameraSelfView = _eisc.GetBool(JoinMap.CameraSelfView.JoinNumber),
cameraSupportsAutoMode = _eisc.GetBool(JoinMap.CameraSupportsAutoMode.JoinNumber),
cameraSupportsOffMode = _eisc.GetBool(JoinMap.CameraSupportsOffMode.JoinNumber),
currentCallString = _eisc.GetString(JoinMap.CurrentCallNumber.JoinNumber),
currentDialString = _eisc.GetString(JoinMap.CurrentDialString.JoinNumber),
directoryContactSelected = new
{
name = _eisc.GetString(JoinMap.DirectoryEntrySelectedName.JoinNumber),
number = _eisc.GetString(JoinMap.DirectoryEntrySelectedNumber.JoinNumber)
},
directorySelectedFolderName = _eisc.GetString(JoinMap.DirectorySelectedFolderName.JoinNumber),
isInCall = _eisc.GetString(JoinMap.HookState.JoinNumber) == "Connected",
hasDirectory = true,
hasDirectorySearch = false,
hasRecents = !_eisc.BooleanOutput[502].BoolValue,
hasCameras = true,
showCamerasWhenNotInCall = _eisc.BooleanOutput[503].BoolValue,
selectedCamera = GetSelectedCamera(),
}));
}
/// <summary>
///
/// </summary>
private void PostDirectory()
{
var u = _eisc.GetUshort(JoinMap.DirectoryRowCount.JoinNumber);
var items = new List<object>();
for (uint i = 0; i < u; i++)
{
var name = _eisc.GetString(JoinMap.DirectoryEntriesStart.JoinNumber + i);
var id = (i + 1).ToString();
// is folder or contact?
if (name.StartsWith("[+]"))
{
items.Add(new
{
folderId = id,
name
});
}
else
{
items.Add(new
{
contactId = id,
name
});
}
}
var directoryMessage = new
{
currentDirectory = new
{
isRootDirectory = _eisc.GetBool(JoinMap.DirectoryIsRoot.JoinNumber),
directoryResults = items
}
};
PostStatusMessage(JToken.FromObject(directoryMessage));
}
/// <summary>
///
/// </summary>
private void PostCameraMode()
{
PostStatusMessage(JToken.FromObject(new
{
cameraMode = GetCameraMode()
}));
}
/// <summary>
///
/// </summary>
private string GetCameraMode()
{
string m;
if (_eisc.GetBool(JoinMap.CameraModeAuto.JoinNumber)) m = eCameraControlMode.Auto.ToString().ToLower();
else if (_eisc.GetBool(JoinMap.CameraModeManual.JoinNumber))
m = eCameraControlMode.Manual.ToString().ToLower();
else m = eCameraControlMode.Off.ToString().ToLower();
return m;
}
private void PostSelectedCamera()
{
PostStatusMessage(JToken.FromObject(new
{
selectedCamera = GetSelectedCamera()
}));
}
/// <summary>
///
/// </summary>
private string GetSelectedCamera()
{
var num = _eisc.GetUshort(JoinMap.CameraNumberSelect.JoinNumber);
string m;
if (num == 100)
{
m = "cameraFar";
}
else
{
m = "camera" + num;
}
return m;
}
/// <summary>
///
/// </summary>
private void PostIsReady()
{
PostStatusMessage(JToken.FromObject(new
{
isReady = true
}));
}
/// <summary>
///
/// </summary>
private void PostCallsList()
{
PostStatusMessage(JToken.FromObject(new
{
calls = GetCurrentCallList(),
}));
}
/// <summary>
///
/// </summary>
/// <param name="s"></param>
private void SelectCamera(string s)
{
var cam = s.Substring(6);
_eisc.SetUshort(JoinMap.CameraNumberSelect.JoinNumber,
(ushort)(cam.ToLower() == "far" ? 100 : ushort.Parse(cam)));
}
/// <summary>
/// Turns the
/// </summary>
/// <returns></returns>
private List<CodecActiveCallItem> GetCurrentCallList()
{
var list = new List<CodecActiveCallItem>();
if (_currentCallItem.Status != eCodecCallStatus.Disconnected)
{
list.Add(_currentCallItem);
}
if (_eisc.GetBool(JoinMap.IncomingCall.JoinNumber))
{
list.Add(_incomingCallItem);
}
return list;
}
}
}

View File

@@ -1,100 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Shades;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class IShadesOpenCloseStopMessenger : MessengerBase
{
private readonly IShadesOpenCloseStop device;
public IShadesOpenCloseStopMessenger(string key, IShadesOpenCloseStop shades, string messagePath)
: base(key, messagePath, shades as Device)
{
device = shades;
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/shadeUp", (id, content) =>
{
device.Open();
});
AddAction("/shadeDown", (id, content) =>
{
device.Close();
});
var stopDevice = device;
if (stopDevice != null)
{
AddAction("/stopOrPreset", (id, content) =>
{
stopDevice.Stop();
});
}
if (device is IShadesOpenClosedFeedback feedbackDevice)
{
feedbackDevice.ShadeIsOpenFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>(ShadeIsOpenFeedback_OutputChange);
feedbackDevice.ShadeIsClosedFeedback.OutputChange += new EventHandler<Core.FeedbackEventArgs>(ShadeIsClosedFeedback_OutputChange);
}
}
private void ShadeIsOpenFeedback_OutputChange(object sender, Core.FeedbackEventArgs e)
{
var state = new ShadeBaseStateMessage
{
IsOpen = e.BoolValue
};
PostStatusMessage(state);
}
private void ShadeIsClosedFeedback_OutputChange(object sender, Core.FeedbackEventArgs e)
{
var state = new ShadeBaseStateMessage
{
IsClosed = e.BoolValue
};
PostStatusMessage(state);
}
private void SendFullStatus()
{
var state = new ShadeBaseStateMessage();
if (device is IShadesOpenClosedFeedback feedbackDevice)
{
state.IsOpen = feedbackDevice.ShadeIsOpenFeedback.BoolValue;
state.IsClosed = feedbackDevice.ShadeIsClosedFeedback.BoolValue;
}
PostStatusMessage(state);
}
}
public class ShadeBaseStateMessage : DeviceStateMessageBase
{
[JsonProperty("middleButtonLabel", NullValueHandling = NullValueHandling.Ignore)]
public string MiddleButtonLabel { get; set; }
[JsonProperty("isOpen", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOpen { get; set; }
[JsonProperty("isClosed", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsClosed { get; set; }
}
}

View File

@@ -1,11 +0,0 @@
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Properties to configure a SIMPL Messenger
/// </summary>
public class SimplMessengerPropertiesConfig : EiscApiPropertiesConfig.ApiDevicePropertiesConfig
{
}
}

View File

@@ -1,109 +0,0 @@
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core.Monitoring;
using System;
using System.Threading.Tasks;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class SystemMonitorMessenger : MessengerBase
{
private readonly SystemMonitorController systemMonitor;
public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath)
: base(key, messagePath, sysMon)
{
systemMonitor = sysMon ?? throw new ArgumentNullException("sysMon");
systemMonitor.SystemMonitorPropertiesChanged += SysMon_SystemMonitorPropertiesChanged;
foreach (var p in systemMonitor.ProgramStatusFeedbackCollection)
{
p.Value.ProgramInfoChanged += ProgramInfoChanged;
}
CrestronConsole.AddNewConsoleCommand(s => SendFullStatusMessage(), "SendFullSysMonStatus",
"Sends the full System Monitor Status", ConsoleAccessLevelEnum.AccessOperator);
}
/// <summary>
/// Posts the program information message
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ProgramInfoChanged(object sender, ProgramInfoEventArgs e)
{
if (e.ProgramInfo != null)
{
//Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString());
PostStatusMessage(JToken.FromObject(e.ProgramInfo)
);
}
}
/// <summary>
/// Posts the system monitor properties
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SysMon_SystemMonitorPropertiesChanged(object sender, EventArgs e)
{
SendSystemMonitorStatusMessage();
}
private void SendFullStatusMessage()
{
SendSystemMonitorStatusMessage();
foreach (var p in systemMonitor.ProgramStatusFeedbackCollection)
{
PostStatusMessage(JToken.FromObject(p.Value.ProgramInfo));
}
}
private void SendSystemMonitorStatusMessage()
{
// This takes a while, launch a new thread
Task.Run(() => PostStatusMessage(JToken.FromObject(new SystemMonitorStateMessage
{
TimeZone = systemMonitor.TimeZoneFeedback.IntValue,
TimeZoneName = systemMonitor.TimeZoneTextFeedback.StringValue,
IoControllerVersion = systemMonitor.IoControllerVersionFeedback.StringValue,
SnmpVersion = systemMonitor.SnmpVersionFeedback.StringValue,
BacnetVersion = systemMonitor.BaCnetAppVersionFeedback.StringValue,
ControllerVersion = systemMonitor.ControllerVersionFeedback.StringValue
})
));
}
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendFullStatusMessage());
}
}
public class SystemMonitorStateMessage
{
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public int TimeZone { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string TimeZoneName { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string IoControllerVersion { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string SnmpVersion { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string BacnetVersion { get; set; }
[JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)]
public string ControllerVersion { get; set; }
}
}

View File

@@ -1,97 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Displays;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class TwoWayDisplayBaseMessenger : MessengerBase
{
private readonly TwoWayDisplayBase _display;
public TwoWayDisplayBaseMessenger(string key, string messagePath) : base(key, messagePath)
{
}
public TwoWayDisplayBaseMessenger(string key, string messagePath, TwoWayDisplayBase display)
: this(key, messagePath)
{
_display = display;
}
#region Overrides of MessengerBase
public void SendFullStatus()
{
var messageObj = new TwoWayDisplayBaseStateMessage
{
//PowerState = _display.PowerIsOnFeedback.BoolValue,
CurrentInput = _display.CurrentInputFeedback.StringValue
};
PostStatusMessage(messageObj);
}
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, content) => SendFullStatus());
//_display.PowerIsOnFeedback.OutputChange += PowerIsOnFeedbackOnOutputChange;
_display.CurrentInputFeedback.OutputChange += CurrentInputFeedbackOnOutputChange;
_display.IsCoolingDownFeedback.OutputChange += IsCoolingFeedbackOnOutputChange;
_display.IsWarmingUpFeedback.OutputChange += IsWarmingFeedbackOnOutputChange;
}
private void CurrentInputFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
PostStatusMessage(JToken.FromObject(new
{
currentInput = feedbackEventArgs.StringValue
})
);
}
//private void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
//{
// PostStatusMessage(JToken.FromObject(new
// {
// powerState = feedbackEventArgs.BoolValue
// })
// );
//}
private void IsWarmingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
PostStatusMessage(JToken.FromObject(new
{
isWarming = feedbackEventArgs.BoolValue
})
);
}
private void IsCoolingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs)
{
PostStatusMessage(JToken.FromObject(new
{
isCooling = feedbackEventArgs.BoolValue
})
);
}
#endregion
}
public class TwoWayDisplayBaseStateMessage : DeviceStateMessageBase
{
//[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)]
//public bool? PowerState { get; set; }
[JsonProperty("currentInput", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentInput { get; set; }
}
}

View File

@@ -1,999 +0,0 @@
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using static PepperDash.Essentials.AppServer.Messengers.VideoCodecBaseStateMessage.CameraStatus;
namespace PepperDash.Essentials.AppServer.Messengers
{
/// <summary>
/// Provides a messaging bridge for a VideoCodecBase device
/// </summary>
public class VideoCodecBaseMessenger : MessengerBase
{
/// <summary>
///
/// </summary>
protected VideoCodecBase Codec { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="codec"></param>
/// <param name="messagePath"></param>
public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath)
: base(key, messagePath, codec)
{
Codec = codec ?? throw new ArgumentNullException("codec");
codec.CallStatusChange += Codec_CallStatusChange;
codec.IsReadyChange += Codec_IsReadyChange;
if (codec is IHasDirectory dirCodec)
{
dirCodec.DirectoryResultReturned += DirCodec_DirectoryResultReturned;
}
if (codec is IHasCallHistory recCodec)
{
recCodec.CallHistory.RecentCallsListHasChanged += CallHistory_RecentCallsListHasChanged;
}
if (codec is IPasswordPrompt pwPromptCodec)
{
pwPromptCodec.PasswordRequired += OnPasswordRequired;
}
}
private void OnPasswordRequired(object sender, PasswordPromptEventArgs args)
{
var eventMsg = new PasswordPromptEventMessage
{
Message = args.Message,
LastAttemptWasIncorrect = args.LastAttemptWasIncorrect,
LoginAttemptFailed = args.LoginAttemptFailed,
LoginAttemptCancelled = args.LoginAttemptCancelled,
EventType = "passwordPrompt"
};
PostEventMessage(eventMsg);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e)
{
var state = new VideoCodecBaseStateMessage();
if (!(sender is CodecCallHistory codecCallHistory)) return;
var recents = codecCallHistory.RecentCalls;
if (recents != null)
{
state.RecentCalls = recents;
PostStatusMessage(state);
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
{
if (Codec is IHasDirectory)
SendDirectory(e.Directory);
}
/// <summary>
/// Posts the current directory
/// </summary>
protected void SendDirectory(CodecDirectory directory)
{
var state = new VideoCodecBaseStateMessage();
if (Codec is IHasDirectory dirCodec)
{
this.LogVerbose("Sending Directory. Directory Item Count: {directoryItemCount}", directory.CurrentDirectoryResults.Count);
//state.CurrentDirectory = PrefixDirectoryFolderItems(directory);
state.CurrentDirectory = directory;
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(state));
/* var directoryMessage = new
{
currentDirectory = new
{
directoryResults = prefixedDirectoryResults,
isRootDirectory = isRoot
}
};
//Spool up a thread in case this is a large quantity of data
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(directoryMessage)); */
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Codec_IsReadyChange(object sender, EventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
IsReady = true
};
PostStatusMessage(state);
SendFullStatus();
}
/// <summary>
/// Called from base's RegisterWithAppServer method
/// </summary>
/// <param name="appServerController"></param>
protected override void RegisterActions()
{
try
{
base.RegisterActions();
AddAction("/isReady", (id, content) => SendIsReady());
AddAction("/fullStatus", (id, content) => SendFullStatus());
AddAction("/dial", (id, content) =>
{
var value = content.ToObject<MobileControlSimpleContent<string>>();
Codec.Dial(value.Value);
});
AddAction("/dialMeeting", (id, content) => Codec.Dial(content.ToObject<Meeting>()));
AddAction("/endCallById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(s.Value);
if (call != null)
Codec.EndCall(call);
});
AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls());
AddAction("/dtmf", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
Codec.SendDtmf(s.Value);
});
AddAction("/rejectById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(s.Value);
if (call != null)
Codec.RejectCall(call);
});
AddAction("/acceptById", (id, content) =>
{
var s = content.ToObject<MobileControlSimpleContent<string>>();
var call = GetCallWithId(s.Value);
if (call != null)
Codec.AcceptCall(call);
});
Codec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange;
Codec.SharingSourceFeedback.OutputChange += SharingSourceFeedback_OutputChange;
// Directory actions
if (Codec is IHasDirectory dirCodec)
{
AddAction("/getDirectory", (id, content) => GetDirectoryRoot());
AddAction("/directoryById", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
GetDirectory(msg.Value);
});
AddAction("/directorySearch", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
GetDirectory(msg.Value);
});
AddAction("/directoryBack", (id, content) => GetPreviousDirectory());
dirCodec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
}
// History actions
if (Codec is IHasCallHistory recCodec)
{
AddAction("/getCallHistory", (id, content) => PostCallHistory());
}
if (Codec is IHasCodecCameras cameraCodec)
{
this.LogVerbose("Adding IHasCodecCameras Actions");
cameraCodec.CameraSelected += CameraCodec_CameraSelected;
AddAction("/cameraSelect", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
cameraCodec.SelectCamera(msg.Value);
});
MapCameraActions();
if (Codec is IHasCodecRoomPresets presetsCodec)
{
this.LogVerbose("Adding IHasCodecRoomPresets Actions");
presetsCodec.CodecRoomPresetsListHasChanged += PresetsCodec_CameraPresetsListHasChanged;
AddAction("/cameraPreset", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<int>>();
presetsCodec.CodecRoomPresetSelect(msg.Value);
});
AddAction("/cameraPresetStore", (id, content) =>
{
var msg = content.ToObject<CodecRoomPreset>();
presetsCodec.CodecRoomPresetStore(msg.ID, msg.Description);
});
}
if (Codec is IHasCameraAutoMode speakerTrackCodec)
{
this.LogVerbose("Adding IHasCameraAutoMode Actions");
speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += CameraAutoModeIsOnFeedback_OutputChange;
AddAction("/cameraModeAuto", (id, content) => speakerTrackCodec.CameraAutoModeOn());
AddAction("/cameraModeManual", (id, content) => speakerTrackCodec.CameraAutoModeOff());
}
if (Codec is IHasCameraOff cameraOffCodec)
{
this.LogVerbose("Adding IHasCameraOff Actions");
cameraOffCodec.CameraIsOffFeedback.OutputChange += (CameraIsOffFeedback_OutputChange);
AddAction("/cameraModeOff", (id, content) => cameraOffCodec.CameraOff());
}
}
if (Codec is IHasCodecSelfView selfViewCodec)
{
this.LogVerbose("Adding IHasCodecSelfView Actions");
AddAction("/cameraSelfView", (id, content) => selfViewCodec.SelfViewModeToggle());
selfViewCodec.SelfviewIsOnFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(SelfviewIsOnFeedback_OutputChange);
}
if (Codec is IHasCodecLayouts layoutsCodec)
{
this.LogVerbose("Adding IHasCodecLayouts Actions");
AddAction("/cameraRemoteView", (id, content) => layoutsCodec.LocalLayoutToggle());
AddAction("/cameraLayout", (id, content) => layoutsCodec.LocalLayoutToggle());
}
if (Codec is IPasswordPrompt pwCodec)
{
this.LogVerbose("Adding IPasswordPrompt Actions");
AddAction("/password", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<string>>();
pwCodec.SubmitPassword(msg.Value);
});
}
if (Codec is IHasFarEndContentStatus farEndContentStatus)
{
farEndContentStatus.ReceivingContent.OutputChange +=
(sender, args) => PostReceivingContent(args.BoolValue);
}
this.LogVerbose("Adding Privacy & Standby Actions");
AddAction("/privacyModeOn", (id, content) => Codec.PrivacyModeOn());
AddAction("/privacyModeOff", (id, content) => Codec.PrivacyModeOff());
AddAction("/privacyModeToggle", (id, content) => Codec.PrivacyModeToggle());
AddAction("/sharingStart", (id, content) => Codec.StartSharing());
AddAction("/sharingStop", (id, content) => Codec.StopSharing());
AddAction("/standbyOn", (id, content) => Codec.StandbyActivate());
AddAction("/standbyOff", (id, content) => Codec.StandbyDeactivate());
}
catch (Exception e)
{
this.LogException(e, "Exception adding paths");
}
}
private void SharingSourceFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
SharingSource = e.StringValue
};
PostStatusMessage(state);
}
private void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
SharingContentIsOn = e.BoolValue
};
PostStatusMessage(state);
}
private void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e)
{
var state = new VideoCodecBaseStateMessage
{
InitialPhonebookSyncComplete = true
};
PostStatusMessage(state);
}
private void CameraIsOffFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostCameraMode();
}
private void SelfviewIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostCameraSelfView();
}
private void PresetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e)
{
PostCameraPresets();
}
private void CameraAutoModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
PostCameraMode();
}
private void CameraCodec_CameraSelected(object sender, CameraSelectedEventArgs e)
{
MapCameraActions();
PostSelectedCamera();
}
/// <summary>
/// Maps the camera control actions to the current selected camera on the codec
/// </summary>
private void MapCameraActions()
{
if (Codec is IHasCameras cameraCodec && cameraCodec.SelectedCamera != null)
{
RemoveAction("/cameraUp");
RemoveAction("/cameraDown");
RemoveAction("/cameraLeft");
RemoveAction("/cameraRight");
RemoveAction("/cameraZoomIn");
RemoveAction("/cameraZoomOut");
RemoveAction("/cameraHome");
if (cameraCodec.SelectedCamera is IHasCameraPtzControl camera)
{
AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.TiltUp();
return;
}
camera.TiltStop();
}));
AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.TiltDown();
return;
}
camera.TiltStop();
}));
AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.PanLeft();
return;
}
camera.PanStop();
}));
AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.PanRight();
return;
}
camera.PanStop();
}));
AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.ZoomIn();
return;
}
camera.ZoomStop();
}));
AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
camera.ZoomOut();
return;
}
camera.ZoomStop();
}));
AddAction("/cameraHome", (id, content) => camera.PositionHome());
RemoveAction("/cameraAutoFocus");
RemoveAction("/cameraFocusNear");
RemoveAction("/cameraFocusFar");
if (cameraCodec is IHasCameraFocusControl focusCamera)
{
AddAction("/cameraAutoFocus", (id, content) => focusCamera.TriggerAutoFocus());
AddAction("/cameraFocusNear", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
focusCamera.FocusNear();
return;
}
focusCamera.FocusStop();
}));
AddAction("/cameraFocusFar", (id, content) => HandleCameraPressAndHold(content, (b) =>
{
if (b)
{
focusCamera.FocusFar();
return;
}
focusCamera.FocusStop();
}));
}
}
}
}
private void HandleCameraPressAndHold(JToken content, Action<bool> cameraAction)
{
var state = content.ToObject<MobileControlSimpleContent<string>>();
var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value);
if (timerHandler == null)
{
return;
}
timerHandler(state.Value, cameraAction);
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
}
private string GetCameraMode()
{
string m = "";
if (Codec is IHasCameraAutoMode speakerTrackCodec)
{
m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue
? eCameraControlMode.Auto.ToString().ToLower()
: eCameraControlMode.Manual.ToString().ToLower();
}
if (Codec is IHasCameraOff cameraOffCodec)
{
if (cameraOffCodec.CameraIsOffFeedback.BoolValue)
m = eCameraControlMode.Off.ToString().ToLower();
}
return m;
}
private void PostCallHistory()
{
var codec = (Codec as IHasCallHistory);
if (codec != null)
{
var status = new VideoCodecBaseStateMessage();
var recents = codec.CallHistory.RecentCalls;
if (recents != null)
{
status.RecentCalls = codec.CallHistory.RecentCalls;
PostStatusMessage(status);
}
}
}
/// <summary>
/// Helper to grab a call with string ID
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private CodecActiveCallItem GetCallWithId(string id)
{
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
private void GetDirectory(string id)
{
if (!(Codec is IHasDirectory dirCodec))
{
return;
}
dirCodec.GetDirectoryFolderContents(id);
}
/// <summary>
///
/// </summary>
private void GetDirectoryRoot()
{
if (!(Codec is IHasDirectory dirCodec))
{
// do something else?
return;
}
if (!dirCodec.PhonebookSyncState.InitialSyncComplete)
{
var state = new VideoCodecBaseStateMessage
{
InitialPhonebookSyncComplete = false
};
PostStatusMessage(state);
return;
}
dirCodec.SetCurrentDirectoryToRoot();
}
/// <summary>
/// Requests the parent folder contents
/// </summary>
private void GetPreviousDirectory()
{
if (!(Codec is IHasDirectory dirCodec))
{
return;
}
dirCodec.GetDirectoryParentFolderContents();
}
/// <summary>
/// Handler for codec changes
/// </summary>
private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
{
SendFullStatus();
}
/// <summary>
///
/// </summary>
private void SendIsReady()
{
var status = new VideoCodecBaseStateMessage();
var codecType = Codec.GetType();
status.IsReady = Codec.IsReady;
status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null;
PostStatusMessage(status);
}
/// <summary>
/// Helper method to build call status for vtc
/// </summary>
/// <returns></returns>
protected VideoCodecBaseStateMessage GetStatus()
{
var status = new VideoCodecBaseStateMessage();
if (Codec is IHasCodecCameras camerasCodec)
{
status.Cameras = new VideoCodecBaseStateMessage.CameraStatus
{
CameraManualIsSupported = true,
CameraAutoIsSupported = Codec.SupportsCameraAutoMode,
CameraOffIsSupported = Codec.SupportsCameraOff,
CameraMode = GetCameraMode(),
Cameras = camerasCodec.Cameras,
SelectedCamera = GetSelectedCamera(camerasCodec)
};
}
if (Codec is IHasDirectory directoryCodec)
{
status.HasDirectory = true;
status.HasDirectorySearch = true;
status.CurrentDirectory = directoryCodec.CurrentDirectoryResult;
}
var codecType = Codec.GetType();
status.CameraSelfViewIsOn = Codec is IHasCodecSelfView && (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue;
status.IsInCall = Codec.IsInCall;
status.PrivacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue;
status.SharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue;
status.SharingSource = Codec.SharingSourceFeedback.StringValue;
status.StandbyIsOn = Codec.StandbyIsOnFeedback.BoolValue;
status.Calls = Codec.ActiveCalls;
status.Info = Codec.CodecInfo;
status.ShowSelfViewByDefault = Codec.ShowSelfViewByDefault;
status.SupportsAdHocMeeting = Codec is IHasStartMeeting;
status.HasRecents = Codec is IHasCallHistory;
status.HasCameras = Codec is IHasCameras;
status.Presets = GetCurrentPresets();
status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null;
status.ReceivingContent = Codec is IHasFarEndContentStatus && (Codec as IHasFarEndContentStatus).ReceivingContent.BoolValue;
if (Codec is IHasMeetingInfo meetingInfoCodec)
{
status.MeetingInfo = meetingInfoCodec.MeetingInfo;
}
//Debug.Console(2, this, "VideoCodecBaseStatus:\n{0}", JsonConvert.SerializeObject(status));
return status;
}
protected virtual void SendFullStatus()
{
if (!Codec.IsReady)
{
return;
}
CrestronInvoke.BeginInvoke((o) => PostStatusMessage(GetStatus()));
}
private void PostReceivingContent(bool receivingContent)
{
var state = new VideoCodecBaseStateMessage
{
ReceivingContent = receivingContent
};
PostStatusMessage(state);
}
private void PostCameraSelfView()
{
var status = new VideoCodecBaseStateMessage
{
CameraSelfViewIsOn = Codec is IHasCodecSelfView
&& (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue
};
PostStatusMessage(status);
}
/// <summary>
///
/// </summary>
private void PostCameraMode()
{
var status = new VideoCodecBaseStateMessage
{
CameraMode = GetCameraMode()
};
PostStatusMessage(status);
}
private void PostSelectedCamera()
{
var camerasCodec = Codec as IHasCodecCameras;
var status = new VideoCodecBaseStateMessage
{
Cameras = new VideoCodecBaseStateMessage.CameraStatus() { SelectedCamera = GetSelectedCamera(camerasCodec) },
Presets = GetCurrentPresets()
};
PostStatusMessage(status);
}
private void PostCameraPresets()
{
var status = new VideoCodecBaseStateMessage
{
Presets = GetCurrentPresets()
};
PostStatusMessage(status);
}
private Camera GetSelectedCamera(IHasCodecCameras camerasCodec)
{
var camera = new Camera();
if (camerasCodec.SelectedCameraFeedback != null)
camera.Key = camerasCodec.SelectedCameraFeedback.StringValue;
if (camerasCodec.SelectedCamera != null)
{
camera.Name = camerasCodec.SelectedCamera.Name;
camera.Capabilities = new Camera.CameraCapabilities()
{
CanPan = camerasCodec.SelectedCamera.CanPan,
CanTilt = camerasCodec.SelectedCamera.CanTilt,
CanZoom = camerasCodec.SelectedCamera.CanZoom,
CanFocus = camerasCodec.SelectedCamera.CanFocus,
};
}
if (camerasCodec.ControllingFarEndCameraFeedback != null)
camera.IsFarEnd = camerasCodec.ControllingFarEndCameraFeedback.BoolValue;
return camera;
}
private List<CodecRoomPreset> GetCurrentPresets()
{
var presetsCodec = Codec as IHasCodecRoomPresets;
List<CodecRoomPreset> currentPresets = null;
if (presetsCodec != null && Codec is IHasFarEndCameraControl &&
(Codec as IHasFarEndCameraControl).ControllingFarEndCameraFeedback.BoolValue)
currentPresets = presetsCodec.FarEndRoomPresets;
else if (presetsCodec != null) currentPresets = presetsCodec.NearEndPresets;
return currentPresets;
}
}
/// <summary>
/// A class that represents the state data to be sent to the user app
/// </summary>
public class VideoCodecBaseStateMessage : DeviceStateMessageBase
{
[JsonProperty("calls", NullValueHandling = NullValueHandling.Ignore)]
public List<CodecActiveCallItem> Calls { get; set; }
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
public string CameraMode { get; set; }
[JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraSelfViewIsOn { get; set; }
[JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)]
public CameraStatus Cameras { get; set; }
[JsonProperty("cameraSupportsAutoMode", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraSupportsAutoMode { get; set; }
[JsonProperty("cameraSupportsOffMode", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraSupportsOffMode { get; set; }
[JsonProperty("currentDialString", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentDialString { get; set; }
[JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)]
public CodecDirectory CurrentDirectory { get; set; }
[JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)]
public string DirectorySelectedFolderName { get; set; }
[JsonProperty("hasCameras", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasCameras { get; set; }
[JsonProperty("hasDirectory", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasDirectory { get; set; }
[JsonProperty("hasDirectorySearch", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasDirectorySearch { get; set; }
[JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasPresets { get; set; }
[JsonProperty("hasRecents", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasRecents { get; set; }
[JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)]
public bool? InitialPhonebookSyncComplete { get; set; }
[JsonProperty("info", NullValueHandling = NullValueHandling.Ignore)]
public VideoCodecInfo Info { get; set; }
[JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsInCall { get; set; }
[JsonProperty("isReady", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsReady { get; set; }
[JsonProperty("isZoomRoom", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsZoomRoom { get; set; }
[JsonProperty("meetingInfo", NullValueHandling = NullValueHandling.Ignore)]
public MeetingInfo MeetingInfo { get; set; }
[JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
public List<CodecRoomPreset> Presets { get; set; }
[JsonProperty("privacyModeIsOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? PrivacyModeIsOn { get; set; }
[JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)]
public bool? ReceivingContent { get; set; }
[JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)]
public List<CodecCallHistory.CallHistoryEntry> RecentCalls { get; set; }
[JsonProperty("sharingContentIsOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? SharingContentIsOn { get; set; }
[JsonProperty("sharingSource", NullValueHandling = NullValueHandling.Ignore)]
public string SharingSource { get; set; }
[JsonProperty("showCamerasWhenNotInCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? ShowCamerasWhenNotInCall { get; set; }
[JsonProperty("showSelfViewByDefault", NullValueHandling = NullValueHandling.Ignore)]
public bool? ShowSelfViewByDefault { get; set; }
[JsonProperty("standbyIsOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? StandbyIsOn { get; set; }
[JsonProperty("supportsAdHocMeeting", NullValueHandling = NullValueHandling.Ignore)]
public bool? SupportsAdHocMeeting { get; set; }
public class CameraStatus
{
[JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraManualIsSupported { get; set; }
[JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraAutoIsSupported { get; set; }
[JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)]
public bool? CameraOffIsSupported { get; set; }
[JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
public string CameraMode { get; set; }
[JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
public List<CameraBase> Cameras { get; set; }
[JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)]
public Camera SelectedCamera { get; set; }
public class Camera
{
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
public string Key { get; set; }
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsFarEnd { get; set; }
[JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)]
public CameraCapabilities Capabilities { get; set; }
public class CameraCapabilities
{
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanPan { get; set; }
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanTilt { get; set; }
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanZoom { get; set; }
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
public bool? CanFocus { get; set; }
}
}
}
}
public class VideoCodecBaseEventMessage : DeviceEventMessageBase
{
}
public class PasswordPromptEventMessage : VideoCodecBaseEventMessage
{
[JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)]
public string Message { get; set; }
[JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)]
public bool LastAttemptWasIncorrect { get; set; }
[JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)]
public bool LoginAttemptFailed { get; set; }
[JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)]
public bool LoginAttemptCancelled { get; set; }
}
}

View File

@@ -1,18 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.AppServer.Messengers
{
public class MobileControlMessage : IMobileControlMessage
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("clientId")]
public string ClientId { get; set; }
[JsonProperty("content")]
public JToken Content { get; set; }
}
}

View File

@@ -1,10 +0,0 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.AppServer
{
public class MobileControlSimpleContent<T>
{
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
public T Value { get; set; }
}
}

View File

@@ -1,56 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectType>ProgramLibrary</ProjectType>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>PepperDash.Essentials.AppServer</RootNamespace>
<TargetFramework>net472</TargetFramework>
<AssemblyTitle>mobile-control-messengers</AssemblyTitle>
<AssemblyName>mobile-control-messengers</AssemblyName>
<Product>mobile-control-messengers</Product>
<Copyright>Copyright © 2024</Copyright>
<OutputPath>bin\$(Configuration)\</OutputPath>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Authors>PepperDash Technology</Authors>
<PackageId>PepperDash.Essentials.MobileControl.Messengers</PackageId>
<PackageTags>crestron 4series</PackageTags>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
<DefineConstants>$(DefineConstants);SERIES4</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DefineConstants>$(DefineConstants);SERIES4</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Messengers\SIMPLAtcMessenger.cs" />
<Compile Remove="Messengers\SIMPLCameraMessenger.cs" />
<Compile Remove="Messengers\SIMPLDirectRouteMessenger.cs" />
<Compile Remove="Messengers\SimplMessengerPropertiesConfig.cs" />
<Compile Remove="Messengers\SIMPLRouteMessenger.cs" />
<Compile Remove="Messengers\SIMPLVtcMessenger.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
<PackageReference Include="PepperDashCore" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="..\PepperDash.Essentials.Devices.Common\PepperDash.Essentials.Devices.Common.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>

View File

@@ -1,570 +0,0 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
// ReSharper disable once InconsistentNaming
public class MobileControlSIMPLRoomJoinMap : JoinMapBaseAdvanced
{
[JoinName("QrCodeUrl")]
public JoinDataComplete QrCodeUrl =
new JoinDataComplete(new JoinData { JoinNumber = 403, JoinSpan = 1 },
new JoinMetadata
{
Description = "QR Code URL",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("PortalSystemUrl")]
public JoinDataComplete PortalSystemUrl =
new JoinDataComplete(new JoinData { JoinNumber = 404, JoinSpan = 1 },
new JoinMetadata
{
Description = "Portal System URL",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("MasterVolume")]
public JoinDataComplete MasterVolume =
new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata
{
Description = "Master Volume Mute Toggle/FB/Level/Label",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.DigitalAnalogSerial
});
[JoinName("VolumeJoinStart")]
public JoinDataComplete VolumeJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 },
new JoinMetadata
{
Description = "Volume Mute Toggle/FB/Level/Label",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.DigitalAnalogSerial
});
[JoinName("PrivacyMute")]
public JoinDataComplete PrivacyMute =
new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata
{
Description = "Privacy Mute Toggle/FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PromptForCode")]
public JoinDataComplete PromptForCode =
new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 },
new JoinMetadata
{
Description = "Prompt User for Code",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ClientJoined")]
public JoinDataComplete ClientJoined =
new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 },
new JoinMetadata
{
Description = "Client Joined",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityPhoneCallEnable")]
public JoinDataComplete ActivityPhoneCallEnable =
new JoinDataComplete(new JoinData { JoinNumber = 48, JoinSpan = 1 },
new JoinMetadata
{
Description = "Enable Activity Phone Call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityVideoCallEnable")]
public JoinDataComplete ActivityVideoCallEnable =
new JoinDataComplete(new JoinData { JoinNumber = 49, JoinSpan = 1 },
new JoinMetadata
{
Description = "Enable Activity Video Call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityShare")]
public JoinDataComplete ActivityShare =
new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata
{
Description = "Activity Share",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityPhoneCall")]
public JoinDataComplete ActivityPhoneCall =
new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata
{
Description = "Activity Phone Call",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ActivityVideoCall")]
public JoinDataComplete ActivityVideoCall =
new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 },
new JoinMetadata
{
Description = "Activity Video Call",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShutdownPromptDuration")]
public JoinDataComplete ShutdownPromptDuration =
new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown Cancel",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("ShutdownCancel")]
public JoinDataComplete ShutdownCancel =
new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown Cancel",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShutdownEnd")]
public JoinDataComplete ShutdownEnd =
new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown End",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShutdownStart")]
public JoinDataComplete ShutdownStart =
new JoinDataComplete(new JoinData { JoinNumber = 63, JoinSpan = 1 },
new JoinMetadata
{
Description = "Shutdown Start",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceHasChanged")]
public JoinDataComplete SourceHasChanged =
new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 },
new JoinMetadata
{
Description = "Source Changed",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CurrentSourceKey")]
public JoinDataComplete CurrentSourceKey =
new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 },
new JoinMetadata
{
Description = "Key of selected source",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigIsLocal")]
public JoinDataComplete ConfigIsLocal =
new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config is local to Essentials",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("NumberOfAuxFaders")]
public JoinDataComplete NumberOfAuxFaders =
new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata
{
Description = "Number of Auxilliary Faders",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("SpeedDialNameStartJoin")]
public JoinDataComplete SpeedDialNameStartJoin =
new JoinDataComplete(new JoinData { JoinNumber = 241, JoinSpan = 10 },
new JoinMetadata
{
Description = "Speed Dial names",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SpeedDialNumberStartJoin")]
public JoinDataComplete SpeedDialNumberStartJoin =
new JoinDataComplete(new JoinData { JoinNumber = 251, JoinSpan = 10 },
new JoinMetadata
{
Description = "Speed Dial numbers",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SpeedDialVisibleStartJoin")]
public JoinDataComplete SpeedDialVisibleStartJoin =
new JoinDataComplete(new JoinData { JoinNumber = 261, JoinSpan = 10 },
new JoinMetadata
{
Description = "Speed Dial Visible",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("RoomIsOn")]
public JoinDataComplete RoomIsOn =
new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room Is On",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UserCodeToSystem")]
public JoinDataComplete UserCodeToSystem =
new JoinDataComplete(new JoinData { JoinNumber = 401, JoinSpan = 1 },
new JoinMetadata
{
Description = "User Code",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ServerUrl")]
public JoinDataComplete ServerUrl =
new JoinDataComplete(new JoinData { JoinNumber = 402, JoinSpan = 1 },
new JoinMetadata
{
Description = "Server URL",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigRoomName")]
public JoinDataComplete ConfigRoomName =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigHelpMessage")]
public JoinDataComplete ConfigHelpMessage =
new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room help message",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigHelpNumber")]
public JoinDataComplete ConfigHelpNumber =
new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room help number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigRoomPhoneNumber")]
public JoinDataComplete ConfigRoomPhoneNumber =
new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room phone number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ConfigRoomURI")]
public JoinDataComplete ConfigRoomUri =
new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 },
new JoinMetadata
{
Description = "Room URI",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("ApiOnlineAndAuthorized")]
public JoinDataComplete ApiOnlineAndAuthorized =
new JoinDataComplete(new JoinData { JoinNumber = 500, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config info from SIMPL is ready",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ConfigIsReady")]
public JoinDataComplete ConfigIsReady =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config info from SIMPL is ready",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ReadyForConfig")]
public JoinDataComplete ReadyForConfig =
new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 },
new JoinMetadata
{
Description = "Config info from SIMPL is ready",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("HideVideoConfRecents")]
public JoinDataComplete HideVideoConfRecents =
new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 },
new JoinMetadata
{
Description = "Hide Video Conference Recents",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("ShowCameraWhenNotInCall")]
public JoinDataComplete ShowCameraWhenNotInCall =
new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 },
new JoinMetadata
{
Description = "Show camera when not in call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UseSourceEnabled")]
public JoinDataComplete UseSourceEnabled =
new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Source Enabled Joins",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceShareDisableJoinStart")]
public JoinDataComplete SourceShareDisableJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is not sharable",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceIsEnabledJoinStart")]
public JoinDataComplete SourceIsEnabledJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is enabled/visible",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceIsControllableJoinStart")]
public JoinDataComplete SourceIsControllableJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is controllable",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceIsAudioSourceJoinStart")]
public JoinDataComplete SourceIsAudioSourceJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source is Audio Source",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceNameJoinStart")]
public JoinDataComplete SourceNameJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Names",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceIconJoinStart")]
public JoinDataComplete SourceIconJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Icons",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceKeyJoinStart")]
public JoinDataComplete SourceKeyJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Keys",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceControlDeviceKeyJoinStart")]
public JoinDataComplete SourceControlDeviceKeyJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Control Device Keys",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceTypeJoinStart")]
public JoinDataComplete SourceTypeJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 },
new JoinMetadata
{
Description = "Source Types",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CameraNearNameStart")]
public JoinDataComplete CameraNearNameStart =
new JoinDataComplete(new JoinData { JoinNumber = 761, JoinSpan = 10 },
new JoinMetadata
{
Description = "Near End Camera Names",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CameraFarName")]
public JoinDataComplete CameraFarName =
new JoinDataComplete(new JoinData { JoinNumber = 771, JoinSpan = 1 },
new JoinMetadata
{
Description = "Far End Camera Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
#region Advanced Sharing
[JoinName("SupportsAdvancedSharing")]
public JoinDataComplete SupportsAdvancedSharing =
new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 },
new JoinMetadata
{
Description = "Supports Advanced Sharing",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UseDestinationEnable")]
public JoinDataComplete UseDestinationEnable =
new JoinDataComplete(new JoinData { JoinNumber = 506, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Destination Enable",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("UserCanChangeShareMode")]
public JoinDataComplete UserCanChangeShareMode =
new JoinDataComplete(new JoinData { JoinNumber = 507, JoinSpan = 1 },
new JoinMetadata
{
Description = "Share Mode Toggle Visible to User",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DestinationNameJoinStart")]
public JoinDataComplete DestinationNameJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 },
new JoinMetadata
{
Description = "Destination Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DestinationDeviceKeyJoinStart")]
public JoinDataComplete DestinationDeviceKeyJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 811, JoinSpan = 10 },
new JoinMetadata
{
Description = "Destination Device Key",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DestinationTypeJoinStart")]
public JoinDataComplete DestinationTypeJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 821, JoinSpan = 10 },
new JoinMetadata
{
Description = "Destination type. Should be Audio, Video, AudioVideo",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DestinationIsEnabledJoinStart")]
public JoinDataComplete DestinationIsEnabledJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 },
new JoinMetadata
{
Description = "Show Destination on UI",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
#endregion
public MobileControlSIMPLRoomJoinMap(uint joinStart)
: base(joinStart, typeof(MobileControlSIMPLRoomJoinMap))
{
}
}
}

View File

@@ -1,72 +0,0 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class MobileControlSIMPLRunDirectRouteActionJoinMap : JoinMapBaseAdvanced
{
[JoinName("AdvancedSharingModeFb")]
public JoinDataComplete AdvancedSharingModeFb =
new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AdvancedSharingModeOn")]
public JoinDataComplete AdvancedSharingModeOn =
new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AdvancedSharingModeOff")]
public JoinDataComplete AdvancedSharingModeOff =
new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("AdvancedSharingModeToggle")]
public JoinDataComplete AdvancedSharingModeToggle =
new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata
{
Description = "Use Advanced Sharing Mode",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SourceForDestinationJoinStart")]
public JoinDataComplete SourceForDestinationJoinStart =
new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 10 },
new JoinMetadata
{
Description = "Source to Route to Destination & FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("SourceForDestinationAudio")]
public JoinDataComplete SourceForDestinationAudio =
new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 },
new JoinMetadata
{
Description = "Source to Route to Destination & FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
public MobileControlSIMPLRunDirectRouteActionJoinMap(uint joinStart)
: base(joinStart, typeof(MobileControlSIMPLRunDirectRouteActionJoinMap))
{
}
}
}

View File

@@ -1,247 +0,0 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class SIMPLAtcJoinMap : JoinMapBaseAdvanced
{
[JoinName("EndCall")]
public JoinDataComplete EndCall =
new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Hang Up",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingAnswer")]
public JoinDataComplete IncomingAnswer =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Answer Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingReject")]
public JoinDataComplete IncomingReject =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Reject Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SpeedDialStart")]
public JoinDataComplete SpeedDialStart =
new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 },
new JoinMetadata()
{
Description = "Speed Dial",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CurrentDialString")]
public JoinDataComplete CurrentDialString =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Dial String",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallNumber")]
public JoinDataComplete CurrentCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallName")]
public JoinDataComplete CurrentCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("HookState")]
public JoinDataComplete HookState =
new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Hook State",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CallDirection")]
public JoinDataComplete CallDirection =
new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Direction",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallName")]
public JoinDataComplete IncomingCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallNumber")]
public JoinDataComplete IncomingCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("0")]
public JoinDataComplete Dtmf0 =
new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 0",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("1")]
public JoinDataComplete Dtmf1 =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 1",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("2")]
public JoinDataComplete Dtmf2 =
new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 2",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("3")]
public JoinDataComplete Dtmf3 =
new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 3",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("4")]
public JoinDataComplete Dtmf4 =
new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 4",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("5")]
public JoinDataComplete Dtmf5 =
new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 5",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("6")]
public JoinDataComplete Dtmf6 =
new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 6",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("7")]
public JoinDataComplete Dtmf7 =
new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 7",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("8")]
public JoinDataComplete Dtmf8 =
new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 8",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("9")]
public JoinDataComplete Dtmf9 =
new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 9",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("*")]
public JoinDataComplete DtmfStar =
new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF *",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("#")]
public JoinDataComplete DtmfPound =
new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF #",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
/// <summary>
/// Constructor that passes the joinStart to the base class
/// </summary>
/// <param name="joinStart"></param>
public SIMPLAtcJoinMap(uint joinStart)
: base(joinStart, typeof(SIMPLAtcJoinMap))
{
}
}
}

View File

@@ -1,553 +0,0 @@
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.AppServer
{
public class SIMPLVtcJoinMap : JoinMapBaseAdvanced
{
[JoinName("EndCall")]
public JoinDataComplete EndCall =
new JoinDataComplete(new JoinData() { JoinNumber = 24, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Hang Up",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingCall")]
public JoinDataComplete IncomingCall =
new JoinDataComplete(new JoinData() { JoinNumber = 50, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingAnswer")]
public JoinDataComplete IncomingAnswer =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Answer Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("IncomingReject")]
public JoinDataComplete IncomingReject =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Reject Incoming Call",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("SpeedDialStart")]
public JoinDataComplete SpeedDialStart =
new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 },
new JoinMetadata()
{
Description = "Speed Dial",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectorySearchBusy")]
public JoinDataComplete DirectorySearchBusy =
new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Search Busy FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryLineSelected")]
public JoinDataComplete DirectoryLineSelected =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Line Selected FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryEntryIsContact")]
public JoinDataComplete DirectoryEntryIsContact =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Selected Entry Is Contact FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryIsRoot")]
public JoinDataComplete DirectoryIsRoot =
new JoinDataComplete(new JoinData() { JoinNumber = 102, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory is on Root FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DDirectoryHasChanged")]
public JoinDataComplete DDirectoryHasChanged =
new JoinDataComplete(new JoinData() { JoinNumber = 103, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory has changed FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryRoot")]
public JoinDataComplete DirectoryRoot =
new JoinDataComplete(new JoinData() { JoinNumber = 104, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Go to Directory Root",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryFolderBack")]
public JoinDataComplete DirectoryFolderBack =
new JoinDataComplete(new JoinData() { JoinNumber = 105, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Go back one directory level",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectoryDialSelectedLine")]
public JoinDataComplete DirectoryDialSelectedLine =
new JoinDataComplete(new JoinData() { JoinNumber = 106, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Dial selected directory line",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraTiltUp")]
public JoinDataComplete CameraTiltUp =
new JoinDataComplete(new JoinData() { JoinNumber = 111, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Tilt Up",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraTiltDown")]
public JoinDataComplete CameraTiltDown =
new JoinDataComplete(new JoinData() { JoinNumber = 112, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Tilt Down",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPanLeft")]
public JoinDataComplete CameraPanLeft =
new JoinDataComplete(new JoinData() { JoinNumber = 113, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Pan Left",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPanRight")]
public JoinDataComplete CameraPanRight =
new JoinDataComplete(new JoinData() { JoinNumber = 114, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Pan Right",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraZoomIn")]
public JoinDataComplete CameraZoomIn =
new JoinDataComplete(new JoinData() { JoinNumber = 115, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Zoom In",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraZoomOut")]
public JoinDataComplete CameraZoomOut =
new JoinDataComplete(new JoinData() { JoinNumber = 116, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Zoom Out",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraPresetStart")]
public JoinDataComplete CameraPresetStart =
new JoinDataComplete(new JoinData() { JoinNumber = 121, JoinSpan = 5 },
new JoinMetadata()
{
Description = "Camera Presets",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraModeAuto")]
public JoinDataComplete CameraModeAuto =
new JoinDataComplete(new JoinData() { JoinNumber = 131, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Mode Auto",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraModeManual")]
public JoinDataComplete CameraModeManual =
new JoinDataComplete(new JoinData() { JoinNumber = 132, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Mode Manual",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraModeOff")]
public JoinDataComplete CameraModeOff =
new JoinDataComplete(new JoinData() { JoinNumber = 133, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Mode Off",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraSelfView")]
public JoinDataComplete CameraSelfView =
new JoinDataComplete(new JoinData() { JoinNumber = 141, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Self View Toggle/FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraLayout")]
public JoinDataComplete CameraLayout =
new JoinDataComplete(new JoinData() { JoinNumber = 142, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Layout Toggle",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraSupportsAutoMode")]
public JoinDataComplete CameraSupportsAutoMode =
new JoinDataComplete(new JoinData() { JoinNumber = 143, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Supports Auto Mode FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraSupportsOffMode")]
public JoinDataComplete CameraSupportsOffMode =
new JoinDataComplete(new JoinData() { JoinNumber = 144, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Supports Off Mode FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("CameraNumberSelect")]
public JoinDataComplete CameraNumberSelect =
new JoinDataComplete(new JoinData() { JoinNumber = 60, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Camera Number Select/FB",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("DirectorySelectRow")]
public JoinDataComplete DirectorySelectRow =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Select Row",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("DirectoryRowCount")]
public JoinDataComplete DirectoryRowCount =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Row Count FB",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Analog
});
[JoinName("CurrentDialString")]
public JoinDataComplete CurrentDialString =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Dial String",
JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallName")]
public JoinDataComplete CurrentCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CurrentCallNumber")]
public JoinDataComplete CurrentCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("HookState")]
public JoinDataComplete HookState =
new JoinDataComplete(new JoinData() { JoinNumber = 31, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Hook State",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("CallDirection")]
public JoinDataComplete CallDirection =
new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Current Call Direction",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallName")]
public JoinDataComplete IncomingCallName =
new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("IncomingCallNumber")]
public JoinDataComplete IncomingCallNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Incoming Call Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectorySearchString")]
public JoinDataComplete DirectorySearchString =
new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Directory Search String",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntriesStart")]
public JoinDataComplete DirectoryEntriesStart =
new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 255 },
new JoinMetadata()
{
Description = "Directory Entries",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntrySelectedName")]
public JoinDataComplete DirectoryEntrySelectedName =
new JoinDataComplete(new JoinData() { JoinNumber = 356, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Selected Directory Entry Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectoryEntrySelectedNumber")]
public JoinDataComplete DirectoryEntrySelectedNumber =
new JoinDataComplete(new JoinData() { JoinNumber = 357, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Selected Directory Entry Number",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("DirectorySelectedFolderName")]
public JoinDataComplete DirectorySelectedFolderName =
new JoinDataComplete(new JoinData() { JoinNumber = 358, JoinSpan = 1 },
new JoinMetadata()
{
Description = "Selected Directory Folder Name",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
[JoinName("1")]
public JoinDataComplete Dtmf1 =
new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 1",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("2")]
public JoinDataComplete Dtmf2 =
new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 2",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("3")]
public JoinDataComplete Dtmf3 =
new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 3",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("4")]
public JoinDataComplete Dtmf4 =
new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 4",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("5")]
public JoinDataComplete Dtmf5 =
new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 5",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("6")]
public JoinDataComplete Dtmf6 =
new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 6",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("7")]
public JoinDataComplete Dtmf7 =
new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 7",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("8")]
public JoinDataComplete Dtmf8 =
new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 8",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("9")]
public JoinDataComplete Dtmf9 =
new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 9",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("0")]
public JoinDataComplete Dtmf0 =
new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF 0",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("*")]
public JoinDataComplete DtmfStar =
new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF *",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("#")]
public JoinDataComplete DtmfPound =
new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 },
new JoinMetadata()
{
Description = "DTMF #",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
public SIMPLVtcJoinMap(uint joinStart)
: base(joinStart, typeof(SIMPLVtcJoinMap))
{
}
}
}

View File

@@ -1,19 +0,0 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials
{
public class AuthorizationResponse
{
[JsonProperty("authorized")]
public bool Authorized { get; set; }
[JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)]
public string Reason { get; set; } = null;
}
public class AuthorizationRequest
{
[JsonProperty("grantCode")]
public string GrantCode { get; set; }
}
}

View File

@@ -1,16 +0,0 @@
using System;
namespace PepperDash.Essentials
{
/// <summary>
/// Represents a room whose configuration is derived from runtime data,
/// perhaps from another program, and that the data may not be fully
/// available at startup.
/// </summary>
public interface IDelayedConfiguration
{
event EventHandler<EventArgs> ConfigurationIsReady;
}
}

View File

@@ -1,19 +0,0 @@
using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials
{
public class MobileControlAction : IMobileControlAction
{
public IMobileControlMessenger Messenger { get; private set; }
public Action<string, string, JToken> Action { get; private set; }
public MobileControlAction(IMobileControlMessenger messenger, Action<string, string, JToken> handler)
{
Messenger = messenger;
Action = handler;
}
}
}

View File

@@ -1,144 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Collections.Generic;
namespace PepperDash.Essentials
{
/// <summary>
///
/// </summary>
public class MobileControlConfig
{
[JsonProperty("serverUrl")]
public string ServerUrl { get; set; }
[JsonProperty("clientAppUrl")]
public string ClientAppUrl { get; set; }
[JsonProperty("directServer")]
public MobileControlDirectServerPropertiesConfig DirectServer { get; set; }
[JsonProperty("applicationConfig")]
public MobileControlApplicationConfig ApplicationConfig { get; set; } = null;
[JsonProperty("enableApiServer")]
public bool EnableApiServer { get; set; } = true;
}
public class MobileControlDirectServerPropertiesConfig
{
[JsonProperty("enableDirectServer")]
public bool EnableDirectServer { get; set; }
[JsonProperty("port")]
public int Port { get; set; }
[JsonProperty("logging")]
public MobileControlLoggingConfig Logging { get; set; }
[JsonProperty("automaticallyForwardPortToCSLAN")]
public bool? AutomaticallyForwardPortToCSLAN { get; set; }
public MobileControlDirectServerPropertiesConfig()
{
Logging = new MobileControlLoggingConfig();
}
}
public class MobileControlLoggingConfig
{
[JsonProperty("enableRemoteLogging")]
public bool EnableRemoteLogging { get; set; }
[JsonProperty("host")]
public string Host { get; set; }
[JsonProperty("port")]
public int Port { get; set; }
}
public class MobileControlRoomBridgePropertiesConfig
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("roomKey")]
public string RoomKey { get; set; }
}
/// <summary>
///
/// </summary>
public class MobileControlSimplRoomBridgePropertiesConfig
{
[JsonProperty("eiscId")]
public string EiscId { get; set; }
}
public class MobileControlApplicationConfig
{
[JsonProperty("apiPath")]
public string ApiPath { get; set; }
[JsonProperty("gatewayAppPath")]
public string GatewayAppPath { get; set; }
[JsonProperty("enableDev")]
public bool? EnableDev { get; set; }
[JsonProperty("logoPath")]
/// <summary>
/// Client logo to be used in header and/or splash screen
/// </summary>
public string LogoPath { get; set; }
[JsonProperty("iconSet")]
[JsonConverter(typeof(StringEnumConverter))]
public MCIconSet? IconSet { get; set; }
[JsonProperty("loginMode")]
public string LoginMode { get; set; }
[JsonProperty("modes")]
public Dictionary<string, McMode> Modes { get; set; }
[JsonProperty("enableRemoteLogging")]
public bool Logging { get; set; }
[JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)]
public List<MobileControlPartnerMetadata> PartnerMetadata { get; set; }
}
public class MobileControlPartnerMetadata
{
[JsonProperty("role")]
public string Role { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("logoPath")]
public string LogoPath { get; set; }
}
public class McMode
{
[JsonProperty("listPageText")]
public string ListPageText { get; set; }
[JsonProperty("loginHelpText")]
public string LoginHelpText { get; set; }
[JsonProperty("passcodePageText")]
public string PasscodePageText { get; set; }
}
public enum MCIconSet
{
GOOGLE,
HABANERO,
NEO
}
}

View File

@@ -1,34 +0,0 @@
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials
{
public class MobileControlDeviceFactory : EssentialsDeviceFactory<MobileControlSystemController>
{
public MobileControlDeviceFactory()
{
TypeNames = new List<string> { "appserver", "mobilecontrol", "webserver" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
try
{
var props = dc.Properties.ToObject<MobileControlConfig>();
return new MobileControlSystemController(dc.Key, dc.Name, props);
}
catch (Exception e)
{
Debug.LogMessage(e, "Error building Mobile Control System Controller");
return null;
}
}
}
}

View File

@@ -1,54 +0,0 @@
using Newtonsoft.Json;
using PepperDash.Essentials.Core.Config;
using System.Collections.Generic;
namespace PepperDash.Essentials
{
/// <summary>
/// Used to overlay additional config data from mobile control on
/// </summary>
public class MobileControlEssentialsConfig : EssentialsConfig
{
[JsonProperty("runtimeInfo")]
public MobileControlRuntimeInfo RuntimeInfo { get; set; }
public MobileControlEssentialsConfig(EssentialsConfig config)
: base()
{
// TODO: Consider using Reflection to iterate properties
this.Devices = config.Devices;
this.Info = config.Info;
this.JoinMaps = config.JoinMaps;
this.Rooms = config.Rooms;
this.SourceLists = config.SourceLists;
this.DestinationLists = config.DestinationLists;
this.SystemUrl = config.SystemUrl;
this.TemplateUrl = config.TemplateUrl;
this.TieLines = config.TieLines;
if (this.Info == null)
this.Info = new InfoConfig();
RuntimeInfo = new MobileControlRuntimeInfo();
}
}
/// <summary>
/// Used to add any additional runtime information from mobile control to be send to the API
/// </summary>
public class MobileControlRuntimeInfo
{
[JsonProperty("pluginVersion")]
public string PluginVersion { get; set; }
[JsonProperty("essentialsVersion")]
public string EssentialsVersion { get; set; }
[JsonProperty("pepperDashCoreVersion")]
public string PepperDashCoreVersion { get; set; }
[JsonProperty("essentialsPlugins")]
public List<LoadedAssembly> EssentialsPlugins { get; set; }
}
}

View File

@@ -1,39 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System;
using System.Linq;
using System.Reflection;
namespace PepperDash.Essentials
{
public class MobileControlFactory
{
public MobileControlFactory()
{
var assembly = Assembly.GetExecutingAssembly();
PluginLoader.SetEssentialsAssembly(assembly.GetName().Name, assembly);
var types = assembly.GetTypes().Where(t => typeof(IDeviceFactory).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
if (types == null)
{
return;
}
foreach (var type in types)
{
try
{
var factory = (IDeviceFactory)Activator.CreateInstance(type);
factory.LoadTypeFactories();
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Unable to load type '{type}' DeviceFactory: {factory}", null, type.Name);
}
}
}
}
}

View File

@@ -1,143 +0,0 @@
using Crestron.SimplSharpPro.EthernetCommunication;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using System;
namespace PepperDash.Essentials.Room.MobileControl
{
/// <summary>
/// Represents a generic device connection through to and EISC for SIMPL01
/// </summary>
public class MobileControlSimplDeviceBridge : Device, IChannel, INumericKeypad
{
/// <summary>
/// EISC used to talk to Simpl
/// </summary>
private readonly ThreeSeriesTcpIpEthernetIntersystemCommunications _eisc;
public MobileControlSimplDeviceBridge(string key, string name,
ThreeSeriesTcpIpEthernetIntersystemCommunications eisc)
: base(key, name)
{
_eisc = eisc;
}
#region IChannel Members
public void ChannelUp(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void ChannelDown(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void LastChannel(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Guide(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Info(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Exit(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
#endregion
#region INumericKeypad Members
public void Digit0(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit1(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit2(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit3(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit4(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit5(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit6(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit7(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit8(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public void Digit9(bool pressRelease)
{
_eisc.SetBool(1111, pressRelease);
}
public bool HasKeypadAccessoryButton1
{
get { throw new NotImplementedException(); }
}
public string KeypadAccessoryButton1Label
{
get { throw new NotImplementedException(); }
}
public void KeypadAccessoryButton1(bool pressRelease)
{
throw new NotImplementedException();
}
public bool HasKeypadAccessoryButton2
{
get { throw new NotImplementedException(); }
}
public string KeypadAccessoryButton2Label
{
get { throw new NotImplementedException(); }
}
public void KeypadAccessoryButton2(bool pressRelease)
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -1,69 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>PepperDash.Essentials</RootNamespace>
<TargetFramework>net472</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<Deterministic>false</Deterministic>
<AssemblyTitle>epi-essentials-mobile-control</AssemblyTitle>
<AssemblyName>epi-essentials-mobile-control</AssemblyName>
<Company>PepperDash Technologies</Company>
<Product>epi-essentials-mobile-control</Product>
<Description>This software is a plugin designed to work as a part of PepperDash Essentials for Crestron control processors. This plugin allows for connection to a PepperDash Mobile Control server.</Description>
<Copyright>Copyright 2020</Copyright>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<InformationalVersion>$(Version)</InformationalVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<OutputPath>bin\$(Configuration)\</OutputPath>
<Authors>PepperDash Technologies</Authors>
<PackageId>PepperDash.Essentials.MobileControl</PackageId>
<PackageTags>crestron 4series</PackageTags>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DefineConstants>TRACE;DEBUG;SERIES4</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DefineConstants>TRACE;SERIES4</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="bin\**" />
<EmbeddedResource Remove="bin\**" />
<None Remove="bin\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="MobileControlSimplDeviceBridge.cs" />
<Compile Remove="RoomBridges\MobileControlSIMPLRoomBridge.cs" />
<Compile Remove="RoomBridges\SourceDeviceMapDictionary.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
<PackageReference Include="PepperDashCore" Version="2.0.1" />
<PackageReference Include="WebSocketSharp-netstandard" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<None Remove="C:\Users\awelker\source\Essentials\Essentials\src\PepperDash.Essentials.MobileControl\bin\Debug\net472\PepperDash.Essentials.MobileControl.4.0.0-local.net472.cplz" />
</ItemGroup>
<ItemGroup>
<None Remove="C:\Users\awelker\source\Essentials\Essentials\src\PepperDash.Essentials.MobileControl\bin\Debug\net472\PepperDash.Essentials.MobileControl.4.0.0-local.net472.cplz" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="..\PepperDash.Essentials.Devices.Common\PepperDash.Essentials.Devices.Common.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="..\PepperDash.Essentials.MobileControl.Messengers\PepperDash.Essentials.MobileControl.Messengers.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -1,131 +0,0 @@
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using System;
namespace PepperDash.Essentials.RoomBridges
{
/// <summary>
///
/// </summary>
public abstract class MobileControlBridgeBase : MessengerBase, IMobileControlRoomMessenger
{
public event EventHandler<EventArgs> UserCodeChanged;
public event EventHandler<EventArgs> UserPromptedForCode;
public event EventHandler<EventArgs> ClientJoined;
public event EventHandler<EventArgs> AppUrlChanged;
public IMobileControl Parent { get; private set; }
public string AppUrl { get; private set; }
public string UserCode { get; private set; }
public string QrCodeUrl { get; protected set; }
public string QrCodeChecksum { get; protected set; }
public string McServerUrl { get; private set; }
public abstract string RoomName { get; }
public abstract string RoomKey { get; }
protected MobileControlBridgeBase(string key, string messagePath)
: base(key, messagePath)
{
}
protected MobileControlBridgeBase(string key, string messagePath, IKeyName device)
: base(key, messagePath, device)
{
}
/// <summary>
/// Set the parent. Does nothing else. Override to add functionality such
/// as adding actions to parent
/// </summary>
/// <param name="parent"></param>
public virtual void AddParent(IMobileControl parent)
{
Parent = parent;
McServerUrl = Parent.ClientAppUrl;
}
/// <summary>
/// Sets the UserCode on the bridge object. Called from controller. A changed code will
/// fire method UserCodeChange. Override that to handle changes
/// </summary>
/// <param name="code"></param>
public void SetUserCode(string code)
{
var changed = UserCode != code;
UserCode = code;
if (changed)
{
UserCodeChange();
}
}
/// <summary>
/// Sets the UserCode on the bridge object. Called from controller. A changed code will
/// fire method UserCodeChange. Override that to handle changes
/// </summary>
/// <param name="code"></param>
/// <param name="qrChecksum">Checksum of the QR code. Used for Cisco codec branding command</param>
public void SetUserCode(string code, string qrChecksum)
{
QrCodeChecksum = qrChecksum;
SetUserCode(code);
}
public virtual void UpdateAppUrl(string url)
{
AppUrl = url;
var handler = AppUrlChanged;
if (handler == null) return;
handler(this, new EventArgs());
}
/// <summary>
/// Empty method in base class. Override this to add functionality
/// when code changes
/// </summary>
protected virtual void UserCodeChange()
{
this.LogDebug("Server user code changed: {userCode}", UserCode);
var qrUrl = string.Format($"{Parent.Host}/api/rooms/{Parent.SystemUuid}/{RoomKey}/qr?x={new Random().Next()}");
QrCodeUrl = qrUrl;
this.LogDebug("Server user code changed: {userCode} - {qrCodeUrl}", UserCode, qrUrl);
OnUserCodeChanged();
}
protected void OnUserCodeChanged()
{
UserCodeChanged?.Invoke(this, new EventArgs());
}
protected void OnUserPromptedForCode()
{
UserPromptedForCode?.Invoke(this, new EventArgs());
}
protected void OnClientJoined()
{
ClientJoined?.Invoke(this, new EventArgs());
}
}
}

View File

@@ -1,967 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.AppServer;
using PepperDash.Essentials.AppServer.Messengers;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Lighting;
using PepperDash.Essentials.Core.Shades;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Room;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.WebSocketServer;
using System;
using System.Collections.Generic;
using System.Linq;
using IShades = PepperDash.Essentials.Core.Shades.IShades;
using ShadeBase = PepperDash.Essentials.Devices.Common.Shades.ShadeBase;
namespace PepperDash.Essentials.RoomBridges
{
public class MobileControlEssentialsRoomBridge : MobileControlBridgeBase
{
private List<JoinToken> _touchPanelTokens = new List<JoinToken>();
public IEssentialsRoom Room { get; private set; }
public string DefaultRoomKey { get; private set; }
/// <summary>
///
/// </summary>
public override string RoomName
{
get { return Room.Name; }
}
public override string RoomKey
{
get { return Room.Key; }
}
public MobileControlEssentialsRoomBridge(IEssentialsRoom room) :
this($"mobileControlBridge-{room.Key}", room.Key, room)
{
Room = room;
}
public MobileControlEssentialsRoomBridge(string key, string roomKey, IEssentialsRoom room) : base(key, $"/room/{room.Key}", room as Device)
{
DefaultRoomKey = roomKey;
AddPreActivationAction(GetRoom);
}
protected override void RegisterActions()
{
// we add actions to the messaging system with a path, and a related action. Custom action
// content objects can be handled in the controller's LineReceived method - and perhaps other
// sub-controller parsing could be attached to these classes, so that the systemController
// doesn't need to know about everything.
this.LogInformation("Registering Actions with AppServer");
AddAction("/promptForCode", (id, content) => OnUserPromptedForCode());
AddAction("/clientJoined", (id, content) => OnClientJoined());
AddAction("/touchPanels", (id, content) => OnTouchPanelsUpdated(content));
AddAction($"/userApp", (id, content) => OnUserAppUpdated(content));
AddAction("/userCode", (id, content) =>
{
var msg = content.ToObject<UserCodeChangedContent>();
SetUserCode(msg.UserCode, msg.QrChecksum ?? string.Empty);
});
// Source Changes and room off
AddAction("/status", (id, content) =>
{
SendFullStatusForClientId(id, Room);
});
if (Room is IRunRouteAction routeRoom)
AddAction("/source", (id, content) =>
{
var msg = content.ToObject<SourceSelectMessageContent>();
this.LogVerbose("Received request to route to source: {sourceListKey} on list: {sourceList}", msg.SourceListItemKey, msg.SourceListKey);
routeRoom.RunRouteAction(msg.SourceListItemKey, msg.SourceListKey);
});
if (Room is IRunDirectRouteAction directRouteRoom)
{
AddAction("/directRoute", (id, content) =>
{
var msg = content.ToObject<DirectRoute>();
this.LogVerbose("Running direct route from {sourceKey} to {destinationKey} with signal type {signalType}", msg.SourceKey, msg.DestinationKey, msg.SignalType);
directRouteRoom.RunDirectRoute(msg.SourceKey, msg.DestinationKey, msg.SignalType);
});
}
if (Room is IRunDefaultPresentRoute defaultRoom)
AddAction("/defaultsource", (id, content) => defaultRoom.RunDefaultPresentRoute());
if (Room is IHasCurrentVolumeControls volumeRoom)
{
volumeRoom.CurrentVolumeDeviceChange += Room_CurrentVolumeDeviceChange;
if (volumeRoom.CurrentVolumeControls == null) return;
AddAction("/volumes/master/level", (id, content) =>
{
var msg = content.ToObject<MobileControlSimpleContent<ushort>>();
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
basicVolumeWithFeedback.SetVolume(msg.Value);
});
AddAction("/volumes/master/muteToggle", (id, content) => volumeRoom.CurrentVolumeControls.MuteToggle());
AddAction("/volumes/master/muteOn", (id, content) =>
{
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
basicVolumeWithFeedback.MuteOn();
});
AddAction("/volumes/master/muteOff", (id, content) =>
{
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
basicVolumeWithFeedback.MuteOff();
});
AddAction("/volumes/master/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
{
basicVolumeWithFeedback.VolumeUp(b);
}
}
));
AddAction("/volumes/master/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
{
basicVolumeWithFeedback.VolumeDown(b);
}
}
));
// Registers for initial volume events, if possible
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback currentVolumeDevice)
{
this.LogVerbose("Registering for volume feedback events");
currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
}
}
if (Room is IHasCurrentSourceInfoChange sscRoom)
sscRoom.CurrentSourceChange += Room_CurrentSingleSourceChange;
if (Room is IEssentialsHuddleVtc1Room vtcRoom)
{
if (vtcRoom.ScheduleSource != null)
{
var key = vtcRoom.Key + "-" + Key;
if (!AppServerController.CheckForDeviceMessenger(key))
{
var scheduleMessenger = new IHasScheduleAwarenessMessenger(key, vtcRoom.ScheduleSource,
$"/room/{vtcRoom.Key}");
AppServerController.AddDeviceMessenger(scheduleMessenger);
}
}
vtcRoom.InCallFeedback.OutputChange += InCallFeedback_OutputChange;
}
if (Room is IPrivacy privacyRoom)
{
AddAction("/volumes/master/privacyMuteToggle", (id, content) => privacyRoom.PrivacyModeToggle());
privacyRoom.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
}
if (Room is IRunDefaultCallRoute defCallRm)
{
AddAction("/activityVideo", (id, content) => defCallRm.RunDefaultCallRoute());
}
Room.OnFeedback.OutputChange += OnFeedback_OutputChange;
Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
AddTechRoomActions();
}
private void OnTouchPanelsUpdated(JToken content)
{
var message = content.ToObject<ApiTouchPanelToken>();
_touchPanelTokens = message.TouchPanels;
UpdateTouchPanelAppUrls(message.UserAppUrl);
}
private void UpdateTouchPanelAppUrls(string userAppUrl)
{
foreach (var tp in _touchPanelTokens)
{
var dev = DeviceManager.AllDevices.OfType<IMobileControlTouchpanelController>().FirstOrDefault((tpc) => tpc.Key.Equals(tp.TouchpanelKey, StringComparison.InvariantCultureIgnoreCase));
if (dev == null)
{
continue;
}
//UpdateAppUrl($"{userAppUrl}?token={tp.Token}");
dev.SetAppUrl($"{userAppUrl}?token={tp.Token}");
}
}
private void OnUserAppUpdated(JToken content)
{
var message = content.ToObject<ApiTouchPanelToken>();
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Updating User App URL to {userAppUrl}. Full Message: {@message}", this, message.UserAppUrl, content);
UpdateTouchPanelAppUrls(message.UserAppUrl);
}
private void InCallFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new RoomStateMessage
{
IsInCall = e.BoolValue
};
PostStatusMessage(state);
}
private void GetRoom()
{
if (Room != null)
{
this.LogInformation("Room with key {key} already linked.", DefaultRoomKey);
return;
}
if (!(DeviceManager.GetDeviceForKey(DefaultRoomKey) is IEssentialsRoom tempRoom))
{
this.LogInformation("Room with key {key} not found or is not an Essentials Room", DefaultRoomKey);
return;
}
Room = tempRoom;
}
protected override void UserCodeChange()
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Server user code changed: {userCode}", this, UserCode);
var qrUrl = string.Format("{0}/rooms/{1}/{3}/qr?x={2}", Parent?.Host, Parent?.SystemUuid, new Random().Next(), DefaultRoomKey);
QrCodeUrl = qrUrl;
this.LogDebug("Server user code changed: {userCode} - {qrUrl}", UserCode, qrUrl);
OnUserCodeChanged();
}
/* /// <summary>
/// Override of base: calls base to add parent and then registers actions and events.
/// </summary>
/// <param name="parent"></param>
public override void AddParent(MobileControlSystemController parent)
{
base.AddParent(parent);
}*/
private void AddTechRoomActions()
{
if (!(Room is IEssentialsTechRoom techRoom))
{
return;
}
AddAction("/roomPowerOn", (id, content) => techRoom.RoomPowerOn());
AddAction("/roomPowerOff", (id, content) => techRoom.RoomPowerOff());
}
private void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new RoomStateMessage();
var volumes = new Dictionary<string, Volume>
{
{ "master", new Volume("master")
{
PrivacyMuted = e.BoolValue
}
}
};
state.Volumes = volumes;
PostStatusMessage(state);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void IsSharingFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
// sharing source
string shareText;
bool isSharing;
if (Room is IHasCurrentSourceInfoChange srcInfoRoom && Room is IHasVideoCodec vcRoom && vcRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && srcInfoRoom.CurrentSourceInfo != null)
{
shareText = srcInfoRoom.CurrentSourceInfo.PreferredName;
isSharing = true;
}
else
{
shareText = "None";
isSharing = false;
}
var state = new RoomStateMessage
{
Share = new ShareState
{
CurrentShareText = shareText,
IsSharing = isSharing
}
};
PostStatusMessage(state);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new
{
isWarmingUp = e.BoolValue
};
PostStatusMessage(JToken.FromObject(state));
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new
{
isCoolingDown = e.BoolValue
};
PostStatusMessage(JToken.FromObject(state));
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new
{
isOn = e.BoolValue
};
PostStatusMessage(JToken.FromObject(state));
}
private void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
{
if (e.OldDev is IBasicVolumeWithFeedback)
{
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
oldDev.MuteFeedback.OutputChange -= MuteFeedback_OutputChange;
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
}
if (e.NewDev is IBasicVolumeWithFeedback)
{
var newDev = e.NewDev as IBasicVolumeWithFeedback;
newDev.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
}
}
/// <summary>
/// Event handler for mute changes
/// </summary>
private void MuteFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new RoomStateMessage();
var volumes = new Dictionary<string, Volume>
{
{ "master", new Volume("master", e.BoolValue) }
};
state.Volumes = volumes;
PostStatusMessage(state);
}
/// <summary>
/// Handles Volume changes on room
/// </summary>
private void VolumeLevelFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
var state = new
{
volumes = new Dictionary<string, Volume>
{
{ "master", new Volume("master", e.IntValue) }
}
};
PostStatusMessage(JToken.FromObject(state));
}
private void Room_CurrentSingleSourceChange(SourceListItem info, ChangeType type)
{
/* Example message
* {
"type":"/room/status",
"content": {
"selectedSourceKey": "off",
}
}
*/
}
/// <summary>
/// Sends the full status of the room to the server
/// </summary>
/// <param name="room"></param>
private void SendFullStatusForClientId(string id, IEssentialsRoom room)
{
//Parent.SendMessageObject(GetFullStatus(room));
var message = GetFullStatusForClientId(room);
if (message == null)
{
return;
}
PostStatusMessage(message, id);
}
/// <summary>
/// Gets full room status
/// </summary>
/// <param name="room">The room to get status of</param>
/// <returns>The status response message</returns>
private RoomStateMessage GetFullStatusForClientId(IEssentialsRoom room)
{
try
{
this.LogVerbose("GetFullStatus");
var sourceKey = room is IHasCurrentSourceInfoChange ? (room as IHasCurrentSourceInfoChange).CurrentSourceInfoKey : null;
var volumes = new Dictionary<string, Volume>();
if (room is IHasCurrentVolumeControls rmVc)
{
if (rmVc.CurrentVolumeControls is IBasicVolumeWithFeedback vc)
{
var volume = new Volume("master", vc.VolumeLevelFeedback.UShortValue, vc.MuteFeedback.BoolValue, "Volume", true, "");
if (room is IPrivacy privacyRoom)
{
volume.HasPrivacyMute = true;
volume.PrivacyMuted = privacyRoom.PrivacyModeIsOnFeedback.BoolValue;
}
volumes.Add("master", volume);
}
}
var state = new RoomStateMessage
{
Configuration = GetRoomConfiguration(room),
ActivityMode = 1,
IsOn = room.OnFeedback.BoolValue,
SelectedSourceKey = sourceKey,
Volumes = volumes,
IsWarmingUp = room.IsWarmingUpFeedback.BoolValue,
IsCoolingDown = room.IsCoolingDownFeedback.BoolValue
};
if (room is IEssentialsHuddleVtc1Room vtcRoom)
{
state.IsInCall = vtcRoom.InCallFeedback.BoolValue;
}
return state;
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Error getting full status", this);
return null;
}
}
/// <summary>
/// Determines the configuration of the room and the details about the devices associated with the room
/// <param name="room"></param>
/// <returns></returns>
private RoomConfiguration GetRoomConfiguration(IEssentialsRoom room)
{
try
{
var configuration = new RoomConfiguration
{
//ShutdownPromptSeconds = room.ShutdownPromptSeconds,
TouchpanelKeys = DeviceManager.AllDevices.
OfType<IMobileControlTouchpanelController>()
.Where((tp) => tp.DefaultRoomKey.Equals(room.Key, StringComparison.InvariantCultureIgnoreCase))
.Select(tp => tp.Key).ToList()
};
try
{
var zrcTp = DeviceManager.AllDevices.OfType<IMobileControlTouchpanelController>().SingleOrDefault((tp) => tp.ZoomRoomController);
configuration.ZoomRoomControllerKey = zrcTp?.Key;
}
catch
{
configuration.ZoomRoomControllerKey = room.Key;
}
if (room is IHasCiscoNavigatorTouchpanel ciscoNavRoom)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting CiscoNavigatorKey to: {ciscoNavRoom.CiscoNavigatorTouchpanelKey}", this);
configuration.CiscoNavigatorKey = ciscoNavRoom.CiscoNavigatorTouchpanelKey;
}
// find the room combiner for this room by checking if the room is in the list of rooms for the room combiner
var roomCombiner = DeviceManager.AllDevices.OfType<IEssentialsRoomCombiner>().FirstOrDefault();
configuration.RoomCombinerKey = roomCombiner?.Key;
if (room is IEssentialsRoomPropertiesConfig propertiesConfig)
{
configuration.HelpMessage = propertiesConfig.PropertiesConfig.HelpMessageForDisplay;
}
if (room is IEssentialsHuddleSpaceRoom huddleRoom && !string.IsNullOrEmpty(huddleRoom.PropertiesConfig.HelpMessageForDisplay))
{
this.LogVerbose("Getting huddle room config");
configuration.HelpMessage = huddleRoom.PropertiesConfig.HelpMessageForDisplay;
configuration.UiBehavior = huddleRoom.PropertiesConfig.UiBehavior;
configuration.DefaultPresentationSourceKey = huddleRoom.PropertiesConfig.DefaultSourceItem;
}
if (room is IEssentialsHuddleVtc1Room vtc1Room && !string.IsNullOrEmpty(vtc1Room.PropertiesConfig.HelpMessageForDisplay))
{
this.LogVerbose("Getting vtc room config");
configuration.HelpMessage = vtc1Room.PropertiesConfig.HelpMessageForDisplay;
configuration.UiBehavior = vtc1Room.PropertiesConfig.UiBehavior;
configuration.DefaultPresentationSourceKey = vtc1Room.PropertiesConfig.DefaultSourceItem;
}
if (room is IEssentialsTechRoom techRoom && !string.IsNullOrEmpty(techRoom.PropertiesConfig.HelpMessage))
{
this.LogVerbose("Getting tech room config");
configuration.HelpMessage = techRoom.PropertiesConfig.HelpMessage;
}
if (room is IHasVideoCodec vcRoom)
{
if (vcRoom.VideoCodec != null)
{
this.LogVerbose("Getting codec config");
var type = vcRoom.VideoCodec.GetType();
configuration.HasVideoConferencing = true;
configuration.VideoCodecKey = vcRoom.VideoCodec.Key;
configuration.VideoCodecIsZoomRoom = type.Name.Equals("ZoomRoom", StringComparison.InvariantCultureIgnoreCase);
}
}
;
if (room is IHasAudioCodec acRoom)
{
if (acRoom.AudioCodec != null)
{
this.LogVerbose("Getting audio codec config");
configuration.HasAudioConferencing = true;
configuration.AudioCodecKey = acRoom.AudioCodec.Key;
}
}
if (room is IHasMatrixRouting matrixRoutingRoom)
{
this.LogVerbose("Getting matrix routing config");
configuration.MatrixRoutingKey = matrixRoutingRoom.MatrixRoutingDeviceKey;
configuration.EndpointKeys = matrixRoutingRoom.EndpointKeys;
}
if (room is IEnvironmentalControls envRoom)
{
this.LogVerbose("Getting environmental controls config. RoomHasEnvironmentalControls: {hasEnvironmentalControls}", envRoom.HasEnvironmentalControlDevices);
configuration.HasEnvironmentalControls = envRoom.HasEnvironmentalControlDevices;
if (envRoom.HasEnvironmentalControlDevices)
{
this.LogVerbose("Room Has {count} Environmental Control Devices.", envRoom.EnvironmentalControlDevices.Count);
foreach (var dev in envRoom.EnvironmentalControlDevices)
{
this.LogVerbose("Adding environmental device: {key}", dev.Key);
eEnvironmentalDeviceTypes type = eEnvironmentalDeviceTypes.None;
if (dev is ILightingScenes)
{
type = eEnvironmentalDeviceTypes.Lighting;
}
else if (dev is ShadeBase || dev is IShadesOpenCloseStop || dev is IShadesOpenClosePreset)
{
type = eEnvironmentalDeviceTypes.Shade;
}
else if (dev is IShades)
{
type = eEnvironmentalDeviceTypes.ShadeController;
}
else if (dev is ISwitchedOutput)
{
type = eEnvironmentalDeviceTypes.Relay;
}
this.LogVerbose("Environmental Device Type: {type}", type);
var envDevice = new EnvironmentalDeviceConfiguration(dev.Key, type);
configuration.EnvironmentalDevices.Add(envDevice);
}
}
else
{
this.LogVerbose("Room Has No Environmental Control Devices");
}
}
if (room is IHasDefaultDisplay defDisplayRoom)
{
this.LogVerbose("Getting default display config");
configuration.DefaultDisplayKey = defDisplayRoom.DefaultDisplay.Key;
configuration.Destinations.Add(eSourceListItemDestinationTypes.defaultDisplay, defDisplayRoom.DefaultDisplay.Key);
}
if (room is IHasMultipleDisplays multiDisplayRoom)
{
this.LogVerbose("Getting multiple display config");
if (multiDisplayRoom.Displays == null)
{
this.LogVerbose("Displays collection is null");
}
else
{
this.LogVerbose("Displays collection exists");
configuration.Destinations = multiDisplayRoom.Displays.ToDictionary(kv => kv.Key, kv => kv.Value.Key);
}
}
if (room is IHasAccessoryDevices accRoom)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Getting accessory devices config", this);
if (accRoom.AccessoryDeviceKeys == null)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Accessory devices collection is null", this);
}
else
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Accessory devices collection exists", this);
configuration.AccessoryDeviceKeys = accRoom.AccessoryDeviceKeys;
}
}
var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
if (sourceList != null)
{
this.LogVerbose("Getting source list config");
configuration.SourceList = sourceList;
configuration.HasRoutingControls = true;
foreach (var source in sourceList)
{
if (source.Value.SourceDevice is Devices.Common.IRSetTopBoxBase)
{
configuration.HasSetTopBoxControls = true;
continue;
}
else if (source.Value.SourceDevice is CameraBase)
{
configuration.HasCameraControls = true;
continue;
}
}
}
var destinationList = ConfigReader.ConfigObject.GetDestinationListForKey(room.DestinationListKey);
if (destinationList != null)
{
configuration.DestinationList = destinationList;
}
var audioControlPointList = ConfigReader.ConfigObject.GetAudioControlPointListForKey(room.AudioControlPointListKey);
if (audioControlPointList != null)
{
configuration.AudioControlPointList = audioControlPointList;
}
var cameraList = ConfigReader.ConfigObject.GetCameraListForKey(room.CameraListKey);
if (cameraList != null)
{
configuration.CameraList = cameraList;
}
return configuration;
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception getting room configuration");
return new RoomConfiguration();
}
}
}
public class RoomStateMessage : DeviceStateMessageBase
{
[JsonProperty("configuration", NullValueHandling = NullValueHandling.Ignore)]
public RoomConfiguration Configuration { get; set; }
[JsonProperty("activityMode", NullValueHandling = NullValueHandling.Ignore)]
public int? ActivityMode { get; set; }
[JsonProperty("advancedSharingActive", NullValueHandling = NullValueHandling.Ignore)]
public bool? AdvancedSharingActive { get; set; }
[JsonProperty("isOn", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsOn { get; set; }
[JsonProperty("isWarmingUp", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsWarmingUp { get; set; }
[JsonProperty("isCoolingDown", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsCoolingDown { get; set; }
[JsonProperty("selectedSourceKey", NullValueHandling = NullValueHandling.Ignore)]
public string SelectedSourceKey { get; set; }
[JsonProperty("share", NullValueHandling = NullValueHandling.Ignore)]
public ShareState Share { get; set; }
[JsonProperty("volumes", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, Volume> Volumes { get; set; }
[JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsInCall { get; set; }
}
public class ShareState
{
[JsonProperty("currentShareText", NullValueHandling = NullValueHandling.Ignore)]
public string CurrentShareText { get; set; }
[JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)]
public bool? Enabled { get; set; }
[JsonProperty("isSharing", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsSharing { get; set; }
}
/// <summary>
/// Represents the capabilities of the room and the associated device info
/// </summary>
public class RoomConfiguration
{
//[JsonProperty("shutdownPromptSeconds", NullValueHandling = NullValueHandling.Ignore)]
//public int? ShutdownPromptSeconds { get; set; }
[JsonProperty("hasVideoConferencing", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasVideoConferencing { get; set; }
[JsonProperty("videoCodecIsZoomRoom", NullValueHandling = NullValueHandling.Ignore)]
public bool? VideoCodecIsZoomRoom { get; set; }
[JsonProperty("hasAudioConferencing", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasAudioConferencing { get; set; }
[JsonProperty("hasEnvironmentalControls", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasEnvironmentalControls { get; set; }
[JsonProperty("hasCameraControls", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasCameraControls { get; set; }
[JsonProperty("hasSetTopBoxControls", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasSetTopBoxControls { get; set; }
[JsonProperty("hasRoutingControls", NullValueHandling = NullValueHandling.Ignore)]
public bool? HasRoutingControls { get; set; }
[JsonProperty("touchpanelKeys", NullValueHandling = NullValueHandling.Ignore)]
public List<string> TouchpanelKeys { get; set; }
[JsonProperty("zoomRoomControllerKey", NullValueHandling = NullValueHandling.Ignore)]
public string ZoomRoomControllerKey { get; set; }
[JsonProperty("ciscoNavigatorKey", NullValueHandling = NullValueHandling.Ignore)]
public string CiscoNavigatorKey { get; set; }
[JsonProperty("videoCodecKey", NullValueHandling = NullValueHandling.Ignore)]
public string VideoCodecKey { get; set; }
[JsonProperty("audioCodecKey", NullValueHandling = NullValueHandling.Ignore)]
public string AudioCodecKey { get; set; }
[JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)]
public string MatrixRoutingKey { get; set; }
[JsonProperty("endpointKeys", NullValueHandling = NullValueHandling.Ignore)]
public List<string> EndpointKeys { get; set; }
[JsonProperty("accessoryDeviceKeys", NullValueHandling = NullValueHandling.Ignore)]
public List<string> AccessoryDeviceKeys { get; set; }
[JsonProperty("defaultDisplayKey", NullValueHandling = NullValueHandling.Ignore)]
public string DefaultDisplayKey { get; set; }
[JsonProperty("destinations", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<eSourceListItemDestinationTypes, string> Destinations { get; set; }
[JsonProperty("environmentalDevices", NullValueHandling = NullValueHandling.Ignore)]
public List<EnvironmentalDeviceConfiguration> EnvironmentalDevices { get; set; }
[JsonProperty("sourceList", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, SourceListItem> SourceList { get; set; }
[JsonProperty("destinationList", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, DestinationListItem> DestinationList { get; set; }
[JsonProperty("audioControlPointList", NullValueHandling = NullValueHandling.Ignore)]
public AudioControlPointListItem AudioControlPointList { get; set; }
[JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, CameraListItem> CameraList { get; set; }
[JsonProperty("defaultPresentationSourceKey", NullValueHandling = NullValueHandling.Ignore)]
public string DefaultPresentationSourceKey { get; set; }
[JsonProperty("helpMessage", NullValueHandling = NullValueHandling.Ignore)]
public string HelpMessage { get; set; }
[JsonProperty("techPassword", NullValueHandling = NullValueHandling.Ignore)]
public string TechPassword { get; set; }
[JsonProperty("uiBehavior", NullValueHandling = NullValueHandling.Ignore)]
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
[JsonProperty("supportsAdvancedSharing", NullValueHandling = NullValueHandling.Ignore)]
public bool? SupportsAdvancedSharing { get; set; }
[JsonProperty("userCanChangeShareMode", NullValueHandling = NullValueHandling.Ignore)]
public bool? UserCanChangeShareMode { get; set; }
[JsonProperty("roomCombinerKey", NullValueHandling = NullValueHandling.Ignore)]
public string RoomCombinerKey { get; set; }
public RoomConfiguration()
{
Destinations = new Dictionary<eSourceListItemDestinationTypes, string>();
EnvironmentalDevices = new List<EnvironmentalDeviceConfiguration>();
SourceList = new Dictionary<string, SourceListItem>();
TouchpanelKeys = new List<string>();
}
}
public class EnvironmentalDeviceConfiguration
{
[JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Ignore)]
public string DeviceKey { get; private set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty("deviceType", NullValueHandling = NullValueHandling.Ignore)]
public eEnvironmentalDeviceTypes DeviceType { get; private set; }
public EnvironmentalDeviceConfiguration(string key, eEnvironmentalDeviceTypes type)
{
DeviceKey = key;
DeviceType = type;
}
}
public enum eEnvironmentalDeviceTypes
{
None,
Lighting,
Shade,
ShadeController,
Relay,
}
public class ApiTouchPanelToken
{
[JsonProperty("touchPanels", NullValueHandling = NullValueHandling.Ignore)]
public List<JoinToken> TouchPanels { get; set; } = new List<JoinToken>();
[JsonProperty("userAppUrl", NullValueHandling = NullValueHandling.Ignore)]
public string UserAppUrl { get; set; } = "";
}
#if SERIES3
public class SourceSelectMessageContent
{
public string SourceListItem { get; set; }
public string SourceListKey { get; set; }
}
public class DirectRoute
{
public string SourceKey { get; set; }
public string DestinationKey { get; set; }
}
/// <summary>
///
/// </summary>
/// <param name="b"></param>
public delegate void PressAndHoldAction(bool b);
#endif
}

View File

@@ -1,96 +0,0 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Room.MobileControl
{
/// <summary>
/// Contains all of the default joins that map to API funtions
/// </summary>
public class SourceDeviceMapDictionary : Dictionary<string, uint>
{
public SourceDeviceMapDictionary()
{
var dictionary = new Dictionary<string, uint>
{
{"preset01", 101},
{"preset02", 102},
{"preset03", 103},
{"preset04", 104},
{"preset05", 105},
{"preset06", 106},
{"preset07", 107},
{"preset08", 108},
{"preset09", 109},
{"preset10", 110},
{"preset11", 111},
{"preset12", 112},
{"preset13", 113},
{"preset14", 114},
{"preset15", 115},
{"preset16", 116},
{"preset17", 117},
{"preset18", 118},
{"preset19", 119},
{"preset20", 120},
{"preset21", 121},
{"preset22", 122},
{"preset23", 123},
{"preset24", 124},
{"num0", 130},
{"num1", 131},
{"num2", 132},
{"num3", 133},
{"num4", 134},
{"num5", 135},
{"num6", 136},
{"num7", 137},
{"num8", 138},
{"num9", 139},
{"numDash", 140},
{"numEnter", 141},
{"chanUp", 142},
{"chanDown", 143},
{"lastChan", 144},
{"exit", 145},
{"powerToggle", 146},
{"red", 147},
{"green", 148},
{"yellow", 149},
{"blue", 150},
{"video", 151},
{"previous", 152},
{"next", 153},
{"rewind", 154},
{"ffwd", 155},
{"closedCaption", 156},
{"stop", 157},
{"pause", 158},
{"up", 159},
{"down", 160},
{"left", 161},
{"right", 162},
{"settings", 163},
{"info", 164},
{"return", 165},
{"guide", 166},
{"reboot", 167},
{"dvrList", 168},
{"replay", 169},
{"play", 170},
{"select", 171},
{"record", 172},
{"menu", 173},
{"topMenu", 174},
{"prevTrack", 175},
{"nextTrack", 176},
{"powerOn", 177},
{"powerOff", 178},
{"dot", 179}
};
foreach (var item in dictionary)
{
Add(item.Key, item.Value);
}
}
}
}

View File

@@ -1,77 +0,0 @@
using PepperDash.Core;
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Services
{
public class MobileControlApiService
{
private readonly HttpClient _client;
public MobileControlApiService(string apiUrl)
{
var handler = new HttpClientHandler
{
AllowAutoRedirect = false,
ServerCertificateCustomValidationCallback = (req, cert, certChain, errors) => true
};
_client = new HttpClient(handler);
}
public async Task<AuthorizationResponse> SendAuthorizationRequest(string apiUrl, string grantCode, string systemUuid)
{
try
{
var request = new HttpRequestMessage(HttpMethod.Get, $"{apiUrl}/system/{systemUuid}/authorize?grantCode={grantCode}");
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Sending authorization request to {host}", null, request.RequestUri);
var response = await _client.SendAsync(request);
var authResponse = new AuthorizationResponse
{
Authorized = response.StatusCode == System.Net.HttpStatusCode.OK
};
if (authResponse.Authorized)
{
return authResponse;
}
if (response.StatusCode == System.Net.HttpStatusCode.Moved)
{
var location = response.Headers.Location;
authResponse.Reason = $"ERROR: Mobile Control API has moved. Please adjust configuration to \"{location}\"";
return authResponse;
}
var responseString = await response.Content.ReadAsStringAsync();
switch (responseString)
{
case "codeNotFound":
authResponse.Reason = $"Authorization failed. Code not found for system UUID {systemUuid}";
break;
case "uuidNotFound":
authResponse.Reason = $"Authorization failed. System UUID {systemUuid} not found. Check Essentials configuration.";
break;
default:
authResponse.Reason = $"Authorization failed. Response {response.StatusCode}: {responseString}";
break;
}
return authResponse;
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Error authorizing with Mobile Control");
return new AuthorizationResponse { Authorized = false, Reason = ex.Message };
}
}
}
}

View File

@@ -1,11 +0,0 @@
using PepperDash.Core;
namespace PepperDash.Essentials.Touchpanel
{
public interface ITheme : IKeyed
{
string Theme { get; }
void UpdateTheme(string theme);
}
}

View File

@@ -1,25 +0,0 @@
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Touchpanel
{
public interface ITswAppControl : IKeyed
{
BoolFeedback AppOpenFeedback { get; }
void HideOpenApp();
void CloseOpenApp();
void OpenApp();
}
public interface ITswZoomControl : IKeyed
{
BoolFeedback ZoomIncomingCallFeedback { get; }
BoolFeedback ZoomInCallFeedback { get; }
void EndZoomCall();
}
}

View File

@@ -1,59 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.AppServer.Messengers;
namespace PepperDash.Essentials.Touchpanel
{
public class ITswAppControlMessenger : MessengerBase
{
private readonly ITswAppControl _appControl;
public ITswAppControlMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
_appControl = device as ITswAppControl;
}
protected override void RegisterActions()
{
if (_appControl == null)
{
this.LogInformation("{deviceKey} does not implement ITswAppControl", _device.Key);
return;
}
AddAction($"/fullStatus", (id, context) => SendFullStatus());
AddAction($"/openApp", (id, context) => _appControl.OpenApp());
AddAction($"/closeApp", (id, context) => _appControl.CloseOpenApp());
AddAction($"/hideApp", (id, context) => _appControl.HideOpenApp());
_appControl.AppOpenFeedback.OutputChange += (s, a) =>
{
PostStatusMessage(JToken.FromObject(new
{
appOpen = a.BoolValue
}));
};
}
private void SendFullStatus()
{
var message = new TswAppStateMessage
{
AppOpen = _appControl.AppOpenFeedback.BoolValue,
};
PostStatusMessage(message);
}
}
public class TswAppStateMessage : DeviceStateMessageBase
{
[JsonProperty("appOpen", NullValueHandling = NullValueHandling.Ignore)]
public bool? AppOpen { get; set; }
}
}

View File

@@ -1,73 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.AppServer.Messengers;
namespace PepperDash.Essentials.Touchpanel
{
public class ITswZoomControlMessenger : MessengerBase
{
private readonly ITswZoomControl _zoomControl;
public ITswZoomControlMessenger(string key, string messagePath, Device device) : base(key, messagePath, device)
{
_zoomControl = device as ITswZoomControl;
}
protected override void RegisterActions()
{
if (_zoomControl == null)
{
this.LogInformation("{deviceKey} does not implement ITswZoomControl", _device.Key);
return;
}
AddAction($"/fullStatus", (id, context) => SendFullStatus());
AddAction($"/endCall", (id, context) => _zoomControl.EndZoomCall());
_zoomControl.ZoomIncomingCallFeedback.OutputChange += (s, a) =>
{
PostStatusMessage(JToken.FromObject(new
{
incomingCall = a.BoolValue,
inCall = _zoomControl.ZoomInCallFeedback.BoolValue
}));
};
_zoomControl.ZoomInCallFeedback.OutputChange += (s, a) =>
{
PostStatusMessage(JToken.FromObject(
new
{
inCall = a.BoolValue,
incomingCall = _zoomControl.ZoomIncomingCallFeedback.BoolValue
}));
};
}
private void SendFullStatus()
{
var message = new TswZoomStateMessage
{
InCall = _zoomControl?.ZoomInCallFeedback.BoolValue,
IncomingCall = _zoomControl?.ZoomIncomingCallFeedback.BoolValue
};
PostStatusMessage(message);
}
}
public class TswZoomStateMessage : DeviceStateMessageBase
{
[JsonProperty("inCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? InCall { get; set; }
[JsonProperty("incomingCall", NullValueHandling = NullValueHandling.Ignore)]
public bool? IncomingCall { get; set; }
}
}

View File

@@ -1,571 +0,0 @@
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceInfo;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Touchpanel
{
//public interface IMobileControlTouchpanelController
//{
// StringFeedback AppUrlFeedback { get; }
// string DefaultRoomKey { get; }
// string DeviceKey { get; }
//}
public class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlTouchpanelController, ITheme
{
private readonly MobileControlTouchpanelProperties localConfig;
private IMobileControlRoomMessenger _bridge;
private string _appUrl;
public StringFeedback AppUrlFeedback { get; private set; }
private readonly StringFeedback QrCodeUrlFeedback;
private readonly StringFeedback McServerUrlFeedback;
private readonly StringFeedback UserCodeFeedback;
private readonly BoolFeedback _appOpenFeedback;
public BoolFeedback AppOpenFeedback => _appOpenFeedback;
private readonly BoolFeedback _zoomIncomingCallFeedback;
public BoolFeedback ZoomIncomingCallFeedback => _zoomIncomingCallFeedback;
private readonly BoolFeedback _zoomInCallFeedback;
public event DeviceInfoChangeHandler DeviceInfoChanged;
public BoolFeedback ZoomInCallFeedback => _zoomInCallFeedback;
public FeedbackCollection<Feedback> Feedbacks { get; private set; }
public FeedbackCollection<Feedback> ZoomFeedbacks { get; private set; }
public string DefaultRoomKey => _config.DefaultRoomKey;
public bool UseDirectServer => localConfig.UseDirectServer;
public bool ZoomRoomController => localConfig.ZoomRoomController;
public string Theme => localConfig.Theme;
public StringFeedback ThemeFeedback { get; private set; }
public DeviceInfo DeviceInfo => new DeviceInfo();
public MobileControlTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, MobileControlTouchpanelProperties config) : base(key, name, panel, config)
{
localConfig = config;
AddPostActivationAction(SubscribeForMobileControlUpdates);
ThemeFeedback = new StringFeedback($"{Key}-theme", () => Theme);
AppUrlFeedback = new StringFeedback($"{Key}-appUrl", () => _appUrl);
QrCodeUrlFeedback = new StringFeedback($"{Key}-qrCodeUrl", () => _bridge?.QrCodeUrl);
McServerUrlFeedback = new StringFeedback($"{Key}-mcServerUrl", () => _bridge?.McServerUrl);
UserCodeFeedback = new StringFeedback($"{Key}-userCode", () => _bridge?.UserCode);
_appOpenFeedback = new BoolFeedback($"{Key}-appOpen", () =>
{
if (Panel is TswX60BaseClass tsX60)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"x60 sending {tsX60.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.BoolValue}");
return !tsX60.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.BoolValue;
}
if (Panel is TswX70Base tsX70)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"x70 sending {tsX70.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue}");
return !tsX70.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue;
}
return false;
});
_zoomIncomingCallFeedback = new BoolFeedback($"{Key}-zoomIncomingCall", () =>
{
if (Panel is TswX60WithZoomRoomAppReservedSigs tsX60)
{
return tsX60.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.BoolValue;
}
if (Panel is TswX70Base tsX70)
{
return tsX70.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.BoolValue;
}
return false;
});
_zoomInCallFeedback = new BoolFeedback($"{Key}-zoomInCall", () =>
{
if (Panel is TswX60WithZoomRoomAppReservedSigs tsX60)
{
return tsX60.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.BoolValue;
}
if (Panel is TswX70Base tsX70)
{
return tsX70.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.BoolValue;
}
return false;
});
Feedbacks = new FeedbackCollection<Feedback>
{
AppUrlFeedback, QrCodeUrlFeedback, McServerUrlFeedback, UserCodeFeedback
};
ZoomFeedbacks = new FeedbackCollection<Feedback> {
AppOpenFeedback, _zoomInCallFeedback, _zoomIncomingCallFeedback
};
RegisterForExtenders();
}
public void UpdateTheme(string theme)
{
localConfig.Theme = theme;
var props = JToken.FromObject(localConfig);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault((d) => d.Key == Key);
if (deviceConfig == null) { return; }
deviceConfig.Properties = props;
ConfigWriter.UpdateDeviceConfig(deviceConfig);
}
private void RegisterForExtenders()
{
if (Panel is TswXX70Base x70Panel)
{
x70Panel.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
UpdateZoomFeedbacks();
if (!x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue)
{
x70Panel.ExtenderButtonToolbarReservedSigs.ShowButtonToolbar();
x70Panel.ExtenderButtonToolbarReservedSigs.Button2On();
}
else
{
x70Panel.ExtenderButtonToolbarReservedSigs.HideButtonToolbar();
x70Panel.ExtenderButtonToolbarReservedSigs.Button2Off();
}
};
x70Panel.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 Zoom Room Ap Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number)
{
ZoomIncomingCallFeedback.FireUpdate();
}
else if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number)
{
ZoomInCallFeedback.FireUpdate();
}
};
x70Panel.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) =>
{
DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
var handler = DeviceInfoChanged;
if (handler == null)
{
return;
}
handler(this, new DeviceInfoEventArgs(DeviceInfo));
};
x70Panel.ExtenderApplicationControlReservedSigs.Use();
x70Panel.ExtenderZoomRoomAppReservedSigs.Use();
x70Panel.ExtenderEthernetReservedSigs.Use();
x70Panel.ExtenderButtonToolbarReservedSigs.Use();
x70Panel.ExtenderButtonToolbarReservedSigs.Button1Off();
x70Panel.ExtenderButtonToolbarReservedSigs.Button3Off();
x70Panel.ExtenderButtonToolbarReservedSigs.Button4Off();
x70Panel.ExtenderButtonToolbarReservedSigs.Button5Off();
x70Panel.ExtenderButtonToolbarReservedSigs.Button6Off();
return;
}
if (Panel is TswX60WithZoomRoomAppReservedSigs x60withZoomApp)
{
x60withZoomApp.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
if (a.Sig.Number == x60withZoomApp.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.Number)
{
AppOpenFeedback.FireUpdate();
}
};
x60withZoomApp.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 Zoom Room App Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number)
{
ZoomIncomingCallFeedback.FireUpdate();
}
else if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number)
{
ZoomInCallFeedback.FireUpdate();
}
};
x60withZoomApp.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) =>
{
DeviceInfo.MacAddress = x60withZoomApp.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
DeviceInfo.IpAddress = x60withZoomApp.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
var handler = DeviceInfoChanged;
if (handler == null)
{
return;
}
handler(this, new DeviceInfoEventArgs(DeviceInfo));
};
x60withZoomApp.ExtenderZoomRoomAppReservedSigs.Use();
x60withZoomApp.ExtenderApplicationControlReservedSigs.Use();
x60withZoomApp.ExtenderEthernetReservedSigs.Use();
}
}
public override bool CustomActivate()
{
var appMessenger = new ITswAppControlMessenger($"appControlMessenger-{Key}", $"/device/{Key}", this);
var zoomMessenger = new ITswZoomControlMessenger($"zoomControlMessenger-{Key}", $"/device/{Key}", this);
var themeMessenger = new ThemeMessenger($"themeMessenger-{Key}", $"/device/{Key}", this);
var mc = DeviceManager.AllDevices.OfType<IMobileControl>().FirstOrDefault();
if (mc == null)
{
return base.CustomActivate();
}
if (!(Panel is TswXX70Base) && !(Panel is TswX60WithZoomRoomAppReservedSigs))
{
mc.AddDeviceMessenger(themeMessenger);
return base.CustomActivate();
}
mc.AddDeviceMessenger(appMessenger);
mc.AddDeviceMessenger(zoomMessenger);
mc.AddDeviceMessenger(themeMessenger);
return base.CustomActivate();
}
protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"System Device Extender args: ${args.Event}:${args.Sig}");
}
protected override void SetupPanelDrivers(string roomKey)
{
AppUrlFeedback.LinkInputSig(Panel.StringInput[1]);
QrCodeUrlFeedback.LinkInputSig(Panel.StringInput[2]);
McServerUrlFeedback.LinkInputSig(Panel.StringInput[3]);
UserCodeFeedback.LinkInputSig(Panel.StringInput[4]);
Panel.OnlineStatusChange += (sender, args) =>
{
UpdateFeedbacks();
this.LogInformation("Sending {appUrl} on join 1", AppUrlFeedback.StringValue);
Panel.StringInput[1].StringValue = AppUrlFeedback.StringValue;
Panel.StringInput[2].StringValue = QrCodeUrlFeedback.StringValue;
Panel.StringInput[3].StringValue = McServerUrlFeedback.StringValue;
Panel.StringInput[4].StringValue = UserCodeFeedback.StringValue;
};
}
private void SubscribeForMobileControlUpdates()
{
foreach (var dev in DeviceManager.AllDevices)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"{dev.Key}:{dev.GetType().Name}");
}
var mcList = DeviceManager.AllDevices.OfType<MobileControlSystemController>().ToList();
if (mcList.Count == 0)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control controller found");
return;
}
// use first in list, since there should only be one.
var mc = mcList[0];
var bridge = mc.GetRoomBridge(_config.DefaultRoomKey);
if (bridge == null)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control bridge for {_config.DefaultRoomKey} found ");
return;
}
_bridge = bridge;
_bridge.UserCodeChanged += UpdateFeedbacks;
_bridge.AppUrlChanged += (s, a) =>
{
this.LogInformation("AppURL changed");
SetAppUrl(_bridge.AppUrl);
UpdateFeedbacks(s, a);
};
SetAppUrl(_bridge.AppUrl);
}
public void SetAppUrl(string url)
{
_appUrl = url;
AppUrlFeedback.FireUpdate();
}
private void UpdateFeedbacks(object sender, EventArgs args)
{
UpdateFeedbacks();
}
private void UpdateFeedbacks()
{
foreach (var feedback in Feedbacks) { this.LogDebug("Updating {feedbackKey}", feedback.Key); feedback.FireUpdate(); }
}
private void UpdateZoomFeedbacks()
{
foreach (var feedback in ZoomFeedbacks)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"Updating {feedback.Key}");
feedback.FireUpdate();
}
}
public void HideOpenApp()
{
if (Panel is TswX70Base x70Panel)
{
x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplication();
return;
}
if (Panel is TswX60BaseClass x60Panel)
{
x60Panel.ExtenderApplicationControlReservedSigs.HideOpenApplication();
return;
}
}
public void OpenApp()
{
if (Panel is TswX70Base x70Panel)
{
x70Panel.ExtenderApplicationControlReservedSigs.OpenApplication();
return;
}
if (Panel is TswX60WithZoomRoomAppReservedSigs)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"X60 panel does not support zoom app");
return;
}
}
public void CloseOpenApp()
{
if (Panel is TswX70Base x70Panel)
{
x70Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication();
return;
}
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
{
x60Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication();
return;
}
}
public void EndZoomCall()
{
if (Panel is TswX70Base x70Panel)
{
x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall();
return;
}
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
{
x60Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall();
return;
}
}
public void UpdateDeviceInfo()
{
if (Panel is TswXX70Base x70Panel)
{
DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
var handler = DeviceInfoChanged;
if (handler == null)
{
return;
}
handler(this, new DeviceInfoEventArgs(DeviceInfo));
}
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
{
DeviceInfo.MacAddress = x60Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
DeviceInfo.IpAddress = x60Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
var handler = DeviceInfoChanged;
if (handler == null)
{
return;
}
handler(this, new DeviceInfoEventArgs(DeviceInfo));
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
}
}
public class MobileControlTouchpanelControllerFactory : EssentialsPluginDeviceFactory<MobileControlTouchpanelController>
{
public MobileControlTouchpanelControllerFactory()
{
TypeNames = new List<string>() { "mccrestronapp", "mctsw550", "mctsw750", "mctsw1050", "mctsw560", "mctsw760", "mctsw1060", "mctsw570", "mctsw770", "mcts770", "mctsw1070", "mcts1070", "mcxpanel" };
MinimumEssentialsFrameworkVersion = "2.0.0";
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
var comm = CommFactory.GetControlPropertiesConfig(dc);
var props = JsonConvert.DeserializeObject<MobileControlTouchpanelProperties>(dc.Properties.ToString());
var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName);
if (panel == null)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Unable to create Touchpanel for type {0}. Touchpanel Controller WILL NOT function correctly", dc.Type);
}
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Factory Attempting to create new MobileControlTouchpanelController");
var panelController = new MobileControlTouchpanelController(dc.Key, dc.Name, panel, props);
return panelController;
}
private BasicTriListWithSmartObject GetPanelForType(string type, uint id, string projectName)
{
type = type.ToLower().Replace("mc", "");
try
{
if (type == "crestronapp")
{
var app = new CrestronApp(id, Global.ControlSystem);
app.ParameterProjectName.Value = projectName;
return app;
}
else if (type == "xpanel")
return new XpanelForHtml5(id, Global.ControlSystem);
else if (type == "tsw550")
return new Tsw550(id, Global.ControlSystem);
else if (type == "tsw552")
return new Tsw552(id, Global.ControlSystem);
else if (type == "tsw560")
return new Tsw560(id, Global.ControlSystem);
else if (type == "tsw750")
return new Tsw750(id, Global.ControlSystem);
else if (type == "tsw752")
return new Tsw752(id, Global.ControlSystem);
else if (type == "tsw760")
return new Tsw760(id, Global.ControlSystem);
else if (type == "tsw1050")
return new Tsw1050(id, Global.ControlSystem);
else if (type == "tsw1052")
return new Tsw1052(id, Global.ControlSystem);
else if (type == "tsw1060")
return new Tsw1060(id, Global.ControlSystem);
else if (type == "tsw570")
return new Tsw570(id, Global.ControlSystem);
else if (type == "tsw770")
return new Tsw770(id, Global.ControlSystem);
else if (type == "ts770")
return new Ts770(id, Global.ControlSystem);
else if (type == "tsw1070")
return new Tsw1070(id, Global.ControlSystem);
else if (type == "ts1070")
return new Ts1070(id, Global.ControlSystem);
else
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW controller with type '{0}'", type);
return null;
}
}
catch (Exception e)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
return null;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More