mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-28 20:04:56 +00:00
Compare commits
15 Commits
v2.0.0-rc.
...
v2.1.0-fea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6fdc14059 | ||
|
|
3d91723ab0 | ||
|
|
4dcb3946c5 | ||
|
|
a288fc5890 | ||
|
|
9ef8698387 | ||
|
|
daccf9eb77 | ||
|
|
6333443ecb | ||
|
|
51414e7d26 | ||
|
|
3222c73282 | ||
|
|
5df7b57c43 | ||
|
|
7631c7a8a1 | ||
|
|
16e2529378 | ||
|
|
8f485071c6 | ||
|
|
4eabd82878 | ||
|
|
428f9f34bd |
@@ -9,6 +9,14 @@ 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
|
||||
@@ -34,10 +42,29 @@ 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
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,41 @@
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<None Include="$(PackageOutputPath)\$(AssemblyName)\*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||
<None Include="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz" Condition="$(ProjectType) == 'Program'">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>build;</PackagePath>
|
||||
</None>
|
||||
<None Include="$(PackageOutputPath)\$(AssemblyName)\*.cplz" Condition="$(ProjectType) == 'ProgramLibrary'">
|
||||
<None Include="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz" Condition="$(ProjectType) == 'ProgramLibrary'">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>build;</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Target Name="Create CPLZ" AfterTargets="Build; AfterRebuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
|
||||
<PropertyGroup Condition="$(ProjectType) == 'ProgramLibrary'">
|
||||
<FileName>$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz</FileName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(ProjectType) == 'Program'">
|
||||
<FileName>$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz</FileName>
|
||||
</PropertyGroup>
|
||||
<Target Name="DeleteCPLZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != '' And Exists($(FileName))">
|
||||
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz">
|
||||
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
||||
</Delete>
|
||||
<Message Text="Deleted files: '@(DeletedList)'" />
|
||||
</Target>
|
||||
<Target Name="CreateCPLZ" AfterTargets="Build" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''" DependsOnTargets="DeleteCPLZ">
|
||||
<Message Text="Creating CPLZ $(TargetDir)"></Message>
|
||||
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
|
||||
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)" Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
|
||||
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
|
||||
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
|
||||
<Copy SourceFiles="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cplz" DestinationFiles="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz" />
|
||||
</Target>
|
||||
<Target Name="Copy CPZ NET6" AfterTargets="SimplSharpPostProcess" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' == 'net6.0' ) Or ( '$(TargetFramework)' == 'net8.0' ))">
|
||||
<Message Text="Copying CPZ"></Message>
|
||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
||||
<Target Name="DeleteCPZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'Program' And $(TargetDir) != '' And Exists($(FileName))">
|
||||
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz">
|
||||
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
||||
</Delete>
|
||||
<Message Text="Deleted files: '@(DeletedList)'" />
|
||||
</Target>
|
||||
<Target Name="Copy CPZ NET47" AfterTargets="SimplSharpPostProcess47" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' != 'net6.0' ) And ( '$(TargetFramework)' != 'net8.0' ))">
|
||||
<Target Name="Copy CPZ" AfterTargets="SimplSharpPostProcess" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' != 'net6.0' ) And ( '$(TargetFramework)' != 'net8.0' ))">
|
||||
<Message Text="Copying CPZ"></Message>
|
||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz" />
|
||||
<Copy SourceFiles="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz" DestinationFiles="$(PackageOutputPath)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
|
||||
<PackageReference Include="PepperDashCore" Version="2.0.0-rc.5" />
|
||||
<PackageReference Include="PepperDashCore" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
|
||||
|
||||
@@ -30,6 +30,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
|
||||
<PackageReference Include="PepperDashCore" Version="2.0.0-rc.5" />
|
||||
<PackageReference Include="PepperDashCore" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,31 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using DisplayBase = PepperDash.Essentials.Core.DisplayBase;
|
||||
|
||||
namespace PepperDash.Essentials.Room.MobileControl
|
||||
{
|
||||
public class CoreDisplayBaseMessenger: MessengerBase
|
||||
{
|
||||
private readonly DisplayBase display;
|
||||
|
||||
public CoreDisplayBaseMessenger(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)
|
||||
{
|
||||
Debug.Console(1, "No input named {0} found for device {1}", 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
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)
|
||||
{
|
||||
Debug.Console(1, "No input named {0} found for device {1}", 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
#if SERIES4
|
||||
#endif
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
#if SERIES4
|
||||
#endif
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
#if SERIES4
|
||||
#endif
|
||||
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)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
#if SERIES4
|
||||
#endif
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
#if SERIES4
|
||||
#endif
|
||||
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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
#if SERIES4
|
||||
#endif
|
||||
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)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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;
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
public class CoreTwoWayDisplayBaseMessenger : MessengerBase
|
||||
{
|
||||
private readonly TwoWayDisplayBase _display;
|
||||
|
||||
public CoreTwoWayDisplayBaseMessenger(string key, string messagePath, Device display)
|
||||
: base(key, messagePath, display)
|
||||
{
|
||||
_display = display as TwoWayDisplayBase;
|
||||
}
|
||||
|
||||
#region Overrides of MessengerBase
|
||||
|
||||
public void SendFullStatus()
|
||||
{
|
||||
var messageObj = new TwoWayDisplayBaseStateMessage
|
||||
{
|
||||
//PowerState = _display.PowerIsOnFeedback.BoolValue,
|
||||
CurrentInput = _display.CurrentInputFeedback.StringValue
|
||||
};
|
||||
|
||||
PostStatusMessage(messageObj);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
base.RegisterActions();
|
||||
if (_display == null)
|
||||
{
|
||||
Debug.Console(0, this, $"Unable to register TwoWayDisplayBase messenger {Key}");
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceInfo;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
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
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
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
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
public class GenericMessenger : MessengerBase
|
||||
{
|
||||
public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device)
|
||||
{
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
||||
}
|
||||
|
||||
private void SendFullStatus()
|
||||
{
|
||||
var state = new DeviceStateMessageBase();
|
||||
|
||||
PostStatusMessage(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
public class IDspPresetsMessenger : MessengerBase
|
||||
{
|
||||
private IDspPresets _device;
|
||||
|
||||
public IDspPresetsMessenger(string key, string messagePath, IDspPresets device)
|
||||
: base(key, messagePath, device as Device)
|
||||
{
|
||||
_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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
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)
|
||||
{
|
||||
Debug.Console(0, this, "Error sending full status: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Independentsoft.Exchange;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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();
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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
|
||||
Debug.Console(1, this, "sourceListKey found in 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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
using PepperDash.Essentials.Core.Shades;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Independentsoft.Json.Parser;
|
||||
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; }
|
||||
}
|
||||
|
||||
class SetTechPasswordContent
|
||||
{
|
||||
[JsonProperty("oldPassword")]
|
||||
public string OldPassword { get; set; }
|
||||
|
||||
[JsonProperty("newPassword")]
|
||||
public string NewPassword { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
||||
|
||||
AddAction("/selectScene", (id, content) =>
|
||||
{
|
||||
var s = content.ToObject<LightingScene>();
|
||||
Device.SelectScene(s);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void SendFullStatus()
|
||||
{
|
||||
Debug.Console(2, "LightingBaseMessenger GetFullStatus");
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
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>
|
||||
#if SERIES4
|
||||
public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger
|
||||
#else
|
||||
public abstract class MessengerBase: EssentialsDevice
|
||||
#endif
|
||||
{
|
||||
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>
|
||||
#if SERIES4
|
||||
public IMobileControl AppServerController { get; private set; }
|
||||
#else
|
||||
public MobileControlSystemController AppServerController { get; private set; }
|
||||
#endif
|
||||
|
||||
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>
|
||||
#if SERIES4
|
||||
public void RegisterWithAppServer(IMobileControl appServerController)
|
||||
#else
|
||||
public void RegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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>
|
||||
#if SERIES4
|
||||
protected virtual void RegisterActions()
|
||||
#else
|
||||
protected virtual void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
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; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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)
|
||||
{
|
||||
Debug.Console(0, this, "Exception saving event: {0}\r\n{1}", ex.Message, ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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>
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
//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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
public void CustomUnregsiterWithAppServer(IMobileControl appServerController)
|
||||
#else
|
||||
public void CustomUnregsiterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController controller)
|
||||
#endif
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
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);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
public void CustomUnregsiterWithAppServer(IMobileControl appServerController)
|
||||
#else
|
||||
public void CustomUnregsiterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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>
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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;
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using PepperDash.Essentials.Core.Bridges;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Properties to configure a SIMPL Messenger
|
||||
/// </summary>
|
||||
public class SimplMessengerPropertiesConfig : EiscApiPropertiesConfig.ApiDevicePropertiesConfig
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
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()
|
||||
{
|
||||
Debug.Console(1, "Posting System Monitor Status Message.");
|
||||
|
||||
// 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
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using TwoWayDisplayBase = PepperDash.Essentials.Devices.Common.Displays.TwoWayDisplayBase;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
|
||||
#if SERIES4
|
||||
public class MobileControlMessage : IMobileControlMessage
|
||||
#else
|
||||
public class MobileControlMessage
|
||||
#endif
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("clientId")]
|
||||
public string ClientId { get; set; }
|
||||
|
||||
[JsonProperty("content")]
|
||||
public JToken Content { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer
|
||||
{
|
||||
public class MobileControlSimpleContent<T>
|
||||
{
|
||||
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public T Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectType>ProgramLibrary</ProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>PepperDash.Essentials.AppServer</RootNamespace>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AssemblyTitle>mobile-control-messengers</AssemblyTitle>
|
||||
<Product>mobile-control-messengers</Product>
|
||||
<Copyright>Copyright © 2024</Copyright>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<InformationalVersion>$(Version)</InformationalVersion>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<Authors>PepperDash Technology</Authors>
|
||||
<PackageId>PepperDash.Essentials.Plugin.MobileControl.Messengers</PackageId>
|
||||
<PackageProjectUrl>https://github.com/PepperDash/Essentials</PackageProjectUrl>
|
||||
<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>
|
||||
<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>
|
||||
@@ -0,0 +1,570 @@
|
||||
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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,553 @@
|
||||
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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
16
src/PepperDash.Essentials.MobileControl/Interfaces.cs
Normal file
16
src/PepperDash.Essentials.MobileControl/Interfaces.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace PepperDash.Essentials.Room.MobileControl
|
||||
{
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using PepperDash.Essentials.Core.Web.RequestHandlers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
161
src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs
Normal file
161
src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
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; }
|
||||
|
||||
#if SERIES4
|
||||
[JsonProperty("directServer")]
|
||||
public MobileControlDirectServerPropertiesConfig DirectServer { get; set; }
|
||||
|
||||
[JsonProperty("applicationConfig")]
|
||||
public MobileControlApplicationConfig ApplicationConfig { get; set; }
|
||||
|
||||
[JsonProperty("enableApiServer")]
|
||||
public bool EnableApiServer { get; set; }
|
||||
#endif
|
||||
|
||||
[JsonProperty("roomBridges")]
|
||||
[Obsolete("No longer necessary")]
|
||||
public List<MobileControlRoomBridgePropertiesConfig> RoomBridges { get; set; }
|
||||
|
||||
public MobileControlConfig()
|
||||
{
|
||||
RoomBridges = new List<MobileControlRoomBridgePropertiesConfig>();
|
||||
|
||||
#if SERIES4
|
||||
EnableApiServer = true; // default to true
|
||||
ApplicationConfig = null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Room.MobileControl;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MobileControlSimplFactory : EssentialsDeviceFactory<MobileControlSIMPLRoomBridge>
|
||||
{
|
||||
public MobileControlSimplFactory()
|
||||
{
|
||||
TypeNames = new List<string> { "mobilecontrolbridge-ddvc01", "mobilecontrolbridge-simpl" };
|
||||
}
|
||||
|
||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
var bridge = new MobileControlSIMPLRoomBridge(dc.Key, dc.Name, comm.IpIdInt);
|
||||
|
||||
bridge.AddPreActivationAction(() =>
|
||||
{
|
||||
var parent = GetMobileControlDevice();
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
return;
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
|
||||
/*bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);*/
|
||||
|
||||
parent.AddDeviceMessenger(bridge);
|
||||
});
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
private static MobileControlSystemController GetMobileControlDevice()
|
||||
{
|
||||
var mobileControlList = DeviceManager.AllDevices.OfType<MobileControlSystemController>().ToList();
|
||||
|
||||
if (mobileControlList.Count > 1)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Warning,
|
||||
"Multiple instances of Mobile Control Server found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mobileControlList.Count > 0)
|
||||
{
|
||||
return mobileControlList[0];
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control not enabled for this system");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PepperDash.Essentials.MobileControl
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectType>ProgramLibrary</ProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>PepperDash.Essentials</RootNamespace>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
<Deterministic>false</Deterministic>
|
||||
<AssemblyTitle>epi-essentials-mobile-control</AssemblyTitle>
|
||||
<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>
|
||||
<Version>4.0.0-local</Version>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<InformationalVersion>$(Version)</InformationalVersion>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Authors>PepperDash Technologies</Authors>
|
||||
<PackageId>PepperDash.Essentials.4Series.Plugin.MobileControl</PackageId>
|
||||
<PackageProjectUrl>https://github.com/PepperDash/Essentials</PackageProjectUrl>
|
||||
<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>
|
||||
<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>
|
||||
@@ -0,0 +1,130 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <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()
|
||||
{
|
||||
Debug.Console(1, this, "Server user code changed: {0}", UserCode);
|
||||
|
||||
var qrUrl = string.Format($"{Parent.Host}/api/rooms/{Parent.SystemUuid}/{RoomKey}/qr?x={new Random().Next()}");
|
||||
QrCodeUrl = qrUrl;
|
||||
|
||||
Debug.Console(1, this, "Server user code changed: {0} - {1}", 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,977 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using PepperDash.Essentials.Room.MobileControl;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
using PepperDash.Essentials.Devices.Common.AudioCodec;
|
||||
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using PepperDash.Essentials.Devices.Common.Room;
|
||||
using IShades = PepperDash.Essentials.Core.Shades.IShades;
|
||||
using ShadeBase = PepperDash.Essentials.Devices.Common.Shades.ShadeBase;
|
||||
using PepperDash.Essentials.Devices.Common.TouchPanel;
|
||||
using Crestron.SimplSharp;
|
||||
using Volume = PepperDash.Essentials.Room.MobileControl.Volume;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
using PepperDash.Essentials.Core.Lighting;
|
||||
using PepperDash.Essentials.Core.Shades;
|
||||
using PepperDash.Core.Logging;
|
||||
|
||||
|
||||
|
||||
#if SERIES4
|
||||
using PepperDash.Essentials.AppServer;
|
||||
#endif
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#if SERIES4
|
||||
protected override void RegisterActions()
|
||||
#else
|
||||
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)
|
||||
#endif
|
||||
{
|
||||
// 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 != null ? zrcTp.Key : null;
|
||||
}
|
||||
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 != null ? roomCombiner.Key : null;
|
||||
|
||||
|
||||
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 || dev is Devices.Common.Lighting.LightingBase)
|
||||
{
|
||||
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
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/PepperDash.Essentials.MobileControl/Touchpanel/ITheme.cs
Normal file
17
src/PepperDash.Essentials.MobileControl/Touchpanel/ITheme.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
{
|
||||
public interface ITheme:IKeyed
|
||||
{
|
||||
string Theme { get; }
|
||||
|
||||
void UpdateTheme(string theme);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
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)
|
||||
{
|
||||
Debug.Console(0, this, $"{_device.Key} does not implement ITswAppControl");
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
Debug.Console(0, this, $"{_device.Key} does not implement ITswZoomControl");
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,571 @@
|
||||
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 PepperDash.Essentials.Touchpanel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Feedback = PepperDash.Essentials.Core.Feedback;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.TouchPanel
|
||||
{
|
||||
public class MobileControlTouchpanelProperties : CrestronTouchpanelPropertiesConfig
|
||||
{
|
||||
[JsonProperty("useDirectServer")]
|
||||
public bool UseDirectServer { get; set; } = false;
|
||||
|
||||
[JsonProperty("zoomRoomController")]
|
||||
public bool ZoomRoomController { get; set; } = false;
|
||||
|
||||
[JsonProperty("buttonToolbarTimeoutInS")]
|
||||
public ushort ButtonToolbarTimoutInS { get; set; } = 0;
|
||||
|
||||
[JsonProperty("theme")]
|
||||
public string Theme { get; set; } = "light";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
{
|
||||
public class ThemeMessenger : MessengerBase
|
||||
{
|
||||
private readonly ITheme _tpDevice;
|
||||
|
||||
public ThemeMessenger(string key, string path, ITheme device) : base(key, path, device as Device)
|
||||
{
|
||||
_tpDevice = device;
|
||||
}
|
||||
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
AddAction("/fullStatus", (id, content) =>
|
||||
{
|
||||
PostStatusMessage(new ThemeUpdateMessage { Theme = _tpDevice.Theme });
|
||||
});
|
||||
|
||||
AddAction("/saveTheme", (id, content) =>
|
||||
{
|
||||
var theme = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Setting theme to {theme}", this, theme.Value);
|
||||
_tpDevice.UpdateTheme(theme.Value);
|
||||
|
||||
PostStatusMessage(JToken.FromObject(new {theme = theme.Value}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class ThemeUpdateMessage:DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("theme")]
|
||||
public string Theme { get; set; }
|
||||
}
|
||||
}
|
||||
150
src/PepperDash.Essentials.MobileControl/TransmitMessage.cs
Normal file
150
src/PepperDash.Essentials.MobileControl/TransmitMessage.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using PepperDash.Essentials.Core.Queues;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class TransmitMessage : IQueueMessage
|
||||
{
|
||||
private readonly WebSocket _ws;
|
||||
private readonly object msgToSend;
|
||||
|
||||
public TransmitMessage(object msg, WebSocket ws)
|
||||
{
|
||||
_ws = ws;
|
||||
msgToSend = msg;
|
||||
}
|
||||
|
||||
public TransmitMessage(DeviceStateMessageBase msg, WebSocket ws)
|
||||
{
|
||||
_ws = ws;
|
||||
msgToSend = msg;
|
||||
}
|
||||
|
||||
#region Implementation of IQueueMessage
|
||||
|
||||
public void Dispatch()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
//Debug.Console(2, "Dispatching message type: {0}", msgToSend.GetType());
|
||||
|
||||
//Debug.Console(2, "Message: {0}", msgToSend.ToString());
|
||||
|
||||
//var messageToSend = JObject.FromObject(msgToSend);
|
||||
|
||||
if (_ws != null && _ws.IsAlive)
|
||||
{
|
||||
var message = JsonConvert.SerializeObject(msgToSend, Formatting.None,
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } });
|
||||
|
||||
Debug.Console(2, "Message TX: {0}", message);
|
||||
|
||||
_ws.Send(message);
|
||||
}
|
||||
else if (_ws == null)
|
||||
{
|
||||
Debug.Console(1, "Cannot send. No client.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "Caught an exception in the Transmit Processor {0}\r{1}\r{2}", ex.Message, ex.InnerException, ex.StackTrace);
|
||||
Debug.Console(2, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.StackTrace);
|
||||
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "Inner Exception: {0}", ex.InnerException.Message);
|
||||
Debug.Console(2, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.InnerException.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
#if SERIES4
|
||||
public class MessageToClients : IQueueMessage
|
||||
{
|
||||
private readonly MobileControlWebsocketServer _server;
|
||||
private readonly object msgToSend;
|
||||
|
||||
public MessageToClients(object msg, MobileControlWebsocketServer server)
|
||||
{
|
||||
_server = server;
|
||||
msgToSend = msg;
|
||||
}
|
||||
|
||||
public MessageToClients(DeviceStateMessageBase msg, MobileControlWebsocketServer server)
|
||||
{
|
||||
_server = server;
|
||||
msgToSend = msg;
|
||||
}
|
||||
|
||||
#region Implementation of IQueueMessage
|
||||
|
||||
public void Dispatch()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Debug.Console(2, "Message: {0}", msgToSend.ToString());
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
Debug.Console(2, _server, Debug.ErrorLogLevel.Notice, "Dispatching message type: {0}", msgToSend.GetType());
|
||||
|
||||
var message = JsonConvert.SerializeObject(msgToSend, Formatting.None,
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } });
|
||||
|
||||
var clientSpecificMessage = msgToSend as MobileControlMessage;
|
||||
if (clientSpecificMessage.ClientId != null)
|
||||
{
|
||||
var clientId = clientSpecificMessage.ClientId;
|
||||
|
||||
Debug.Console(2, _server, "Message TX To Client ID: {0} Message: {1}", clientId, message);
|
||||
|
||||
_server.SendMessageToClient(clientId, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.SendMessageToAllClients(message);
|
||||
|
||||
Debug.Console(2, "Message TX To Clients: {0}", message);
|
||||
}
|
||||
}
|
||||
else if (_server == null)
|
||||
{
|
||||
Debug.Console(1, "Cannot send. No server.");
|
||||
}
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
//Swallowing this exception, as it occurs on shutdown and there's no need to print out a scary stack trace
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "Caught an exception in the Transmit Processor {0}", ex.Message);
|
||||
Debug.Console(2, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.StackTrace);
|
||||
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "----\r\n{0}", ex.InnerException.Message);
|
||||
Debug.Console(2, Debug.ErrorLogLevel.Error, "Stack Trace: {0}", ex.InnerException.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer
|
||||
{
|
||||
public class UserCodeChangedContent
|
||||
{
|
||||
[JsonProperty("userCode")]
|
||||
public string UserCode { get; set; }
|
||||
|
||||
[JsonProperty("qrChecksum", NullValueHandling = NullValueHandling.Include)]
|
||||
public string QrChecksum { get; set; }
|
||||
}
|
||||
}
|
||||
76
src/PepperDash.Essentials.MobileControl/Volumes.cs
Normal file
76
src/PepperDash.Essentials.MobileControl/Volumes.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepperDash.Essentials.Room.MobileControl
|
||||
{
|
||||
public class Volumes
|
||||
{
|
||||
[JsonProperty("master", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public Volume Master { get; set; }
|
||||
|
||||
[JsonProperty("auxFaders", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public Dictionary<string, Volume> AuxFaders { get; set; }
|
||||
|
||||
[JsonProperty("numberOfAuxFaders", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int? NumberOfAuxFaders { get; set; }
|
||||
|
||||
public Volumes()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Volume
|
||||
{
|
||||
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Key { get; set; }
|
||||
|
||||
[JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public int? Level { get; set; }
|
||||
|
||||
[JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? Muted { get; set; }
|
||||
|
||||
[JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Label { get; set; }
|
||||
|
||||
[JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? HasMute { get; set; }
|
||||
|
||||
[JsonProperty("hasPrivacyMute", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? HasPrivacyMute { get; set; }
|
||||
|
||||
[JsonProperty("privacyMuted", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? PrivacyMuted { get; set; }
|
||||
|
||||
|
||||
[JsonProperty("muteIcon", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MuteIcon { get; set; }
|
||||
|
||||
public Volume(string key, int level, bool muted, string label, bool hasMute, string muteIcon)
|
||||
: this(key)
|
||||
{
|
||||
Level = level;
|
||||
Muted = muted;
|
||||
Label = label;
|
||||
HasMute = hasMute;
|
||||
MuteIcon = muteIcon;
|
||||
}
|
||||
|
||||
public Volume(string key, int level)
|
||||
: this(key)
|
||||
{
|
||||
Level = level;
|
||||
}
|
||||
|
||||
public Volume(string key, bool muted)
|
||||
: this(key)
|
||||
{
|
||||
Muted = muted;
|
||||
}
|
||||
|
||||
public Volume(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
using PepperDash.Essentials.AppServer.Messengers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PepperDash.Essentials.WebApiHandlers
|
||||
{
|
||||
public class ActionPathsHandler : WebApiBaseRequestHandler
|
||||
{
|
||||
private readonly MobileControlSystemController mcController;
|
||||
public ActionPathsHandler(MobileControlSystemController controller) : base(true)
|
||||
{
|
||||
mcController = controller;
|
||||
}
|
||||
|
||||
protected override void HandleGet(HttpCwsContext context)
|
||||
{
|
||||
var response = JsonConvert.SerializeObject(new ActionPathsResponse(mcController));
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.Headers.Add("Content-Type", "application/json");
|
||||
context.Response.Write(response, false);
|
||||
context.Response.End();
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionPathsResponse
|
||||
{
|
||||
[JsonIgnore]
|
||||
private readonly MobileControlSystemController mcController;
|
||||
|
||||
[JsonProperty("actionPaths")]
|
||||
public List<ActionPath> ActionPaths => mcController.GetActionDictionaryPaths().Select((path) => new ActionPath { MessengerKey = path.Item1, Path = path.Item2}).ToList();
|
||||
|
||||
public ActionPathsResponse(MobileControlSystemController mcController)
|
||||
{
|
||||
this.mcController = mcController;
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionPath
|
||||
{
|
||||
[JsonProperty("messengerKey")]
|
||||
public string MessengerKey { get; set; }
|
||||
|
||||
[JsonProperty("path")]
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
using PepperDash.Essentials.Core.Web;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PepperDash.Essentials.WebApiHandlers
|
||||
{
|
||||
public class MobileAuthRequestHandler : WebApiBaseRequestAsyncHandler
|
||||
{
|
||||
private readonly MobileControlSystemController mcController;
|
||||
|
||||
public MobileAuthRequestHandler(MobileControlSystemController controller) : base(true)
|
||||
{
|
||||
mcController = controller;
|
||||
}
|
||||
|
||||
protected override async Task HandlePost(HttpCwsContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var requestBody = EssentialsWebApiHelpers.GetRequestBody(context.Request);
|
||||
|
||||
var grantCode = JsonConvert.DeserializeObject<AuthorizationRequest>(requestBody);
|
||||
|
||||
if (string.IsNullOrEmpty(grantCode?.GrantCode))
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Missing grant code");
|
||||
context.Response.StatusCode = 400;
|
||||
context.Response.StatusDescription = "Missing grant code";
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
var response = await mcController.ApiService.SendAuthorizationRequest(mcController.Host, grantCode.GrantCode, mcController.SystemUuid);
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, $"response received");
|
||||
if (response.Authorized)
|
||||
{
|
||||
mcController.RegisterSystemToServer();
|
||||
}
|
||||
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
var responseBody = JsonConvert.SerializeObject(response, Formatting.None);
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.Headers.Add("Content-Type", "application/json");
|
||||
context.Response.Write(responseBody, false);
|
||||
context.Response.End();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogMessage(ex, "Exception recieved authorizing system");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PepperDash.Essentials.WebApiHandlers
|
||||
{
|
||||
public class MobileInfoHandler : WebApiBaseRequestHandler
|
||||
{
|
||||
private readonly MobileControlSystemController mcController;
|
||||
public MobileInfoHandler(MobileControlSystemController controller) : base(true)
|
||||
{
|
||||
mcController = controller;
|
||||
}
|
||||
|
||||
protected override void HandleGet(HttpCwsContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = new InformationResponse(mcController);
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.Write(JsonConvert.SerializeObject(response), false);
|
||||
context.Response.End();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Console(1, $"exception showing mobile info: {ex.Message}");
|
||||
Debug.Console(2, $"stack trace: {ex.StackTrace}");
|
||||
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InformationResponse
|
||||
{
|
||||
[JsonIgnore]
|
||||
private readonly MobileControlSystemController mcController;
|
||||
|
||||
[JsonProperty("edgeServer", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public MobileControlEdgeServer EdgeServer => mcController.Config.EnableApiServer ? new MobileControlEdgeServer(mcController) : null;
|
||||
|
||||
|
||||
[JsonProperty("directServer", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public MobileControlDirectServer DirectServer => mcController.Config.DirectServer.EnableDirectServer ? new MobileControlDirectServer(mcController.DirectServer) : null;
|
||||
|
||||
|
||||
public InformationResponse(MobileControlSystemController controller)
|
||||
{
|
||||
mcController = controller;
|
||||
}
|
||||
}
|
||||
|
||||
public class MobileControlEdgeServer
|
||||
{
|
||||
[JsonIgnore]
|
||||
private readonly MobileControlSystemController mcController;
|
||||
|
||||
[JsonProperty("serverAddress")]
|
||||
public string ServerAddress => mcController.Config == null ? "No Config" : mcController.Host;
|
||||
|
||||
[JsonProperty("systemName")]
|
||||
public string SystemName => mcController.RoomBridges.Count > 0 ? mcController.RoomBridges[0].RoomName : "No Config";
|
||||
|
||||
[JsonProperty("systemUrl")]
|
||||
public string SystemUrl => ConfigReader.ConfigObject.SystemUrl;
|
||||
|
||||
[JsonProperty("userCode")]
|
||||
public string UserCode => mcController.RoomBridges.Count > 0 ? mcController.RoomBridges[0].UserCode : "Not available";
|
||||
|
||||
[JsonProperty("connected")]
|
||||
public bool Connected => mcController.Connected;
|
||||
|
||||
[JsonProperty("secondsSinceLastAck")]
|
||||
public int SecondsSinceLastAck => (DateTime.Now - mcController.LastAckMessage).Seconds;
|
||||
|
||||
public MobileControlEdgeServer(MobileControlSystemController controller)
|
||||
{
|
||||
mcController = controller;
|
||||
}
|
||||
}
|
||||
|
||||
public class MobileControlDirectServer
|
||||
{
|
||||
[JsonIgnore]
|
||||
private readonly MobileControlWebsocketServer directServer;
|
||||
|
||||
[JsonProperty("userAppUrl")]
|
||||
public string UserAppUrl => $"{directServer.UserAppUrlPrefix}/[insert_client_token]";
|
||||
|
||||
[JsonProperty("serverPort")]
|
||||
public int ServerPort => directServer.Port;
|
||||
|
||||
[JsonProperty("tokensDefined")]
|
||||
public int TokensDefined => directServer.UiClients.Count;
|
||||
|
||||
[JsonProperty("clientsConnected")]
|
||||
public int ClientsConnected => directServer.ConnectedUiClientsCount;
|
||||
|
||||
[JsonProperty("clients")]
|
||||
public List<MobileControlDirectClient> Clients => directServer.UiClients.Select((c, i) => { return new MobileControlDirectClient(c, i, directServer.UserAppUrlPrefix); }).ToList();
|
||||
|
||||
public MobileControlDirectServer(MobileControlWebsocketServer server)
|
||||
{
|
||||
directServer = server;
|
||||
}
|
||||
}
|
||||
|
||||
public class MobileControlDirectClient
|
||||
{
|
||||
[JsonIgnore]
|
||||
private readonly UiClientContext context;
|
||||
|
||||
[JsonIgnore]
|
||||
private readonly string Key;
|
||||
|
||||
[JsonIgnore]
|
||||
private readonly int clientNumber;
|
||||
|
||||
[JsonIgnore]
|
||||
private readonly string urlPrefix;
|
||||
|
||||
[JsonProperty("clientNumber")]
|
||||
public string ClientNumber => $"{clientNumber}";
|
||||
|
||||
[JsonProperty("roomKey")]
|
||||
public string RoomKey => context.Token.RoomKey;
|
||||
|
||||
[JsonProperty("touchpanelKey")]
|
||||
public string TouchpanelKey => context.Token.TouchpanelKey;
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url => $"{urlPrefix}{Key}";
|
||||
|
||||
[JsonProperty("token")]
|
||||
public string Token => Key;
|
||||
|
||||
[JsonProperty("connected")]
|
||||
public bool Connected => context.Client == null ? false : context.Client.Context.WebSocket.IsAlive;
|
||||
|
||||
[JsonProperty("duration")]
|
||||
public double Duration => context.Client == null ? 0 : context.Client.ConnectedDuration.TotalSeconds;
|
||||
|
||||
public MobileControlDirectClient(KeyValuePair<string, UiClientContext> clientContext, int index, string urlPrefix)
|
||||
{
|
||||
context = clientContext.Value;
|
||||
Key = clientContext.Key;
|
||||
clientNumber = index;
|
||||
this.urlPrefix = urlPrefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
using PepperDash.Essentials.Core.Web;
|
||||
|
||||
namespace PepperDash.Essentials.WebApiHandlers
|
||||
{
|
||||
public class UiClientHandler : WebApiBaseRequestHandler
|
||||
{
|
||||
private readonly MobileControlWebsocketServer server;
|
||||
public UiClientHandler(MobileControlWebsocketServer directServer) : base(true)
|
||||
{
|
||||
server = directServer;
|
||||
}
|
||||
|
||||
protected override void HandlePost(HttpCwsContext context)
|
||||
{
|
||||
var req = context.Request;
|
||||
var res = context.Response;
|
||||
var body = EssentialsWebApiHelpers.GetRequestBody(req);
|
||||
|
||||
var request = JsonConvert.DeserializeObject<ClientRequest>(body);
|
||||
|
||||
var response = new ClientResponse();
|
||||
|
||||
if (string.IsNullOrEmpty(request?.RoomKey))
|
||||
{
|
||||
response.Error = "roomKey is required";
|
||||
|
||||
res.StatusCode = 400;
|
||||
res.ContentType = "application/json";
|
||||
res.Headers.Add("Content-Type", "application/json");
|
||||
res.Write(JsonConvert.SerializeObject(response), false);
|
||||
res.End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.GrantCode))
|
||||
{
|
||||
response.Error = "grantCode is required";
|
||||
|
||||
res.StatusCode = 400;
|
||||
res.ContentType = "application/json";
|
||||
res.Headers.Add("Content-Type", "application/json");
|
||||
res.Write(JsonConvert.SerializeObject(response), false);
|
||||
res.End();
|
||||
return;
|
||||
}
|
||||
|
||||
var (token, path) = server.ValidateGrantCode(request.GrantCode, request.RoomKey);
|
||||
|
||||
response.Token = token;
|
||||
response.Path = path;
|
||||
|
||||
res.StatusCode = 200;
|
||||
res.ContentType = "application/json";
|
||||
res.Headers.Add("Content-Type", "application/json");
|
||||
res.Write(JsonConvert.SerializeObject(response), false);
|
||||
res.End();
|
||||
}
|
||||
|
||||
protected override void HandleDelete(HttpCwsContext context)
|
||||
{
|
||||
var req = context.Request;
|
||||
var res = context.Response;
|
||||
var body = EssentialsWebApiHelpers.GetRequestBody(req);
|
||||
|
||||
var request = JsonConvert.DeserializeObject<ClientRequest>(body);
|
||||
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(request?.Token))
|
||||
{
|
||||
var response = new ClientResponse
|
||||
{
|
||||
Error = "token is required"
|
||||
};
|
||||
|
||||
res.StatusCode = 400;
|
||||
res.ContentType = "application/json";
|
||||
res.Headers.Add("Content-Type", "application/json");
|
||||
res.Write(JsonConvert.SerializeObject(response), false);
|
||||
res.End();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!server.UiClients.TryGetValue(request.Token, out UiClientContext clientContext))
|
||||
{
|
||||
var response = new ClientResponse
|
||||
{
|
||||
Error = $"Unable to find client with token: {request.Token}"
|
||||
};
|
||||
|
||||
res.StatusCode = 200;
|
||||
res.ContentType = "application/json";
|
||||
res.Headers.Add("Content-Type", "application/json");
|
||||
res.Write(JsonConvert.SerializeObject(response), false);
|
||||
res.End();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientContext.Client != null && clientContext.Client.Context.WebSocket.IsAlive)
|
||||
{
|
||||
clientContext.Client.Context.WebSocket.Close(WebSocketSharp.CloseStatusCode.Normal, "Token removed from server");
|
||||
}
|
||||
|
||||
var path = server.WsPath + request.Token;
|
||||
|
||||
if (!server.Server.RemoveWebSocketService(path))
|
||||
{
|
||||
Debug.Console(0, $"Unable to remove client with token {request.Token}");
|
||||
|
||||
var response = new ClientResponse
|
||||
{
|
||||
Error = $"Unable to remove client with token {request.Token}"
|
||||
};
|
||||
|
||||
res.StatusCode = 500;
|
||||
res.ContentType = "application/json";
|
||||
res.Headers.Add("Content-Type", "application/json");
|
||||
res.Write(JsonConvert.SerializeObject(response), false);
|
||||
res.End();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
server.UiClients.Remove(request.Token);
|
||||
|
||||
server.UpdateSecret();
|
||||
|
||||
res.StatusCode = 200;
|
||||
res.End();
|
||||
}
|
||||
}
|
||||
|
||||
public class ClientRequest
|
||||
{
|
||||
[JsonProperty("roomKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string RoomKey { get; set; }
|
||||
|
||||
[JsonProperty("grantCode", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string GrantCode { get; set; }
|
||||
|
||||
[JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Token { get; set; }
|
||||
}
|
||||
|
||||
public class ClientResponse
|
||||
{
|
||||
[JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Error { get; set; }
|
||||
|
||||
[JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Token { get; set; }
|
||||
|
||||
[JsonProperty("path", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
internal class WebSocketServerSecretProvider : CrestronLocalSecretsProvider
|
||||
{
|
||||
public WebSocketServerSecretProvider(string key)
|
||||
: base(key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
|
||||
public class WebSocketServerSecret : ISecret
|
||||
{
|
||||
public ISecretProvider Provider { get; private set; }
|
||||
|
||||
public string Key { get; private set; }
|
||||
|
||||
public object Value { get; private set; }
|
||||
|
||||
public WebSocketServerSecret(string key, object value, ISecretProvider provider)
|
||||
{
|
||||
Key = key;
|
||||
Value = JsonConvert.SerializeObject(value);
|
||||
Provider = provider;
|
||||
}
|
||||
|
||||
public ServerTokenSecrets DeserializeSecret()
|
||||
{
|
||||
return JsonConvert.DeserializeObject<ServerTokenSecrets>(Value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -261,6 +261,7 @@ namespace PepperDash.Essentials
|
||||
_ = new DeviceFactory();
|
||||
|
||||
_ = new ProcessorExtensionDeviceFactory();
|
||||
_ = new MobileControl.MobileControlFactory();
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials load from configuration");
|
||||
|
||||
@@ -469,26 +470,34 @@ namespace PepperDash.Essentials
|
||||
/// Reads all rooms from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadRooms()
|
||||
{
|
||||
{
|
||||
if (ConfigReader.ConfigObject.Rooms == null)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "Notice: Configuration contains no rooms - Is this intentional? This may be a valid configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||
{
|
||||
var room = Core.DeviceFactory.GetDevice(roomConfig);
|
||||
|
||||
DeviceManager.AddDevice(room);
|
||||
if (room is ICustomMobileControl)
|
||||
try
|
||||
{
|
||||
continue;
|
||||
var room = Core.DeviceFactory.GetDevice(roomConfig);
|
||||
|
||||
DeviceManager.AddDevice(room);
|
||||
if (room is ICustomMobileControl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception ex)
|
||||
{
|
||||
Debug.LogMessage(ex, "Exception loading room {roomKey}:{roomType}", null, roomConfig.Key, roomConfig.Type);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Information, "All Rooms Loaded.");
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -49,10 +49,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.21.90" />
|
||||
<PackageReference Include="PepperDashCore" Version="2.0.0-rc.5" />
|
||||
<PackageReference Include="PepperDashCore" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
||||
<ProjectReference Include="..\PepperDash.Essentials.Devices.Common\PepperDash.Essentials.Devices.Common.csproj" />
|
||||
<ProjectReference Include="..\PepperDash.Essentials.MobileControl.Messengers\PepperDash.Essentials.MobileControl.Messengers.csproj" />
|
||||
<ProjectReference Include="..\PepperDash.Essentials.MobileControl\PepperDash.Essentials.MobileControl.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user